summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--src/cairo-path-fill.c101
-rw-r--r--src/cairo-path-stroke.c253
-rw-r--r--src/cairo-path.c56
-rw-r--r--src/cairo-pen.c2
-rw-r--r--src/cairo-polygon.c56
-rw-r--r--src/cairo_path.c56
-rw-r--r--src/cairo_path_fill.c101
-rw-r--r--src/cairo_path_stroke.c253
-rw-r--r--src/cairo_pen.c2
-rw-r--r--src/cairo_polygon.c56
-rw-r--r--src/cairoint.h22
12 files changed, 554 insertions, 420 deletions
diff --git a/ChangeLog b/ChangeLog
index de8e6457..6b057825 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
2003-12-08 Carl Worth <cworth@isi.edu>
+ * src/cairoint.h:
+ * src/cairo_path_stroke.c:
+ * src/cairo_path_fill.c:
+ * src/cairo_path.c: Clean up cairo_path_callbacks to have move_to,
+ line_to, curve_to, abd close_path instead of add_edge, add_spline,
+ and done_sub_path. Much, much nicer.
+
+ * src/cairo_polygon.c (_cairo_polygon_move_to): Provide
+ cairo_polygon_move_to and cairo_polygon_line_to instead of
+ cairo_polygon_add_point.
+
+ * src/cairo_pen.c (_cairo_pen_stroke_spline_half): Track change in
+ cairo_polygon interface.
+
+2003-12-08 Carl Worth <cworth@isi.edu>
+
* configure.in: Bump version to 0.1.16 since it actually has a
hope of building, (due to fix for broken cairo-xlib.h includes).
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index 8f34af85..74a019d6 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -31,6 +31,8 @@ typedef struct cairo_filler {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
+ cairo_point_t current_point;
+
cairo_polygon_t polygon;
} cairo_filler_t;
@@ -41,15 +43,19 @@ static void
_cairo_filler_fini (cairo_filler_t *filler);
static cairo_status_t
-_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_filler_move_to (void *closure, cairo_point_t *point);
+
+static cairo_status_t
+_cairo_filler_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_filler_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d);
+_cairo_filler_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d);
static cairo_status_t
-_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
+_cairo_filler_close_path (void *closure);
static cairo_status_t
_cairo_filler_done_path (void *closure);
@@ -60,6 +66,9 @@ _cairo_filler_init (cairo_filler_t *filler, cairo_gstate_t *gstate, cairo_traps_
filler->gstate = gstate;
filler->traps = traps;
+ filler->current_point.x = 0;
+ filler->current_point.y = 0;
+
_cairo_polygon_init (&filler->polygon);
}
@@ -70,18 +79,46 @@ _cairo_filler_fini (cairo_filler_t *filler)
}
static cairo_status_t
-_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_filler_move_to (void *closure, cairo_point_t *point)
{
+ cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
- return _cairo_polygon_add_edge (polygon, p1, p2);
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
+
+ status = _cairo_polygon_move_to (polygon, point);
+ if (status)
+ return status;
+
+ filler->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_filler_line_to (void *closure, cairo_point_t *point)
+{
+ cairo_status_t status;
+ cairo_filler_t *filler = closure;
+ cairo_polygon_t *polygon = &filler->polygon;
+
+ status = _cairo_polygon_line_to (polygon, point);
+ if (status)
+ return status;
+
+ filler->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_filler_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d)
+_cairo_filler_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -90,7 +127,8 @@ _cairo_filler_add_spline (void *closure,
cairo_gstate_t *gstate = filler->gstate;
cairo_spline_t spline;
- status = _cairo_spline_init (&spline, a, b, c, d);
+ status = _cairo_spline_init (&spline, &filler->current_point, b, c, d);
+
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
@@ -98,47 +136,62 @@ _cairo_filler_add_spline (void *closure,
if (status)
goto CLEANUP_SPLINE;
- for (i = 0; i < spline.num_points - 1; i++) {
- status = _cairo_polygon_add_edge (polygon, &spline.points[i], &spline.points[i+1]);
+ for (i = 1; i < spline.num_points; i++) {
+ status = _cairo_polygon_line_to (polygon, &spline.points[i]);
if (status)
- goto CLEANUP_SPLINE;
+ break;
}
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
+ filler->current_point = *d;
+
return status;
}
static cairo_status_t
-_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done)
+_cairo_filler_close_path (void *closure)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
- _cairo_polygon_close (polygon);
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_filler_done_path (void *closure)
{
+ cairo_status_t status;
cairo_filler_t *filler = closure;
+ cairo_polygon_t *polygon = &filler->polygon;
+
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
- return _cairo_traps_tessellate_polygon (filler->traps,
- &filler->polygon,
- filler->gstate->fill_rule);
+ status = _cairo_traps_tessellate_polygon (filler->traps,
+ &filler->polygon,
+ filler->gstate->fill_rule);
+ if (status)
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_path_fill_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
{
static const cairo_path_callbacks_t filler_callbacks = {
- _cairo_filler_add_edge,
- _cairo_filler_add_spline,
- _cairo_filler_done_sub_path,
+ _cairo_filler_move_to,
+ _cairo_filler_line_to,
+ _cairo_filler_curve_to,
+ _cairo_filler_close_path,
_cairo_filler_done_path
};
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 35e7b1b7..2bc271de 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -31,11 +31,17 @@ typedef struct cairo_stroker {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
- int have_prev;
- int have_first;
- int is_first;
- cairo_stroke_face_t prev;
- cairo_stroke_face_t first;
+ int has_current_point;
+ cairo_point_t current_point;
+ cairo_point_t first_point;
+
+ int has_current_face;
+ cairo_stroke_face_t current_face;
+
+ int has_first_face;
+ cairo_stroke_face_t first_face;
+
+ int dashed;
int dash_index;
int dash_on;
double dash_remain;
@@ -49,18 +55,22 @@ static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
static cairo_status_t
-_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_stroker_move_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_stroker_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d);
+_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done);
+_cairo_stroker_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d);
+
+static cairo_status_t
+_cairo_stroker_close_path (void *closure);
static cairo_status_t
_cairo_stroker_done_path (void *closure);
@@ -89,6 +99,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
if (++i == gstate->num_dashes)
i = 0;
}
+ stroker->dashed = 1;
stroker->dash_index = i;
stroker->dash_on = on;
stroker->dash_remain = gstate->dash[i] - offset;
@@ -113,11 +124,15 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra
{
stroker->gstate = gstate;
stroker->traps = traps;
- stroker->have_prev = 0;
- stroker->have_first = 0;
- stroker->is_first = 1;
+
+ stroker->has_current_point = 0;
+ stroker->has_current_face = 0;
+ stroker->has_first_face = 0;
+
if (gstate->dash)
_cairo_stroker_start_dash (stroker);
+ else
+ stroker->dashed = 0;
}
static void
@@ -286,10 +301,11 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
outer.x = _cairo_fixed_from_double (mx);
outer.y = _cairo_fixed_from_double (my);
_cairo_polygon_init (&polygon);
- _cairo_polygon_add_edge (&polygon, &in->point, inpt);
- _cairo_polygon_add_edge (&polygon, inpt, &outer);
- _cairo_polygon_add_edge (&polygon, &outer, outpt);
- _cairo_polygon_add_edge (&polygon, outpt, &in->point);
+ _cairo_polygon_move_to (&polygon, &in->point);
+ _cairo_polygon_line_to (&polygon, inpt);
+ _cairo_polygon_line_to (&polygon, &outer);
+ _cairo_polygon_line_to (&polygon, outpt);
+ _cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps,
&polygon,
CAIRO_FILL_RULE_WINDING);
@@ -351,8 +367,6 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
cairo_point_t occw, ocw;
cairo_polygon_t polygon;
- _cairo_polygon_init (&polygon);
-
dx = f->usr_vector.x;
dy = f->usr_vector.y;
dx *= gstate->line_width / 2.0;
@@ -365,10 +379,12 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
ocw.x = f->cw.x + fvector.dx;
ocw.y = f->cw.y + fvector.dy;
- _cairo_polygon_add_edge (&polygon, &f->cw, &ocw);
- _cairo_polygon_add_edge (&polygon, &ocw, &occw);
- _cairo_polygon_add_edge (&polygon, &occw, &f->ccw);
- _cairo_polygon_add_edge (&polygon, &f->ccw, &f->cw);
+ _cairo_polygon_init (&polygon);
+ _cairo_polygon_move_to (&polygon, &f->cw);
+ _cairo_polygon_line_to (&polygon, &ocw);
+ _cairo_polygon_line_to (&polygon, &occw);
+ _cairo_polygon_line_to (&polygon, &f->ccw);
+ _cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
@@ -482,11 +498,31 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
}
static cairo_status_t
-_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_stroker_move_to (void *closure, cairo_point_t *point)
+{
+ cairo_stroker_t *stroker = closure;
+
+ stroker->first_point = *point;
+ stroker->current_point = *point;
+ stroker->has_current_point = 1;
+
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_stroker_line_to (void *closure, cairo_point_t *point)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
cairo_stroke_face_t start, end;
+ 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
@@ -500,19 +536,20 @@ _cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
if (status)
return status;
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
if (status)
return status;
} else {
- stroker->have_prev = 1;
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = start;
+ stroker->has_first_face = 1;
}
}
- stroker->prev = end;
- stroker->is_first = 0;
+ stroker->current_face = end;
+ stroker->has_current_face = 1;
+
+ stroker->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
@@ -521,7 +558,7 @@ _cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
* Dashed lines. Cap each dash end, join around turns when on
*/
static cairo_status_t
-_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@@ -532,6 +569,11 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
cairo_point_t fd1, fd2;
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
+ 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);
@@ -569,18 +611,18 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
return status;
} else {
/*
- * First in this segment, join to any prev, else
+ * First in this segment, join to any current_face, else
* if at start of sub-path, mark position, else
* cap
*/
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &sub_start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
if (status)
return status;
} else {
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = sub_start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = sub_start;
+ stroker->has_first_face = 1;
} else {
status = _cairo_stroker_cap (stroker, &sub_start);
if (status)
@@ -600,8 +642,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
* Mark previous line face and fix up next time
* through
*/
- stroker->prev = sub_end;
- stroker->have_prev = 1;
+ stroker->current_face = sub_end;
+ stroker->has_current_face = 1;
}
} else {
/*
@@ -609,27 +651,30 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
* and cap if necessary
*/
if (first) {
- if (stroker->have_prev) {
- status = _cairo_stroker_cap (stroker, &stroker->prev);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_cap (stroker, &stroker->current_face);
if (status)
return status;
}
}
if (!remain)
- stroker->have_prev = 0;
+ stroker->has_current_face = 0;
}
_cairo_stroker_step_dash (stroker, tmp);
fd1 = fd2;
first = 0;
}
- stroker->is_first = 0;
+
+ stroker->current_point = *point;
+
return status;
}
static cairo_status_t
-_cairo_stroker_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d)
+_cairo_stroker_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@@ -638,6 +683,7 @@ _cairo_stroker_add_spline (void *closure,
cairo_pen_t pen;
cairo_stroke_face_t start, end;
cairo_point_t extra_points[4];
+ cairo_point_t *a = &stroker->current_point;
status = _cairo_spline_init (&spline, a, b, c, d);
if (status == CAIRO_INT_STATUS_DEGENERATE)
@@ -650,19 +696,18 @@ _cairo_stroker_add_spline (void *closure,
_compute_face (a, &spline.initial_slope, gstate, &start);
_compute_face (d, &spline.final_slope, gstate, &end);
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
if (status)
return status;
} else {
- stroker->have_prev = 1;
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = start;
+ stroker->has_first_face = 1;
}
}
- stroker->prev = end;
- stroker->is_first = 0;
+ stroker->current_face = end;
+ stroker->has_current_face = 1;
extra_points[0] = start.cw;
extra_points[0].x -= start.point.x;
@@ -690,50 +735,35 @@ _cairo_stroker_add_spline (void *closure,
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
+ stroker->current_point = *d;
+
return status;
}
static cairo_status_t
-_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
+_cairo_stroker_close_path (void *closure)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
- switch (done) {
- case CAIRO_SUB_PATH_DONE_JOIN:
- if (stroker->have_first && stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &stroker->first);
- if (status)
- return status;
- break;
- }
- /* fall through... */
- case CAIRO_SUB_PATH_DONE_CAP:
- if (stroker->have_first) {
- cairo_point_t t;
- /* The initial cap needs an outward facing vector. Reverse everything */
- stroker->first.usr_vector.x = -stroker->first.usr_vector.x;
- stroker->first.usr_vector.y = -stroker->first.usr_vector.y;
- stroker->first.dev_vector.dx = -stroker->first.dev_vector.dx;
- stroker->first.dev_vector.dy = -stroker->first.dev_vector.dy;
- t = stroker->first.cw;
- stroker->first.cw = stroker->first.ccw;
- stroker->first.ccw = t;
- status = _cairo_stroker_cap (stroker, &stroker->first);
- if (status)
- return status;
- }
- if (stroker->have_prev) {
- status = _cairo_stroker_cap (stroker, &stroker->prev);
- if (status)
- return status;
- }
- break;
+ 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->has_first_face && stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
+ if (status)
+ return status;
}
- stroker->have_prev = 0;
- stroker->have_first = 0;
- stroker->is_first = 1;
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+ stroker->has_current_point = 0;
return CAIRO_STATUS_SUCCESS;
}
@@ -741,6 +771,33 @@ _cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
static cairo_status_t
_cairo_stroker_done_path (void *closure)
{
+ cairo_status_t status;
+ cairo_stroker_t *stroker = closure;
+
+ if (stroker->has_first_face) {
+ cairo_point_t t;
+ /* The initial cap needs an outward facing vector. Reverse everything */
+ stroker->first_face.usr_vector.x = -stroker->first_face.usr_vector.x;
+ stroker->first_face.usr_vector.y = -stroker->first_face.usr_vector.y;
+ stroker->first_face.dev_vector.dx = -stroker->first_face.dev_vector.dx;
+ stroker->first_face.dev_vector.dy = -stroker->first_face.dev_vector.dy;
+ t = stroker->first_face.cw;
+ stroker->first_face.cw = stroker->first_face.ccw;
+ stroker->first_face.ccw = t;
+ status = _cairo_stroker_cap (stroker, &stroker->first_face);
+ if (status)
+ return status;
+ }
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_cap (stroker, &stroker->current_face);
+ if (status)
+ return status;
+ }
+
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+ stroker->has_current_point = 0;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -748,15 +805,17 @@ cairo_status_t
_cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
{
static const cairo_path_callbacks_t stroker_solid_cb = {
- _cairo_stroker_add_edge,
- _cairo_stroker_add_spline,
- _cairo_stroker_done_sub_path,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
_cairo_stroker_done_path
};
static const cairo_path_callbacks_t stroker_dashed_cb = {
- _cairo_stroker_add_edge_dashed,
- _cairo_stroker_add_spline,
- _cairo_stroker_done_sub_path,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to_dashed,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
_cairo_stroker_done_path
};
const cairo_path_callbacks_t *callbacks = gstate->dash ? &stroker_dashed_cb : &stroker_solid_cb;
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 9366394d..10e14319 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -329,10 +329,6 @@ _cairo_path_interpret (cairo_path_t *path, cairo_direction_t dir, const cairo_pa
cairo_path_arg_buf_t *arg_buf = path->arg_head;
int buf_i = 0;
cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
- cairo_point_t current = {0, 0};
- cairo_point_t first = {0, 0};
- int has_current = 0;
- int has_edge = 0;
int step = (dir == CAIRO_DIRECTION_FORWARD) ? 1 : -1;
for (op_buf = (dir == CAIRO_DIRECTION_FORWARD) ? path->op_head : path->op_tail;
@@ -374,61 +370,23 @@ _cairo_path_interpret (cairo_path_t *path, cairo_direction_t dir, const cairo_pa
switch (op) {
case CAIRO_PATH_OP_MOVE_TO:
- if (has_edge) {
- status = (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_CAP);
- if (status)
- return status;
- }
- first = point[0];
- current = point[0];
- has_current = 1;
- has_edge = 0;
+ status = (*cb->move_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_LINE_TO:
- if (has_current) {
- status = (*cb->add_edge) (closure, &current, &point[0]);
- if (status)
- return status;
- current = point[0];
- has_edge = 1;
- } else {
- first = point[0];
- current = point[0];
- has_current = 1;
- has_edge = 0;
- }
+ status = (*cb->line_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_CURVE_TO:
- if (has_current) {
- status = (*cb->add_spline) (closure, &current, &point[0], &point[1], &point[2]);
- if (status)
- return status;
- current = point[2];
- has_edge = 1;
- } else {
- first = point[2];
- current = point[2];
- has_current = 1;
- has_edge = 0;
- }
+ status = (*cb->curve_to) (closure, &point[0], &point[1], &point[2]);
break;
case CAIRO_PATH_OP_CLOSE_PATH:
- if (has_edge) {
- (*cb->add_edge) (closure, &current, &first);
- (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_JOIN);
- }
- current.x = 0;
- current.y = 0;
- first.x = 0;
- first.y = 0;
- has_current = 0;
- has_edge = 0;
+ default:
+ status = (*cb->close_path) (closure);
break;
}
+ if (status)
+ return status;
}
}
- if (has_edge)
- (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_CAP);
return (*cb->done_path) (closure);
}
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index dd054372..0bb5debd 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -288,7 +288,7 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
while (i != stop) {
hull_point.x = point[i].x + pen->vertices[active].point.x;
hull_point.y = point[i].y + pen->vertices[active].point.y;
- status = _cairo_polygon_add_point (polygon, &hull_point);
+ status = _cairo_polygon_line_to (polygon, &hull_point);
if (status)
return status;
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index 97f074a3..fbda7321 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -35,9 +35,6 @@
static cairo_status_t
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
-static void
-_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *point);
-
void
_cairo_polygon_init (cairo_polygon_t *polygon)
{
@@ -46,10 +43,7 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
polygon->edges_size = 0;
polygon->edges = NULL;
- polygon->first_point_defined = 0;
- polygon->last_point_defined = 0;
-
- polygon->closed = 0;
+ polygon->has_current_point = 0;
}
void
@@ -62,10 +56,7 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
polygon->num_edges = 0;
}
- polygon->first_point_defined = 0;
- polygon->last_point_defined = 0;
-
- polygon->closed = 0;
+ polygon->has_current_point = 0;
}
static cairo_status_t
@@ -92,25 +83,12 @@ _cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
return CAIRO_STATUS_SUCCESS;
}
-static void
-_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *point)
-{
- polygon->last_point = *point;
- polygon->last_point_defined = 1;
-}
-
cairo_status_t
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_edge_t *edge;
- if (! polygon->first_point_defined) {
- polygon->first_point = *p1;
- polygon->first_point_defined = 1;
- polygon->closed = 0;
- }
-
/* drop horizontal edges */
if (p1->y == p2->y) {
goto DONE;
@@ -137,20 +115,31 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
polygon->num_edges++;
DONE:
- _cairo_polygon_set_last_point (polygon, p2);
+ _cairo_polygon_move_to (polygon, p2);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
+{
+ if (! polygon->has_current_point)
+ polygon->first_point = *point;
+ polygon->current_point = *point;
+ polygon->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *point)
+_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- if (polygon->last_point_defined) {
- status = _cairo_polygon_add_edge (polygon, &polygon->last_point, point);
+ if (polygon->has_current_point) {
+ status = _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
} else {
- _cairo_polygon_set_last_point (polygon, point);
+ _cairo_polygon_move_to (polygon, point);
}
return status;
@@ -161,13 +150,14 @@ _cairo_polygon_close (cairo_polygon_t *polygon)
{
cairo_status_t status;
- if (polygon->closed == 0 && polygon->last_point_defined) {
- status = _cairo_polygon_add_edge (polygon, &polygon->last_point, &polygon->first_point);
+ if (polygon->has_current_point) {
+ status = _cairo_polygon_add_edge (polygon,
+ &polygon->current_point,
+ &polygon->first_point);
if (status)
return status;
- polygon->closed = 1;
- polygon->first_point_defined = 0;
+ polygon->has_current_point = 0;
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo_path.c b/src/cairo_path.c
index 9366394d..10e14319 100644
--- a/src/cairo_path.c
+++ b/src/cairo_path.c
@@ -329,10 +329,6 @@ _cairo_path_interpret (cairo_path_t *path, cairo_direction_t dir, const cairo_pa
cairo_path_arg_buf_t *arg_buf = path->arg_head;
int buf_i = 0;
cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
- cairo_point_t current = {0, 0};
- cairo_point_t first = {0, 0};
- int has_current = 0;
- int has_edge = 0;
int step = (dir == CAIRO_DIRECTION_FORWARD) ? 1 : -1;
for (op_buf = (dir == CAIRO_DIRECTION_FORWARD) ? path->op_head : path->op_tail;
@@ -374,61 +370,23 @@ _cairo_path_interpret (cairo_path_t *path, cairo_direction_t dir, const cairo_pa
switch (op) {
case CAIRO_PATH_OP_MOVE_TO:
- if (has_edge) {
- status = (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_CAP);
- if (status)
- return status;
- }
- first = point[0];
- current = point[0];
- has_current = 1;
- has_edge = 0;
+ status = (*cb->move_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_LINE_TO:
- if (has_current) {
- status = (*cb->add_edge) (closure, &current, &point[0]);
- if (status)
- return status;
- current = point[0];
- has_edge = 1;
- } else {
- first = point[0];
- current = point[0];
- has_current = 1;
- has_edge = 0;
- }
+ status = (*cb->line_to) (closure, &point[0]);
break;
case CAIRO_PATH_OP_CURVE_TO:
- if (has_current) {
- status = (*cb->add_spline) (closure, &current, &point[0], &point[1], &point[2]);
- if (status)
- return status;
- current = point[2];
- has_edge = 1;
- } else {
- first = point[2];
- current = point[2];
- has_current = 1;
- has_edge = 0;
- }
+ status = (*cb->curve_to) (closure, &point[0], &point[1], &point[2]);
break;
case CAIRO_PATH_OP_CLOSE_PATH:
- if (has_edge) {
- (*cb->add_edge) (closure, &current, &first);
- (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_JOIN);
- }
- current.x = 0;
- current.y = 0;
- first.x = 0;
- first.y = 0;
- has_current = 0;
- has_edge = 0;
+ default:
+ status = (*cb->close_path) (closure);
break;
}
+ if (status)
+ return status;
}
}
- if (has_edge)
- (*cb->done_sub_path) (closure, CAIRO_SUB_PATH_DONE_CAP);
return (*cb->done_path) (closure);
}
diff --git a/src/cairo_path_fill.c b/src/cairo_path_fill.c
index 8f34af85..74a019d6 100644
--- a/src/cairo_path_fill.c
+++ b/src/cairo_path_fill.c
@@ -31,6 +31,8 @@ typedef struct cairo_filler {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
+ cairo_point_t current_point;
+
cairo_polygon_t polygon;
} cairo_filler_t;
@@ -41,15 +43,19 @@ static void
_cairo_filler_fini (cairo_filler_t *filler);
static cairo_status_t
-_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_filler_move_to (void *closure, cairo_point_t *point);
+
+static cairo_status_t
+_cairo_filler_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_filler_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d);
+_cairo_filler_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d);
static cairo_status_t
-_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
+_cairo_filler_close_path (void *closure);
static cairo_status_t
_cairo_filler_done_path (void *closure);
@@ -60,6 +66,9 @@ _cairo_filler_init (cairo_filler_t *filler, cairo_gstate_t *gstate, cairo_traps_
filler->gstate = gstate;
filler->traps = traps;
+ filler->current_point.x = 0;
+ filler->current_point.y = 0;
+
_cairo_polygon_init (&filler->polygon);
}
@@ -70,18 +79,46 @@ _cairo_filler_fini (cairo_filler_t *filler)
}
static cairo_status_t
-_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_filler_move_to (void *closure, cairo_point_t *point)
{
+ cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
- return _cairo_polygon_add_edge (polygon, p1, p2);
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
+
+ status = _cairo_polygon_move_to (polygon, point);
+ if (status)
+ return status;
+
+ filler->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_filler_line_to (void *closure, cairo_point_t *point)
+{
+ cairo_status_t status;
+ cairo_filler_t *filler = closure;
+ cairo_polygon_t *polygon = &filler->polygon;
+
+ status = _cairo_polygon_line_to (polygon, point);
+ if (status)
+ return status;
+
+ filler->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_filler_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d)
+_cairo_filler_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -90,7 +127,8 @@ _cairo_filler_add_spline (void *closure,
cairo_gstate_t *gstate = filler->gstate;
cairo_spline_t spline;
- status = _cairo_spline_init (&spline, a, b, c, d);
+ status = _cairo_spline_init (&spline, &filler->current_point, b, c, d);
+
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
@@ -98,47 +136,62 @@ _cairo_filler_add_spline (void *closure,
if (status)
goto CLEANUP_SPLINE;
- for (i = 0; i < spline.num_points - 1; i++) {
- status = _cairo_polygon_add_edge (polygon, &spline.points[i], &spline.points[i+1]);
+ for (i = 1; i < spline.num_points; i++) {
+ status = _cairo_polygon_line_to (polygon, &spline.points[i]);
if (status)
- goto CLEANUP_SPLINE;
+ break;
}
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
+ filler->current_point = *d;
+
return status;
}
static cairo_status_t
-_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done)
+_cairo_filler_close_path (void *closure)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
- _cairo_polygon_close (polygon);
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_filler_done_path (void *closure)
{
+ cairo_status_t status;
cairo_filler_t *filler = closure;
+ cairo_polygon_t *polygon = &filler->polygon;
+
+ status = _cairo_polygon_close (polygon);
+ if (status)
+ return status;
- return _cairo_traps_tessellate_polygon (filler->traps,
- &filler->polygon,
- filler->gstate->fill_rule);
+ status = _cairo_traps_tessellate_polygon (filler->traps,
+ &filler->polygon,
+ filler->gstate->fill_rule);
+ if (status)
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_path_fill_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
{
static const cairo_path_callbacks_t filler_callbacks = {
- _cairo_filler_add_edge,
- _cairo_filler_add_spline,
- _cairo_filler_done_sub_path,
+ _cairo_filler_move_to,
+ _cairo_filler_line_to,
+ _cairo_filler_curve_to,
+ _cairo_filler_close_path,
_cairo_filler_done_path
};
diff --git a/src/cairo_path_stroke.c b/src/cairo_path_stroke.c
index 35e7b1b7..2bc271de 100644
--- a/src/cairo_path_stroke.c
+++ b/src/cairo_path_stroke.c
@@ -31,11 +31,17 @@ typedef struct cairo_stroker {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
- int have_prev;
- int have_first;
- int is_first;
- cairo_stroke_face_t prev;
- cairo_stroke_face_t first;
+ int has_current_point;
+ cairo_point_t current_point;
+ cairo_point_t first_point;
+
+ int has_current_face;
+ cairo_stroke_face_t current_face;
+
+ int has_first_face;
+ cairo_stroke_face_t first_face;
+
+ int dashed;
int dash_index;
int dash_on;
double dash_remain;
@@ -49,18 +55,22 @@ static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
static cairo_status_t
-_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_stroker_move_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2);
+_cairo_stroker_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d);
+_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point);
static cairo_status_t
-_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done);
+_cairo_stroker_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d);
+
+static cairo_status_t
+_cairo_stroker_close_path (void *closure);
static cairo_status_t
_cairo_stroker_done_path (void *closure);
@@ -89,6 +99,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
if (++i == gstate->num_dashes)
i = 0;
}
+ stroker->dashed = 1;
stroker->dash_index = i;
stroker->dash_on = on;
stroker->dash_remain = gstate->dash[i] - offset;
@@ -113,11 +124,15 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra
{
stroker->gstate = gstate;
stroker->traps = traps;
- stroker->have_prev = 0;
- stroker->have_first = 0;
- stroker->is_first = 1;
+
+ stroker->has_current_point = 0;
+ stroker->has_current_face = 0;
+ stroker->has_first_face = 0;
+
if (gstate->dash)
_cairo_stroker_start_dash (stroker);
+ else
+ stroker->dashed = 0;
}
static void
@@ -286,10 +301,11 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
outer.x = _cairo_fixed_from_double (mx);
outer.y = _cairo_fixed_from_double (my);
_cairo_polygon_init (&polygon);
- _cairo_polygon_add_edge (&polygon, &in->point, inpt);
- _cairo_polygon_add_edge (&polygon, inpt, &outer);
- _cairo_polygon_add_edge (&polygon, &outer, outpt);
- _cairo_polygon_add_edge (&polygon, outpt, &in->point);
+ _cairo_polygon_move_to (&polygon, &in->point);
+ _cairo_polygon_line_to (&polygon, inpt);
+ _cairo_polygon_line_to (&polygon, &outer);
+ _cairo_polygon_line_to (&polygon, outpt);
+ _cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps,
&polygon,
CAIRO_FILL_RULE_WINDING);
@@ -351,8 +367,6 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
cairo_point_t occw, ocw;
cairo_polygon_t polygon;
- _cairo_polygon_init (&polygon);
-
dx = f->usr_vector.x;
dy = f->usr_vector.y;
dx *= gstate->line_width / 2.0;
@@ -365,10 +379,12 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
ocw.x = f->cw.x + fvector.dx;
ocw.y = f->cw.y + fvector.dy;
- _cairo_polygon_add_edge (&polygon, &f->cw, &ocw);
- _cairo_polygon_add_edge (&polygon, &ocw, &occw);
- _cairo_polygon_add_edge (&polygon, &occw, &f->ccw);
- _cairo_polygon_add_edge (&polygon, &f->ccw, &f->cw);
+ _cairo_polygon_init (&polygon);
+ _cairo_polygon_move_to (&polygon, &f->cw);
+ _cairo_polygon_line_to (&polygon, &ocw);
+ _cairo_polygon_line_to (&polygon, &occw);
+ _cairo_polygon_line_to (&polygon, &f->ccw);
+ _cairo_polygon_close (&polygon);
status = _cairo_traps_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
@@ -482,11 +498,31 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
}
static cairo_status_t
-_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_stroker_move_to (void *closure, cairo_point_t *point)
+{
+ cairo_stroker_t *stroker = closure;
+
+ stroker->first_point = *point;
+ stroker->current_point = *point;
+ stroker->has_current_point = 1;
+
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_stroker_line_to (void *closure, cairo_point_t *point)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
cairo_stroke_face_t start, end;
+ 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
@@ -500,19 +536,20 @@ _cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
if (status)
return status;
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
if (status)
return status;
} else {
- stroker->have_prev = 1;
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = start;
+ stroker->has_first_face = 1;
}
}
- stroker->prev = end;
- stroker->is_first = 0;
+ stroker->current_face = end;
+ stroker->has_current_face = 1;
+
+ stroker->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
@@ -521,7 +558,7 @@ _cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
* Dashed lines. Cap each dash end, join around turns when on
*/
static cairo_status_t
-_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2)
+_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@@ -532,6 +569,11 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
cairo_point_t fd1, fd2;
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
+ 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);
@@ -569,18 +611,18 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
return status;
} else {
/*
- * First in this segment, join to any prev, else
+ * First in this segment, join to any current_face, else
* if at start of sub-path, mark position, else
* cap
*/
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &sub_start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
if (status)
return status;
} else {
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = sub_start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = sub_start;
+ stroker->has_first_face = 1;
} else {
status = _cairo_stroker_cap (stroker, &sub_start);
if (status)
@@ -600,8 +642,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
* Mark previous line face and fix up next time
* through
*/
- stroker->prev = sub_end;
- stroker->have_prev = 1;
+ stroker->current_face = sub_end;
+ stroker->has_current_face = 1;
}
} else {
/*
@@ -609,27 +651,30 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
* and cap if necessary
*/
if (first) {
- if (stroker->have_prev) {
- status = _cairo_stroker_cap (stroker, &stroker->prev);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_cap (stroker, &stroker->current_face);
if (status)
return status;
}
}
if (!remain)
- stroker->have_prev = 0;
+ stroker->has_current_face = 0;
}
_cairo_stroker_step_dash (stroker, tmp);
fd1 = fd2;
first = 0;
}
- stroker->is_first = 0;
+
+ stroker->current_point = *point;
+
return status;
}
static cairo_status_t
-_cairo_stroker_add_spline (void *closure,
- cairo_point_t *a, cairo_point_t *b,
- cairo_point_t *c, cairo_point_t *d)
+_cairo_stroker_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@@ -638,6 +683,7 @@ _cairo_stroker_add_spline (void *closure,
cairo_pen_t pen;
cairo_stroke_face_t start, end;
cairo_point_t extra_points[4];
+ cairo_point_t *a = &stroker->current_point;
status = _cairo_spline_init (&spline, a, b, c, d);
if (status == CAIRO_INT_STATUS_DEGENERATE)
@@ -650,19 +696,18 @@ _cairo_stroker_add_spline (void *closure,
_compute_face (a, &spline.initial_slope, gstate, &start);
_compute_face (d, &spline.final_slope, gstate, &end);
- if (stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &start);
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
if (status)
return status;
} else {
- stroker->have_prev = 1;
- if (stroker->is_first) {
- stroker->have_first = 1;
- stroker->first = start;
+ if (!stroker->has_first_face) {
+ stroker->first_face = start;
+ stroker->has_first_face = 1;
}
}
- stroker->prev = end;
- stroker->is_first = 0;
+ stroker->current_face = end;
+ stroker->has_current_face = 1;
extra_points[0] = start.cw;
extra_points[0].x -= start.point.x;
@@ -690,50 +735,35 @@ _cairo_stroker_add_spline (void *closure,
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
+ stroker->current_point = *d;
+
return status;
}
static cairo_status_t
-_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
+_cairo_stroker_close_path (void *closure)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
- switch (done) {
- case CAIRO_SUB_PATH_DONE_JOIN:
- if (stroker->have_first && stroker->have_prev) {
- status = _cairo_stroker_join (stroker, &stroker->prev, &stroker->first);
- if (status)
- return status;
- break;
- }
- /* fall through... */
- case CAIRO_SUB_PATH_DONE_CAP:
- if (stroker->have_first) {
- cairo_point_t t;
- /* The initial cap needs an outward facing vector. Reverse everything */
- stroker->first.usr_vector.x = -stroker->first.usr_vector.x;
- stroker->first.usr_vector.y = -stroker->first.usr_vector.y;
- stroker->first.dev_vector.dx = -stroker->first.dev_vector.dx;
- stroker->first.dev_vector.dy = -stroker->first.dev_vector.dy;
- t = stroker->first.cw;
- stroker->first.cw = stroker->first.ccw;
- stroker->first.ccw = t;
- status = _cairo_stroker_cap (stroker, &stroker->first);
- if (status)
- return status;
- }
- if (stroker->have_prev) {
- status = _cairo_stroker_cap (stroker, &stroker->prev);
- if (status)
- return status;
- }
- break;
+ 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->has_first_face && stroker->has_current_face) {
+ status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
+ if (status)
+ return status;
}
- stroker->have_prev = 0;
- stroker->have_first = 0;
- stroker->is_first = 1;
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+ stroker->has_current_point = 0;
return CAIRO_STATUS_SUCCESS;
}
@@ -741,6 +771,33 @@ _cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
static cairo_status_t
_cairo_stroker_done_path (void *closure)
{
+ cairo_status_t status;
+ cairo_stroker_t *stroker = closure;
+
+ if (stroker->has_first_face) {
+ cairo_point_t t;
+ /* The initial cap needs an outward facing vector. Reverse everything */
+ stroker->first_face.usr_vector.x = -stroker->first_face.usr_vector.x;
+ stroker->first_face.usr_vector.y = -stroker->first_face.usr_vector.y;
+ stroker->first_face.dev_vector.dx = -stroker->first_face.dev_vector.dx;
+ stroker->first_face.dev_vector.dy = -stroker->first_face.dev_vector.dy;
+ t = stroker->first_face.cw;
+ stroker->first_face.cw = stroker->first_face.ccw;
+ stroker->first_face.ccw = t;
+ status = _cairo_stroker_cap (stroker, &stroker->first_face);
+ if (status)
+ return status;
+ }
+ if (stroker->has_current_face) {
+ status = _cairo_stroker_cap (stroker, &stroker->current_face);
+ if (status)
+ return status;
+ }
+
+ stroker->has_first_face = 0;
+ stroker->has_current_face = 0;
+ stroker->has_current_point = 0;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -748,15 +805,17 @@ cairo_status_t
_cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
{
static const cairo_path_callbacks_t stroker_solid_cb = {
- _cairo_stroker_add_edge,
- _cairo_stroker_add_spline,
- _cairo_stroker_done_sub_path,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
_cairo_stroker_done_path
};
static const cairo_path_callbacks_t stroker_dashed_cb = {
- _cairo_stroker_add_edge_dashed,
- _cairo_stroker_add_spline,
- _cairo_stroker_done_sub_path,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to_dashed,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
_cairo_stroker_done_path
};
const cairo_path_callbacks_t *callbacks = gstate->dash ? &stroker_dashed_cb : &stroker_solid_cb;
diff --git a/src/cairo_pen.c b/src/cairo_pen.c
index dd054372..0bb5debd 100644
--- a/src/cairo_pen.c
+++ b/src/cairo_pen.c
@@ -288,7 +288,7 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
while (i != stop) {
hull_point.x = point[i].x + pen->vertices[active].point.x;
hull_point.y = point[i].y + pen->vertices[active].point.y;
- status = _cairo_polygon_add_point (polygon, &hull_point);
+ status = _cairo_polygon_line_to (polygon, &hull_point);
if (status)
return status;
diff --git a/src/cairo_polygon.c b/src/cairo_polygon.c
index 97f074a3..fbda7321 100644
--- a/src/cairo_polygon.c
+++ b/src/cairo_polygon.c
@@ -35,9 +35,6 @@
static cairo_status_t
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
-static void
-_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *point);
-
void
_cairo_polygon_init (cairo_polygon_t *polygon)
{
@@ -46,10 +43,7 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
polygon->edges_size = 0;
polygon->edges = NULL;
- polygon->first_point_defined = 0;
- polygon->last_point_defined = 0;
-
- polygon->closed = 0;
+ polygon->has_current_point = 0;
}
void
@@ -62,10 +56,7 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
polygon->num_edges = 0;
}
- polygon->first_point_defined = 0;
- polygon->last_point_defined = 0;
-
- polygon->closed = 0;
+ polygon->has_current_point = 0;
}
static cairo_status_t
@@ -92,25 +83,12 @@ _cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
return CAIRO_STATUS_SUCCESS;
}
-static void
-_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *point)
-{
- polygon->last_point = *point;
- polygon->last_point_defined = 1;
-}
-
cairo_status_t
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_edge_t *edge;
- if (! polygon->first_point_defined) {
- polygon->first_point = *p1;
- polygon->first_point_defined = 1;
- polygon->closed = 0;
- }
-
/* drop horizontal edges */
if (p1->y == p2->y) {
goto DONE;
@@ -137,20 +115,31 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
polygon->num_edges++;
DONE:
- _cairo_polygon_set_last_point (polygon, p2);
+ _cairo_polygon_move_to (polygon, p2);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
+{
+ if (! polygon->has_current_point)
+ polygon->first_point = *point;
+ polygon->current_point = *point;
+ polygon->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *point)
+_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- if (polygon->last_point_defined) {
- status = _cairo_polygon_add_edge (polygon, &polygon->last_point, point);
+ if (polygon->has_current_point) {
+ status = _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
} else {
- _cairo_polygon_set_last_point (polygon, point);
+ _cairo_polygon_move_to (polygon, point);
}
return status;
@@ -161,13 +150,14 @@ _cairo_polygon_close (cairo_polygon_t *polygon)
{
cairo_status_t status;
- if (polygon->closed == 0 && polygon->last_point_defined) {
- status = _cairo_polygon_add_edge (polygon, &polygon->last_point, &polygon->first_point);
+ if (polygon->has_current_point) {
+ status = _cairo_polygon_add_edge (polygon,
+ &polygon->current_point,
+ &polygon->first_point);
if (status)
return status;
- polygon->closed = 1;
- polygon->first_point_defined = 0;
+ polygon->has_current_point = 0;
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairoint.h b/src/cairoint.h
index 036bff21..838c061e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -144,15 +144,11 @@ typedef enum cairo_direction {
CAIRO_DIRECTION_REVERSE
} cairo_direction_t;
-typedef enum cairo_sub_path_done {
- CAIRO_SUB_PATH_DONE_CAP,
- CAIRO_SUB_PATH_DONE_JOIN
-} cairo_sub_path_done_t;
-
typedef struct cairo_path_callbacks {
- cairo_status_t (*add_edge) (void *closure, cairo_point_t *p1, cairo_point_t *p2);
- cairo_status_t (*add_spline) (void *closure, cairo_point_t *a, cairo_point_t *b, cairo_point_t *c, cairo_point_t *d);
- cairo_status_t (*done_sub_path) (void *closure, cairo_sub_path_done_t done);
+ cairo_status_t (*move_to) (void *closure, cairo_point_t *point);
+ cairo_status_t (*line_to) (void *closure, cairo_point_t *point);
+ cairo_status_t (*curve_to) (void *closure, cairo_point_t *b, cairo_point_t *c, cairo_point_t *d);
+ cairo_status_t (*close_path) (void *closure);
cairo_status_t (*done_path) (void *closure);
} cairo_path_callbacks_t;
@@ -193,9 +189,8 @@ typedef struct cairo_polygon {
cairo_edge_t *edges;
cairo_point_t first_point;
- int first_point_defined;
- cairo_point_t last_point;
- int last_point_defined;
+ cairo_point_t current_point;
+ int has_current_point;
int closed;
} cairo_polygon_t;
@@ -1065,7 +1060,10 @@ extern cairo_status_t __internal_linkage
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2);
extern cairo_status_t __internal_linkage
-_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *point);
+_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point);
+
+extern cairo_status_t __internal_linkage
+_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point);
extern cairo_status_t __internal_linkage
_cairo_polygon_close (cairo_polygon_t *polygon);