diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | src/cairo-path-fill.c | 101 | ||||
-rw-r--r-- | src/cairo-path-stroke.c | 253 | ||||
-rw-r--r-- | src/cairo-path.c | 56 | ||||
-rw-r--r-- | src/cairo-pen.c | 2 | ||||
-rw-r--r-- | src/cairo-polygon.c | 56 | ||||
-rw-r--r-- | src/cairo_path.c | 56 | ||||
-rw-r--r-- | src/cairo_path_fill.c | 101 | ||||
-rw-r--r-- | src/cairo_path_stroke.c | 253 | ||||
-rw-r--r-- | src/cairo_pen.c | 2 | ||||
-rw-r--r-- | src/cairo_polygon.c | 56 | ||||
-rw-r--r-- | src/cairoint.h | 22 |
12 files changed, 554 insertions, 420 deletions
@@ -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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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); |