diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-14 21:19:54 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-19 21:14:34 +0100 |
commit | b132fae5e843c329d1414d1a65b2e8d66b99852f (patch) | |
tree | 7df5e21300eefe3abcc30616b22d7f5d3248b4d4 /src/cairo-surface-clipper.c | |
parent | f58ade7bace8c82d0ea6740f56d227696181d616 (diff) | |
download | cairo-b132fae5e843c329d1414d1a65b2e8d66b99852f.tar.gz |
clip: Rudimentary support for clip-polygon extraction
Step 1, fix the failings sighted recently by tracking clip-boxes as an
explicit property of the clipping and of composition.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-surface-clipper.c')
-rw-r--r-- | src/cairo-surface-clipper.c | 122 |
1 files changed, 77 insertions, 45 deletions
diff --git a/src/cairo-surface-clipper.c b/src/cairo-surface-clipper.c index 948730047..c1644b495 100644 --- a/src/cairo-surface-clipper.c +++ b/src/cairo-surface-clipper.c @@ -39,6 +39,63 @@ /* A collection of routines to facilitate vector surface clipping */ +/* XXX Eliminate repeated paths and nested clips */ + +static cairo_status_t +_cairo_path_fixed_add_box (cairo_path_fixed_t *path, + const cairo_box_t *box) +{ + cairo_status_t status; + + status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y); + if (unlikely (status)) + return status; + + status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y); + if (unlikely (status)) + return status; + + status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y); + if (unlikely (status)) + return status; + + status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y); + if (unlikely (status)) + return status; + + return _cairo_path_fixed_close_path (path); +} + +static cairo_status_t +_cairo_surface_clipper_intersect_clip_boxes (cairo_surface_clipper_t *clipper, + const cairo_clip_t *clip) +{ + cairo_path_fixed_t path; + cairo_status_t status; + int i; + + /* Reconstruct the path for the clip boxes. + * XXX maybe a new clipper callback? + */ + + _cairo_path_fixed_init (&path); + for (i = 0; i < clip->num_boxes; i++) { + status = _cairo_path_fixed_add_box (&path, &clip->boxes[i]); + if (unlikely (status)) { + _cairo_path_fixed_fini (&path); + return status; + } + } + + status = clipper->intersect_clip_path (clipper, &path, + CAIRO_FILL_RULE_WINDING, + 0., + CAIRO_ANTIALIAS_DEFAULT); + _cairo_path_fixed_init (&path); + + return status; +} + static cairo_status_t _cairo_surface_clipper_intersect_clip_path_recursive (cairo_surface_clipper_t *clipper, cairo_clip_path_t *clip_path) @@ -62,57 +119,33 @@ _cairo_surface_clipper_intersect_clip_path_recursive (cairo_surface_clipper_t *c cairo_status_t _cairo_surface_clipper_set_clip (cairo_surface_clipper_t *clipper, - cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_status_t status; - cairo_bool_t clear; - - /* XXX as we cache a reference to the path, and compare every time, - * we may in future need to install a notification if the clip->path - * is every modified (e.g. cairo_clip_translate). - */ - if (clip == NULL && clipper->clip.path == NULL) + if (_cairo_clip_equal (clip, clipper->clip)) return CAIRO_STATUS_SUCCESS; - if (clip != NULL && clipper->clip.path != NULL && - _cairo_clip_equal (clip, &clipper->clip)) - { - return CAIRO_STATUS_SUCCESS; - } - /* all clipped out state should never propagate this far */ - assert (clip == NULL || clip->path != NULL); + assert (!_cairo_clip_is_all_clipped (clip)); - /* Check whether this clip is a continuation of the previous. - * If not, we have to remove the current clip and rebuild. - */ - clear = clip == NULL || clip->path->prev != clipper->clip.path; + _cairo_clip_destroy (clipper->clip); + clipper->clip = _cairo_clip_copy (clip); - _cairo_clip_reset (&clipper->clip); - _cairo_clip_init_copy (&clipper->clip, clip); + status = clipper->intersect_clip_path (clipper, NULL, 0, 0, 0); + if (unlikely (status)) + return status; - if (clear) { - clipper->is_clipped = FALSE; - status = clipper->intersect_clip_path (clipper, NULL, 0, 0, 0); - if (unlikely (status)) - return status; + if (clip == NULL) + return CAIRO_STATUS_SUCCESS; - if (clip != NULL && clip->path != NULL) { - status = - _cairo_surface_clipper_intersect_clip_path_recursive (clipper, - clip->path); - clipper->is_clipped = TRUE; - } - } else { - cairo_clip_path_t *path = clip->path; - - clipper->is_clipped = TRUE; - status = clipper->intersect_clip_path (clipper, - &path->path, - path->fill_rule, - path->tolerance, - path->antialias); + status = _cairo_surface_clipper_intersect_clip_boxes (clipper, clip); + if (unlikely (status)) + return status; + + if (clip->path != NULL) { + status = _cairo_surface_clipper_intersect_clip_path_recursive (clipper, + clip->path); } return status; @@ -122,14 +155,13 @@ void _cairo_surface_clipper_init (cairo_surface_clipper_t *clipper, cairo_surface_clipper_intersect_clip_path_func_t func) { - _cairo_clip_init (&clipper->clip); - clipper->is_clipped = FALSE; + clipper->clip = NULL; clipper->intersect_clip_path = func; } void _cairo_surface_clipper_reset (cairo_surface_clipper_t *clipper) { - _cairo_clip_reset (&clipper->clip); - clipper->is_clipped = FALSE; + _cairo_clip_destroy (clipper->clip); + clipper->clip = NULL; } |