diff options
author | M Joonas Pihlaja <jpihlaja@cc.helsinki.fi> | 2008-07-25 16:35:14 +0300 |
---|---|---|
committer | M Joonas Pihlaja <jpihlaja@cc.helsinki.fi> | 2008-12-06 14:04:35 +0200 |
commit | a370d077bc697588b6dac2556afa0b95ff83a77d (patch) | |
tree | dd4920163e00750d4532d8e75340f5aa19ae0ffb | |
parent | 6acb8223930081f70b422ef93a49ea645c2cc12d (diff) |
[path-fixed] New _cairo_path_fixed_is_region().
We want to hit the current fast paths for rendering axis aligned
rectilinear paths rather than spans, and for that we need to be able
to identify regional paths.
-rw-r--r-- | src/cairo-path-fixed.c | 96 | ||||
-rw-r--r-- | src/cairoint.h | 3 |
2 files changed, 99 insertions, 0 deletions
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c index d6a3d7f2..dd25bb88 100644 --- a/src/cairo-path-fixed.c +++ b/src/cairo-path-fixed.c @@ -1179,3 +1179,99 @@ _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter) return FALSE; } + +/* Closure for path region testing. Every move_to must be to integer + * coordinates, there must be no curves, and every line_to or + * close_path must represent an axis aligned line to an integer point. + * We're relying on the path interpreter always sending a single + * move_to at the start of any subpath, not receiving having any + * superfluous move_tos, and the path intepreter bailing with our + * first non-successful error. */ +typedef struct cairo_path_region_tester { + cairo_point_t last_move_point; + cairo_point_t current_point; +} cprt_t; + +static cairo_status_t +_cprt_line_to (void *closure, + cairo_point_t *p2) +{ + cprt_t *self = closure; + cairo_point_t *p1 = &self->current_point; + if (p2->x == p1->x) { + if (_cairo_fixed_is_integer(p2->y)) { + *p1 = *p2; + return CAIRO_STATUS_SUCCESS; + } + } + else if (p2->y == p1->y) { + if (_cairo_fixed_is_integer(p2->x)) { + *p1 = *p2; + return CAIRO_STATUS_SUCCESS; + } + } + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +static cairo_status_t +_cprt_close_path (void *closure) +{ + cprt_t *self = closure; + return _cprt_line_to (closure, &self->last_move_point); +} + +static cairo_status_t +_cprt_move_to (void *closure, + cairo_point_t *p) +{ + cprt_t *self = closure; + cairo_status_t status = _cprt_close_path (closure); + if (status) return status; + if (_cairo_fixed_is_integer(p->x) && + _cairo_fixed_is_integer(p->y)) + { + self->current_point = *p; + self->last_move_point = *p; + return CAIRO_STATUS_SUCCESS; + } + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +static cairo_status_t +_cprt_curve_to (void *closure, + cairo_point_t *p0, + cairo_point_t *p1, + cairo_point_t *p2) +{ + (void)closure; + (void)p0; + (void)p1; + (void)p2; + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +/** + * Check whether the given path is representable as a region. + * That is, if the path contains only axis aligned lines between + * integer coordinates in device space. + */ +cairo_bool_t +_cairo_path_fixed_is_region (cairo_path_fixed_t *path) +{ + cprt_t cprt; + cairo_status_t status; + if (path->has_curve_to) + return FALSE; + cprt.current_point.x = 0; + cprt.current_point.y = 0; + cprt.last_move_point.x = 0; + cprt.last_move_point.y = 0; + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cprt_move_to, + _cprt_line_to, + _cprt_curve_to, + _cprt_close_path, + &cprt); + return status == CAIRO_STATUS_SUCCESS; +} diff --git a/src/cairoint.h b/src/cairoint.h index 34ea874a..692c36ab 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1536,6 +1536,9 @@ cairo_private cairo_bool_t _cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path, cairo_box_t *box); +cairo_private cairo_bool_t +_cairo_path_fixed_is_region (cairo_path_fixed_t *path); + /* cairo-path-in-fill.c */ cairo_private void _cairo_path_fixed_in_fill (cairo_path_fixed_t *path, |