summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2006-02-23 22:01:07 -0800
committerCarl Worth <cworth@cworth.org>2006-02-23 22:01:07 -0800
commit1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d (patch)
tree8b12feb1c110aaf21dd76f547c8f049c223b07eb
parent0354956a09cf5a45feed256c1d880bbb9b7c7c42 (diff)
downloadcairo-1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d.tar.gz
cairo_new_sub_path: Making cairo_arc easier to use and more.
This adds a new function which has as its only effect the elimination of the current point. This makes it much easier to use the various cairo_arc calls when the initial line_to is not actually desired. This function also unifies and generalizes the long-existing behavior of cairo_line_to being treated as cairo_move_to when there is no current point. With the addition of cairo_new_sub_path this becomes a documented feature with similar behavior in cairo_curve_to as well.
-rw-r--r--.gitignore1
-rw-r--r--src/cairo-path-stroke.c24
-rw-r--r--src/cairo-path.c40
-rw-r--r--src/cairo-pdf-surface.c48
-rw-r--r--src/cairo-ps-surface.c53
-rw-r--r--src/cairo-svg-surface.c17
-rw-r--r--src/cairo.c60
-rw-r--r--src/cairo.h3
-rw-r--r--src/cairoint.h3
-rw-r--r--test/.gitignore1
-rw-r--r--test/Makefile.am4
-rw-r--r--test/new-sub-path-ref.pngbin0 -> 386 bytes
-rw-r--r--test/new-sub-path-rgb24-ref.pngbin0 -> 355 bytes
-rw-r--r--test/new-sub-path.c79
14 files changed, 209 insertions, 124 deletions
diff --git a/.gitignore b/.gitignore
index aaa9f03b1..73e1e4e75 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ stamp-h
stamp-h1
stamp-h.in
*~
+*.orig
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 96664ceeb..e8170990e 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -47,7 +47,6 @@ typedef struct cairo_stroker {
cairo_pen_t pen;
- cairo_bool_t has_current_point;
cairo_point_t current_point;
cairo_point_t first_point;
@@ -159,7 +158,6 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
stroke_style->line_width / 2.0,
tolerance, ctm);
- stroker->has_current_point = FALSE;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
@@ -607,7 +605,6 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
stroker->first_point = *point;
stroker->current_point = *point;
- stroker->has_current_point = 1;
stroker->has_first_face = 0;
stroker->has_current_face = 0;
@@ -624,9 +621,6 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in cairo_stroker_add_sub_edge and in _compute_face). The
@@ -674,9 +668,6 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
@@ -914,14 +905,12 @@ _cairo_stroker_close_path (void *closure)
cairo_status_t status;
cairo_stroker_t *stroker = closure;
- if (stroker->has_current_point) {
- if (stroker->dashed)
- status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
- else
- status = _cairo_stroker_line_to (stroker, &stroker->first_point);
- if (status)
- return status;
- }
+ if (stroker->dashed)
+ status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
+ else
+ status = _cairo_stroker_line_to (stroker, &stroker->first_point);
+ if (status)
+ return status;
if (stroker->has_first_face && stroker->has_current_face) {
status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
@@ -931,7 +920,6 @@ _cairo_stroker_close_path (void *closure)
stroker->has_first_face = 0;
stroker->has_current_face = 0;
- stroker->has_current_point = 0;
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 669e587ac..7358bee53 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -87,7 +87,7 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->current_point.x = 0;
path->current_point.y = 0;
- path->has_current_point = 0;
+ path->has_current_point = FALSE;
path->last_move_point = path->current_point;
}
@@ -163,7 +163,7 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
}
path->arg_buf_tail = NULL;
- path->has_current_point = 0;
+ path->has_current_point = FALSE;
}
void
@@ -189,12 +189,18 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
return status;
path->current_point = point;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
+void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
+{
+ path->has_current_point = FALSE;
+}
+
cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
@@ -202,7 +208,7 @@ _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
{
cairo_fixed_t x, y;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@@ -222,12 +228,16 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
point.x = x;
point.y = y;
- status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+ if (! path->has_current_point)
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
+ else
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+
if (status)
return status;
path->current_point = point;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -239,7 +249,7 @@ _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
{
cairo_fixed_t x, y;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@@ -261,12 +271,19 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
+ if (! path->has_current_point) {
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
+ &point[0], 1);
+ if (status)
+ return status;
+ }
+
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
path->current_point = point[2];
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -281,7 +298,7 @@ _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x0 = path->current_point.x + dx0;
@@ -304,13 +321,16 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
{
cairo_status_t status;
+ if (! path->has_current_point)
+ return CAIRO_STATUS_SUCCESS;
+
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
if (status)
return status;
path->current_point.x = path->last_move_point.x;
path->current_point.y = path->last_move_point.y;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ee5c482cf..0c024a26b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1263,22 +1263,15 @@ intersect (cairo_line_t *line, cairo_fixed_t y)
_cairo_fixed_to_double (line->p2.y - line->p1.y);
}
-typedef struct
-{
- cairo_output_stream_t *output_stream;
- cairo_bool_t has_current_point;
-} pdf_path_info_t;
-
static cairo_status_t
_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f m ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1286,20 +1279,12 @@ _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
static cairo_status_t
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
- pdf_path_info_t *info = closure;
- const char *pdf_operator;
-
- if (info->has_current_point)
- pdf_operator = "l";
- else
- pdf_operator = "m";
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %s ",
+ _cairo_output_stream_printf (output_stream,
+ "%f %f l ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y),
- pdf_operator);
- info->has_current_point = TRUE;
+ _cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
@@ -1310,9 +1295,9 @@ _cairo_pdf_path_curve_to (void *closure,
cairo_point_t *c,
cairo_point_t *d)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f %f %f %f %f c ",
_cairo_fixed_to_double (b->x),
_cairo_fixed_to_double (b->y),
@@ -1327,11 +1312,10 @@ _cairo_pdf_path_curve_to (void *closure,
static cairo_status_t
_cairo_pdf_path_close_path (void *closure)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"h\r\n");
- info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1349,7 +1333,6 @@ _cairo_pdf_surface_fill (void *abstract_surface,
cairo_pdf_document_t *document = surface->document;
const char *pdf_operator;
cairo_status_t status;
- pdf_path_info_t info;
status = emit_pattern (surface, pattern);
if (status)
@@ -1360,16 +1343,13 @@ _cairo_pdf_surface_fill (void *abstract_surface,
assert (document->current_stream != NULL &&
document->current_stream == surface->current_stream);
- info.output_stream = document->output_stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
- &info);
+ document->output_stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1600,7 +1580,6 @@ _cairo_pdf_surface_intersect_clip_path (void *dst,
cairo_pdf_document_t *document = surface->document;
cairo_output_stream_t *output = document->output_stream;
cairo_status_t status;
- pdf_path_info_t info;
const char *pdf_operator;
_cairo_pdf_surface_ensure_stream (surface);
@@ -1617,16 +1596,13 @@ _cairo_pdf_surface_intersect_clip_path (void *dst,
surface->has_clip = TRUE;
}
- info.output_stream = document->output_stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
- &info);
+ document->output_stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6cf862170..37053e965 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1049,22 +1049,16 @@ _cairo_ps_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_STATUS_SUCCESS;
}
-typedef struct
-{
- cairo_output_stream_t *output_stream;
- cairo_bool_t has_current_point;
-} cairo_ps_surface_path_info_t;
static cairo_status_t
_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f moveto ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1072,33 +1066,25 @@ _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
static cairo_status_t
_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
{
- cairo_ps_surface_path_info_t *info = closure;
- const char *ps_operator;
+ cairo_output_stream_t *output_stream = closure;
- if (info->has_current_point)
- ps_operator = "lineto";
- else
- ps_operator = "moveto";
-
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %s ",
+ _cairo_output_stream_printf (output_stream,
+ "%f %f lineto ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y),
- ps_operator);
- info->has_current_point = TRUE;
+ _cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_surface_path_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f %f %f %f %f curveto ",
_cairo_fixed_to_double (b->x),
_cairo_fixed_to_double (b->y),
@@ -1113,11 +1099,10 @@ _cairo_ps_surface_path_curve_to (void *closure,
static cairo_status_t
_cairo_ps_surface_path_close_path (void *closure)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"closepath\n");
- info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1132,7 +1117,6 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
_cairo_output_stream_printf (stream,
@@ -1143,16 +1127,13 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_ps_surface_path_move_to,
_cairo_ps_surface_path_line_to,
_cairo_ps_surface_path_curve_to,
_cairo_ps_surface_path_close_path,
- &info);
+ stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1276,7 +1257,6 @@ _cairo_ps_surface_fill (void *abstract_surface,
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_int_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
if (pattern_operation_needs_fallback (op, source))
@@ -1293,16 +1273,13 @@ _cairo_ps_surface_fill (void *abstract_surface,
emit_pattern (surface, source);
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_ps_surface_path_move_to,
_cairo_ps_surface_path_line_to,
_cairo_ps_surface_path_curve_to,
_cairo_ps_surface_path_close_path,
- &info);
+ stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5a2c92fff..929700569 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -783,7 +783,6 @@ emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
typedef struct
{
cairo_svg_document_t *document;
- cairo_bool_t has_current_point;
xmlBufferPtr path;
} svg_path_info_t;
@@ -801,7 +800,6 @@ _cairo_svg_path_move_to (void *closure, cairo_point_t *point)
_cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->y));
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -813,10 +811,7 @@ _cairo_svg_path_line_to (void *closure, cairo_point_t *point)
xmlBufferPtr path = info->path;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
- if (info->has_current_point)
- xmlBufferCat (path, CC2XML ("L "));
- else
- xmlBufferCat (path, CC2XML ("M "));
+ xmlBufferCat (path, CC2XML ("L "));
_cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->x));
xmlBufferCat (path, CC2XML (buffer));
@@ -825,8 +820,6 @@ _cairo_svg_path_line_to (void *closure, cairo_point_t *point)
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- info->has_current_point = TRUE;
-
return CAIRO_STATUS_SUCCESS;
}
@@ -868,10 +861,7 @@ _cairo_svg_path_close_path (void *closure)
{
svg_path_info_t *info = closure;
- if (info->has_current_point)
- xmlBufferCat (info->path, CC2XML ("Z "));
-
- info->has_current_point = FALSE;
+ xmlBufferCat (info->path, CC2XML ("Z "));
return CAIRO_STATUS_SUCCESS;
}
@@ -893,7 +883,6 @@ _cairo_svg_surface_fill (void *abstract_surface,
xmlBufferPtr style;
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
style = xmlBufferCreate ();
@@ -1035,7 +1024,6 @@ _cairo_svg_surface_stroke (void *abstract_dst,
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
rx = ry = stroke_style->line_width;
@@ -1176,7 +1164,6 @@ _cairo_svg_surface_intersect_clip_path (void *dst,
if (path != NULL) {
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
group = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
diff --git a/src/cairo.c b/src/cairo.c
index 96cd504b7..6a94d0fac 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -957,8 +957,8 @@ cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
* cairo_new_path:
* @cr: a cairo context
*
- * Clears the current path. After this call there will be no current
- * point.
+ * Clears the current path. After this call there will be no path and
+ * no current point.
**/
void
cairo_new_path (cairo_t *cr)
@@ -976,8 +976,8 @@ slim_hidden_def(cairo_new_path);
* @x: the X coordinate of the new position
* @y: the Y coordinate of the new position
*
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will be (@x, @y).
+ * Begin a new subpath. After this call the current point will be (@x,
+ * @y).
**/
void
cairo_move_to (cairo_t *cr, double x, double y)
@@ -998,6 +998,31 @@ cairo_move_to (cairo_t *cr, double x, double y)
slim_hidden_def(cairo_move_to);
/**
+ * cairo_new_sub_path:
+ * @cr: a cairo context
+ *
+ * Begin a new subpath. Note that the existing path is not
+ * affected. After this call there will be no current point.
+ *
+ * In many cases, this call is not needed since new subpaths are
+ * frequently started with cairo_move_to().
+ *
+ * A call to cairo_new_sub_path() is particularly useful when
+ * beginning a new subpath with one of the cairo_arc() calls. This
+ * makes things easier as it is no longer necessary to manually
+ * compute the arc's initial coordinates for a call to
+ * cairo_move_to().
+ **/
+void
+cairo_new_sub_path (cairo_t *cr)
+{
+ if (cr->status)
+ return;
+
+ _cairo_path_fixed_new_sub_path (&cr->path);
+}
+
+/**
* cairo_line_to:
* @cr: a cairo context
* @x: the X coordinate of the end of the new line
@@ -1006,6 +1031,9 @@ slim_hidden_def(cairo_move_to);
* Adds a line to the path from the current point to position (@x, @y)
* in user-space coordinates. After this call the current point
* will be (@x, @y).
+ *
+ * If there is no current point before the call to cairo_line_to()
+ * this function will behave as cairo_move_to (@cr, @x, @y).
**/
void
cairo_line_to (cairo_t *cr, double x, double y)
@@ -1038,6 +1066,10 @@ cairo_line_to (cairo_t *cr, double x, double y)
* position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and
* (@x2, @y2) as the control points. After this call the current point
* will be (@x3, @y3).
+ *
+ * If there is no current point before the call to cairo_curve_to()
+ * this function will behave as if preceded by a call to
+ * cairo_move_to (@cr, @x1, @y1).
**/
void
cairo_curve_to (cairo_t *cr,
@@ -1208,11 +1240,15 @@ cairo_arc_to (cairo_t *cr,
* @dx: the X offset
* @dy: the Y offset
*
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will offset by (@x, @y).
+ * Begin a new subpath. After this call the current point will offset
+ * by (@x, @y).
*
* Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy)
* is logically equivalent to cairo_move_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_move_to (cairo_t *cr, double dx, double dy)
@@ -1244,6 +1280,10 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
*
* Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy)
* is logically equivalent to cairo_line_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
@@ -1284,6 +1324,10 @@ slim_hidden_def(cairo_rel_line_to);
* @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to
* cairo_curve_to (@cr, x + @dx1, y + @dy1, x + @dx2, y + @dy2, x +
* @dx3, y + @dy3).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_curve_to (cairo_t *cr,
@@ -1378,8 +1422,10 @@ cairo_stroke_to_path (cairo_t *cr)
* The behavior of cairo_close_path() is distinct from simply calling
* cairo_line_to() with the equivalent coordinate in the case of
* stroking. When a closed subpath is stroked, there are no caps on
- * the ends of the subpath. Instead, their is a line join connecting
+ * the ends of the subpath. Instead, there is a line join connecting
* the final and initial segments of the subpath.
+ *
+ * If there is no current point, this function will have no effect.
**/
void
cairo_close_path (cairo_t *cr)
diff --git a/src/cairo.h b/src/cairo.h
index fbb362088..6dd274267 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -436,6 +436,9 @@ cairo_public void
cairo_move_to (cairo_t *cr, double x, double y);
cairo_public void
+cairo_new_sub_path (cairo_t *cr);
+
+cairo_public void
cairo_line_to (cairo_t *cr, double x, double y);
cairo_public void
diff --git a/src/cairoint.h b/src/cairoint.h
index 88fccae11..d51b994cf 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1394,6 +1394,9 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y);
+cairo_private void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path);
+
cairo_private cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
diff --git a/test/.gitignore b/test/.gitignore
index 5173349b2..1a1212224 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -37,6 +37,7 @@ move-to-show-surface
multi-page
multi-page.pdf
multi-page.ps
+new-sub-path
nil-surface
operator-clear
operator-source
diff --git a/test/Makefile.am b/test/Makefile.am
index 0da8b5a74..0ea0624aa 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -29,6 +29,7 @@ mask \
mask-ctm \
mask-surface-ctm \
move-to-show-surface \
+new-sub-path \
nil-surface \
operator-clear \
operator-source \
@@ -143,6 +144,8 @@ mask-surface-ctm-ref.png \
mask-surface-ctm-rgb24-ref.png \
move-to-show-surface-ref.png \
move-to-show-surface-rgb24-ref.png \
+new-sub-path-ref.png \
+new-sub-path-rgb24-ref.png \
nil-surface-ref.png \
nil-surface-rgb24-ref.png \
operator-clear-ref.png \
@@ -311,6 +314,7 @@ mask_ctm_LDADD = $(LDADDS)
mask_surface_ctm_LDADD = $(LDADDS)
multi_page_LDADD = $(LDADDS)
move_to_show_surface_LDADD = $(LDADDS)
+new_sub_path_LDADD = $(LDADDS)
nil_surface_LDADD = $(LDADDS)
operator_clear_LDADD = $(LDADDS)
operator_source_LDADD = $(LDADDS)
diff --git a/test/new-sub-path-ref.png b/test/new-sub-path-ref.png
new file mode 100644
index 000000000..7319ab3fc
--- /dev/null
+++ b/test/new-sub-path-ref.png
Binary files differ
diff --git a/test/new-sub-path-rgb24-ref.png b/test/new-sub-path-rgb24-ref.png
new file mode 100644
index 000000000..8cbc73161
--- /dev/null
+++ b/test/new-sub-path-rgb24-ref.png
Binary files differ
diff --git a/test/new-sub-path.c b/test/new-sub-path.c
new file mode 100644
index 000000000..90e0c7308
--- /dev/null
+++ b/test/new-sub-path.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth@cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#define SIZE 10
+
+cairo_test_t test = {
+ "new-sub-path",
+ "Test the cairo_new_sub_path call",
+ 8 * SIZE,
+ 3 * SIZE
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
+
+ /* Test cairo_new_sub_path followed by several different
+ * path-modification functions in turn...
+ */
+
+ /* ... cairo_move_to */
+ cairo_new_sub_path (cr);
+ cairo_move_to (cr, SIZE, SIZE);
+ cairo_line_to (cr, SIZE, 2 * SIZE);
+
+ /* ... cairo_line_to */
+ cairo_new_sub_path (cr);
+ cairo_line_to (cr, 2 * SIZE, 1.5 * SIZE);
+ cairo_line_to (cr, 3 * SIZE, 1.5 * SIZE);
+
+ /* ... cairo_curve_to */
+ cairo_new_sub_path (cr);
+ cairo_curve_to (cr,
+ 4.0 * SIZE, 1.5 * SIZE,
+ 4.5 * SIZE, 1.0 * SIZE,
+ 5.0 * SIZE, 1.5 * SIZE);
+
+ /* ... cairo_arc */
+ cairo_new_sub_path (cr);
+ cairo_arc (cr,
+ 6.5 * SIZE, 1.5 * SIZE,
+ 0.5 * SIZE,
+ 0.0, 2.0 * M_PI);
+
+ cairo_stroke (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}