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.

Provide cairo_polygon_move_to and cairo_polygon_line_to instead of cairo_polygon_add_point.
Track change in cairo_polygon interface.
This commit is contained in:
Carl Worth 2003-12-08 13:38:26 +00:00
parent 6aff3cbf96
commit 08553e75b7
12 changed files with 554 additions and 420 deletions

View file

@ -1,3 +1,19 @@
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

View file

@ -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_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
_cairo_filler_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
_cairo_filler_curve_to (void *closure,
cairo_point_t *b,
cairo_point_t *c,
cairo_point_t *d);
static cairo_status_t
_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_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
_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_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;
return _cairo_traps_tessellate_polygon (filler->traps,
&filler->polygon,
filler->gstate->fill_rule);
status = _cairo_polygon_close (polygon);
if (status)
return status;
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
};

View file

@ -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;
}
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
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->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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
_cairo_filler_line_to (void *closure, cairo_point_t *point);
static cairo_status_t
_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
_cairo_filler_curve_to (void *closure,
cairo_point_t *b,
cairo_point_t *c,
cairo_point_t *d);
static cairo_status_t
_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_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
_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_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;
return _cairo_traps_tessellate_polygon (filler->traps,
&filler->polygon,
filler->gstate->fill_rule);
status = _cairo_polygon_close (polygon);
if (status)
return status;
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
};

View file

@ -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;
}
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
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->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;

View file

@ -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;

View file

@ -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;

View file

@ -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);