summaryrefslogtreecommitdiff
path: root/src/cairo-clip.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-07-14 21:19:54 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-07-19 21:14:34 +0100
commitb132fae5e843c329d1414d1a65b2e8d66b99852f (patch)
tree7df5e21300eefe3abcc30616b22d7f5d3248b4d4 /src/cairo-clip.c
parentf58ade7bace8c82d0ea6740f56d227696181d616 (diff)
downloadcairo-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-clip.c')
-rw-r--r--src/cairo-clip.c1414
1 files changed, 179 insertions, 1235 deletions
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 9054b4e9d..99d7cd466 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -50,6 +50,16 @@
#include "cairo-region-private.h"
static freed_pool_t clip_path_pool;
+static freed_pool_t clip_pool;
+
+const cairo_clip_t __cairo_clip_all;
+
+static const cairo_rectangle_int_t _cairo_empty_rectangle = { 0, 0, 0, 0 };
+static const cairo_rectangle_int_t _cairo_unbounded_rectangle = {
+ CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN,
+ CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+ CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+};
static cairo_clip_path_t *
_cairo_clip_path_create (cairo_clip_t *clip)
@@ -65,10 +75,6 @@ _cairo_clip_path_create (cairo_clip_t *clip)
CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
- clip_path->flags = 0;
- clip_path->region = NULL;
- clip_path->surface = NULL;
-
clip_path->prev = clip->path;
clip->path = clip_path;
@@ -85,7 +91,7 @@ _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
return clip_path;
}
-static void
+void
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
{
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
@@ -94,10 +100,6 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
return;
_cairo_path_fixed_fini (&clip_path->path);
- if (clip_path->region != NULL)
- cairo_region_destroy (clip_path->region);
- if (clip_path->surface != NULL)
- cairo_surface_destroy (clip_path->surface);
if (clip_path->prev != NULL)
_cairo_clip_path_destroy (clip_path->prev);
@@ -105,115 +107,75 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
_freed_pool_put (&clip_path_pool, clip_path);
}
-void
-_cairo_clip_init (cairo_clip_t *clip)
+cairo_clip_t *
+_cairo_clip_create (void)
{
- clip->all_clipped = FALSE;
+ cairo_clip_t *clip;
+
+ clip = _freed_pool_get (&clip_pool);
+ if (unlikely (clip == NULL)) {
+ clip = malloc (sizeof (cairo_clip_t));
+ if (unlikely (clip == NULL))
+ return NULL;
+ }
+
+ clip->extents = _cairo_unbounded_rectangle;
+
clip->path = NULL;
+ clip->boxes = NULL;
+ clip->num_boxes = 0;
+ clip->region = NULL;
+ clip->is_region = FALSE;
+
+ return clip;
}
-static void
-_cairo_clip_set_all_clipped (cairo_clip_t *clip)
+void
+_cairo_clip_destroy (cairo_clip_t *clip)
{
- clip->all_clipped = TRUE;
- if (clip->path != NULL) {
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return;
+
+ if (clip->path != NULL)
_cairo_clip_path_destroy (clip->path);
- clip->path = NULL;
- }
+
+ free (clip->boxes);
+ cairo_region_destroy (clip->region);
+
+ _freed_pool_put (&clip_pool, clip);
}
-static cairo_status_t
-_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rect)
+cairo_clip_t *
+_cairo_clip_copy (const cairo_clip_t *clip)
{
- cairo_clip_path_t *clip_path;
- cairo_status_t status;
+ cairo_clip_t *copy;
- if (clip->path != NULL) {
- if (rect->x <= clip->path->extents.x &&
- rect->y <= clip->path->extents.y &&
- rect->x + rect->width >= clip->path->extents.x + clip->path->extents.width &&
- rect->y + rect->height >= clip->path->extents.y + clip->path->extents.height)
- {
- return CAIRO_STATUS_SUCCESS;
- }
- }
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return (cairo_clip_t *) clip;
- clip_path = _cairo_clip_path_create (clip);
- if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_path_fixed_init (&clip_path->path);
-
- status = _cairo_path_fixed_move_to (&clip_path->path,
- _cairo_fixed_from_int (rect->x),
- _cairo_fixed_from_int (rect->y));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (rect->width),
- _cairo_fixed_from_int (0));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (0),
- _cairo_fixed_from_int (rect->height));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (-rect->width),
- _cairo_fixed_from_int (0));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_close_path (&clip_path->path);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
- clip_path->tolerance = 1;
- clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT;
- clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
-
- clip_path->extents = *rect;
- if (clip_path->prev != NULL) {
- if (! _cairo_rectangle_intersect (&clip_path->extents,
- &clip_path->prev->extents))
- {
- _cairo_clip_set_all_clipped (clip);
- }
- }
+ copy = _cairo_clip_create ();
- /* could preallocate the region if it proves worthwhile */
+ if (clip->path)
+ copy->path = _cairo_clip_path_reference (clip->path);
- return CAIRO_STATUS_SUCCESS;
-}
+ if (clip->num_boxes) {
+ copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+ if (unlikely (copy->boxes == NULL))
+ return _cairo_clip_set_all_clipped (copy);
-cairo_clip_t *
-_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
-{
- if (other != NULL) {
- clip->all_clipped = other->all_clipped;
- if (other->path == NULL) {
- clip->path = NULL;
- if (! clip->all_clipped)
- clip = NULL;
- } else {
- clip->path = _cairo_clip_path_reference (other->path);
- }
- } else {
- _cairo_clip_init (clip);
- clip = NULL;
+ memcpy (copy->boxes, clip->boxes,
+ clip->num_boxes * sizeof (cairo_box_t));
+ copy->num_boxes = clip->num_boxes;
}
- return clip;
-}
+ copy->extents = clip->extents;
+ copy->region = cairo_region_reference (clip->region);
+ copy->is_region = clip->is_region;
-void
-_cairo_clip_reset (cairo_clip_t *clip)
-{
- clip->all_clipped = FALSE;
- if (clip->path != NULL) {
- _cairo_clip_path_destroy (clip->path);
- clip->path = NULL;
- }
+ return copy;
}
-static cairo_status_t
+cairo_clip_t *
_cairo_clip_intersect_path (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
@@ -224,928 +186,147 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
cairo_status_t status;
cairo_rectangle_int_t extents;
cairo_box_t box;
- cairo_bool_t is_box = FALSE;
-
- if (clip->path != NULL) {
- if (clip->path->fill_rule == fill_rule &&
- (_cairo_path_fixed_fill_is_rectilinear (path) || tolerance == clip->path->tolerance) &&
- antialias == clip->path->antialias &&
- _cairo_path_fixed_equal (&clip->path->path, path))
- {
- return CAIRO_STATUS_SUCCESS;
+
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
+
+ /* catch the empty clip path */
+ if (_cairo_path_fixed_fill_is_empty (path))
+ return _cairo_clip_set_all_clipped (clip);
+
+ if (_cairo_path_fixed_is_box (path, &box)) {
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ box.p1.x = _cairo_fixed_round_down (box.p1.x);
+ box.p1.y = _cairo_fixed_round_down (box.p1.y);
+ box.p2.x = _cairo_fixed_round_down (box.p2.x);
+ box.p2.y = _cairo_fixed_round_down (box.p2.y);
}
+
+ return _cairo_clip_intersect_box (clip, &box);
}
+ if (_cairo_path_fixed_fill_is_rectilinear (path))
+ return _cairo_clip_intersect_rectilinear_path (clip, path,
+ fill_rule, antialias);
_cairo_path_fixed_approximate_clip_extents (path, &extents);
- if (extents.width == 0 || extents.height == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
+ if (extents.width == 0 || extents.height == 0)
+ return _cairo_clip_set_all_clipped (clip);
- is_box = _cairo_path_fixed_is_box (path, &box);
- if (clip->path != NULL) {
- if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
+ if (clip && ! _cairo_rectangle_intersect (&clip->extents, &extents))
+ return _cairo_clip_set_all_clipped (clip);
- /* does this clip wholly subsume the others? */
- if (is_box &&
- box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) &&
- box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) &&
- box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) &&
- box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height))
- {
- return CAIRO_STATUS_SUCCESS;
- }
+ if (clip == NULL) {
+ clip = _cairo_clip_create ();
+ if (unlikely (clip == NULL))
+ return _cairo_clip_set_all_clipped (clip);
+
+ clip->extents = extents;
}
clip_path = _cairo_clip_path_create (clip);
if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return _cairo_clip_set_all_clipped (clip);
status = _cairo_path_fixed_init_copy (&clip_path->path, path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
+ if (unlikely (status))
+ return _cairo_clip_set_all_clipped (clip);
- clip_path->extents = extents;
clip_path->fill_rule = fill_rule;
clip_path->tolerance = tolerance;
clip_path->antialias = antialias;
- if (is_box)
- clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
- return CAIRO_STATUS_SUCCESS;
+ clip->is_region = FALSE;
+ return clip;
}
cairo_bool_t
_cairo_clip_equal (const cairo_clip_t *clip_a,
const cairo_clip_t *clip_b)
{
- const cairo_clip_path_t *clip_path_a, *clip_path_b;
-
- clip_path_a = clip_a->path;
- clip_path_b = clip_b->path;
-
- while (clip_path_a && clip_path_b) {
- if (clip_path_a == clip_path_b)
- return TRUE;
-
- if (clip_path_a->fill_rule != clip_path_b->fill_rule)
- return FALSE;
-
- if (clip_path_a->tolerance != clip_path_b->tolerance)
- return FALSE;
-
- if (clip_path_a->antialias != clip_path_b->antialias)
- return FALSE;
-
- if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
- return FALSE;
-
- clip_path_a = clip_path_a->prev;
- clip_path_b = clip_path_b->prev;
- }
-
- return clip_path_a == clip_path_b; /* ie both NULL */
-}
-
-cairo_status_t
-_cairo_clip_clip (cairo_clip_t *clip,
- const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias)
-{
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- /* catch the empty clip path */
- if (_cairo_path_fixed_fill_is_empty (path)) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- return _cairo_clip_intersect_path (clip,
- path, fill_rule, tolerance,
- antialias);
-}
-
-cairo_status_t
-_cairo_clip_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rectangle)
-{
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- if (rectangle->width == 0 || rectangle->height == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- /* if a smaller clip has already been set, ignore the new path */
- if (clip->path != NULL) {
- if (rectangle->x <= clip->path->extents.x &&
- rectangle->y <= clip->path->extents.y &&
- rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
- rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
- {
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
- return _cairo_clip_intersect_rectangle (clip, rectangle);
-}
-
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip,
- cairo_clip_path_t *other_path,
- const cairo_matrix_t *matrix)
-{
- cairo_status_t status;
- cairo_clip_path_t *clip_path;
-
- if (other_path->prev != NULL) {
- status = _cairo_clip_path_reapply_clip_path_transform (clip,
- other_path->prev,
- matrix);
- if (unlikely (status))
- return status;
- }
-
- clip_path = _cairo_clip_path_create (clip);
- if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = _cairo_path_fixed_init_copy (&clip_path->path,
- &other_path->path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
-
- _cairo_path_fixed_transform (&clip_path->path, matrix);
- _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
- &clip_path->extents);
- if (clip_path->prev != NULL) {
- _cairo_rectangle_intersect (&clip_path->extents,
- &clip_path->prev->extents);
- }
-
- clip_path->fill_rule = other_path->fill_rule;
- clip_path->tolerance = other_path->tolerance;
- clip_path->antialias = other_path->antialias;
+ /* are both all-clipped or no-clip? */
+ if (clip_a == clip_b)
+ return TRUE;
- return CAIRO_STATUS_SUCCESS;
+ return FALSE;
}
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
- cairo_clip_path_t *other_path,
- int tx, int ty)
+static cairo_clip_t *
+_cairo_clip_path_copy_with_translation (cairo_clip_t *clip,
+ cairo_clip_path_t *other_path,
+ int fx, int fy)
{
cairo_status_t status;
cairo_clip_path_t *clip_path;
- if (other_path->prev != NULL) {
- status = _cairo_clip_path_reapply_clip_path_translate (clip,
- other_path->prev,
- tx, ty);
- if (unlikely (status))
- return status;
- }
+ if (other_path->prev != NULL)
+ clip = _cairo_clip_path_copy_with_translation (clip, other_path->prev,
+ fx, fy);
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
clip_path = _cairo_clip_path_create (clip);
if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return _cairo_clip_set_all_clipped (clip);
status = _cairo_path_fixed_init_copy (&clip_path->path,
&other_path->path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
+ if (unlikely (status))
+ return _cairo_clip_set_all_clipped (clip);
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (tx),
- _cairo_fixed_from_int (ty));
+ _cairo_path_fixed_translate (&clip_path->path, fx, fy);
clip_path->fill_rule = other_path->fill_rule;
clip_path->tolerance = other_path->tolerance;
clip_path->antialias = other_path->antialias;
- clip_path->flags = other_path->flags;
- if (other_path->region != NULL) {
- clip_path->region = cairo_region_copy (other_path->region);
- status = clip_path->region->status;
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
-
- cairo_region_translate (clip_path->region, tx, ty);
- }
- clip_path->surface = cairo_surface_reference (other_path->surface);
-
- clip_path->extents = other_path->extents;
- clip_path->extents.x += tx;
- clip_path->extents.y += ty;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_clip_init_copy_transformed (cairo_clip_t *clip,
- cairo_clip_t *other,
- const cairo_matrix_t *matrix)
-{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- int tx, ty;
-
- if (other == NULL) {
- _cairo_clip_init (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (other->all_clipped) {
- _cairo_clip_init (clip);
- clip->all_clipped = TRUE;
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (_cairo_matrix_is_identity (matrix)) {
- _cairo_clip_init_copy (clip, other);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (other->path != NULL) {
- _cairo_clip_init (clip);
-
- /* if we only need to translate, so we can reuse the caches... */
- /* XXX we still loose the benefit of constructs when the copy is
- * deleted though. Indirect clip_paths?
- */
- if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) {
- status = _cairo_clip_path_reapply_clip_path_translate (clip,
- other->path,
- tx, ty);
- } else {
- status = _cairo_clip_path_reapply_clip_path_transform (clip,
- other->path,
- matrix);
- if (clip->path->extents.width == 0 &&
- clip->path->extents.height == 0)
- {
- _cairo_clip_set_all_clipped (clip);
- }
- }
- }
-
- return status;
-}
-
-static cairo_status_t
-_cairo_clip_apply_clip_path (cairo_clip_t *clip,
- const cairo_clip_path_t *path)
-{
- if (path->prev != NULL) {
- cairo_status_t status;
-
- status = _cairo_clip_apply_clip_path (clip, path->prev);
- if (unlikely (status))
- return status;
- }
-
- return _cairo_clip_intersect_path (clip,
- &path->path,
- path->fill_rule,
- path->tolerance,
- path->antialias);
-}
-
-cairo_status_t
-_cairo_clip_apply_clip (cairo_clip_t *clip,
- const cairo_clip_t *other)
-{
- cairo_status_t status;
-
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- if (other->all_clipped) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- status = CAIRO_STATUS_SUCCESS;
- if (other->path != NULL)
- status = _cairo_clip_apply_clip_path (clip, other->path);
-
- return status;
-}
-
-static inline cairo_bool_t
-_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
-{
- while (clip_path != NULL) {
- if (! _cairo_path_fixed_fill_is_rectilinear (&clip_path->path))
- return FALSE;
-
- clip_path = clip_path->prev;
- }
-
- return TRUE;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
-{
- cairo_traps_t traps;
- cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)];
- cairo_box_t *boxes = stack_boxes;
- cairo_status_t status;
- int n;
-
- /* If we have nothing to intersect with this path, then it cannot
- * magically be reduced into a region.
- */
- if (clip_path->prev == NULL)
- goto UNSUPPORTED;
-
- /* Start simple... Intersect some boxes with an arbitrary path. */
- if (! _cairo_path_fixed_fill_is_rectilinear (&clip_path->path))
- goto UNSUPPORTED;
- if (clip_path->prev->prev != NULL)
- goto UNSUPPORTED;
-
- _cairo_traps_init (&traps);
- _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
- _cairo_traps_limit (&traps, boxes, 1);
-
- status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path,
- clip_path->fill_rule,
- &traps);
- if (unlikely (_cairo_status_is_error (status)))
- return status;
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- goto UNSUPPORTED;
-
- if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) {
- boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
- if (unlikely (boxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- for (n = 0; n < traps.num_traps; n++) {
- boxes[n].p1.x = traps.traps[n].left.p1.x;
- boxes[n].p1.y = traps.traps[n].top;
- boxes[n].p2.x = traps.traps[n].right.p1.x;
- boxes[n].p2.y = traps.traps[n].bottom;
- }
-
- _cairo_traps_clear (&traps);
- _cairo_traps_limit (&traps, boxes, n);
- status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
- clip_path->prev->fill_rule,
- clip_path->prev->tolerance,
- &traps);
- if (boxes != stack_boxes)
- free (boxes);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_traps_extract_region (&traps, &clip_path->region);
- _cairo_traps_fini (&traps);
-
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- goto UNSUPPORTED;
- if (unlikely (status))
- return status;
-
- clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
- return CAIRO_STATUS_SUCCESS;
-
-UNSUPPORTED:
- clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
-{
- cairo_int_status_t status;
- cairo_region_t *prev = NULL;
-
- if (clip_path->flags &
- (CAIRO_CLIP_PATH_HAS_REGION |
- CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED))
- {
- return clip_path->flags & CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED ?
- CAIRO_INT_STATUS_UNSUPPORTED :
- CAIRO_STATUS_SUCCESS;
- }
-
- if (! _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- return _cairo_clip_path_to_region_geometric (clip_path);
-
- /* first retrieve the region for our antecedents */
- if (clip_path->prev != NULL) {
- status = _cairo_clip_path_to_region (clip_path->prev);
- if (status) {
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- return _cairo_clip_path_to_region_geometric (clip_path);
-
- return status;
- }
-
- prev = clip_path->prev->region;
- }
-
- /* now extract the region for ourselves */
- clip_path->region =
- _cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path,
- clip_path->fill_rule,
- &clip_path->extents);
- assert (clip_path->region != NULL);
-
- status = clip_path->region->status;
- if (unlikely (status))
- return status;
-
- if (prev != NULL) {
- status = cairo_region_intersect (clip_path->region, prev);
- if (unlikely (status))
- return status;
- }
-
- clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline int
-pot (int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
-}
-
-/* XXX there is likely a faster method! ;-) */
-static cairo_status_t
-_region_clip_to_boxes (const cairo_region_t *region,
- cairo_box_t **boxes,
- int *num_boxes,
- int *size_boxes)
-{
- cairo_traps_t traps;
- cairo_status_t status;
- int n, num_rects;
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, *boxes, *num_boxes);
- traps.is_rectilinear = TRUE;
- traps.is_rectangular = TRUE;
-
- num_rects = cairo_region_num_rectangles (region);
- for (n = 0; n < num_rects; n++) {
- cairo_rectangle_int_t rect;
- cairo_point_t p1, p2;
-
- cairo_region_get_rectangle (region, n, &rect);
-
- p1.x = _cairo_fixed_from_int (rect.x);
- p1.y = _cairo_fixed_from_int (rect.y);
- p2.x = _cairo_fixed_from_int (rect.x + rect.width);
- p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-
- status = _cairo_traps_tessellate_rectangle (&traps, &p1, &p2);
- if (unlikely (status))
- goto CLEANUP;
- }
-
- status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps, CAIRO_FILL_RULE_WINDING);
- if (unlikely (status))
- goto CLEANUP;
-
- n = *size_boxes;
- if (n < 0)
- n = -n;
-
- if (traps.num_traps > n) {
- cairo_box_t *new_boxes;
-
- new_boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- if (*size_boxes > 0)
- free (*boxes);
-
- *boxes = new_boxes;
- *size_boxes = traps.num_traps;
- }
-
- for (n = 0; n < traps.num_traps; n++) {
- (*boxes)[n].p1.x = traps.traps[n].left.p1.x;
- (*boxes)[n].p1.y = traps.traps[n].top;
- (*boxes)[n].p2.x = traps.traps[n].right.p1.x;
- (*boxes)[n].p2.y = traps.traps[n].bottom;
- }
- *num_boxes = n;
-
- CLEANUP:
- _cairo_traps_fini (&traps);
-
- return status;
-}
-
-static cairo_status_t
-_rectilinear_clip_to_boxes (const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- cairo_box_t **boxes,
- int *num_boxes,
- int *size_boxes)
-{
- cairo_polygon_t polygon;
- cairo_traps_t traps;
- cairo_status_t status;
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, *boxes, *num_boxes);
-
- _cairo_polygon_init (&polygon, *boxes, *num_boxes);
-
- status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
- fill_rule,
- &traps);
- if (unlikely (_cairo_status_is_error (status)))
- goto CLEANUP;
- if (status == CAIRO_STATUS_SUCCESS)
- goto BOXES;
-
- /* tolerance will be ignored as the path is rectilinear */
- status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
- if (unlikely (status))
- goto CLEANUP;
-
- if (polygon.num_edges == 0) {
- *num_boxes = 0;
- } else {
- status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
- &polygon,
- fill_rule);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- int i;
-
- BOXES:
- i = *size_boxes;
- if (i < 0)
- i = -i;
-
- if (traps.num_traps > i) {
- cairo_box_t *new_boxes;
- int new_size;
-
- new_size = pot (traps.num_traps);
- new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- if (*size_boxes > 0)
- free (*boxes);
-
- *boxes = new_boxes;
- *size_boxes = new_size;
- }
-
- for (i = 0; i < traps.num_traps; i++) {
- (*boxes)[i].p1.x = traps.traps[i].left.p1.x;
- (*boxes)[i].p1.y = traps.traps[i].top;
- (*boxes)[i].p2.x = traps.traps[i].right.p1.x;
- (*boxes)[i].p2.y = traps.traps[i].bottom;
- }
- *num_boxes = i;
- }
- }
-
- CLEANUP:
- _cairo_polygon_fini (&polygon);
- _cairo_traps_fini (&traps);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
- cairo_box_t **boxes,
- int *count)
-{
- int size = -*count;
- int num_boxes = 0;
- cairo_status_t status;
-
- if (clip_path->region != NULL) {
- int num_rects, n;
-
- num_rects = cairo_region_num_rectangles (clip_path->region);
- if (num_rects > -size) {
- cairo_box_t *new_boxes;
-
- new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- *boxes = new_boxes;
- }
-
- for (n = 0; n < num_rects; n++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (clip_path->region, n, &rect);
- (*boxes)[n].p1.x = _cairo_fixed_from_int (rect.x);
- (*boxes)[n].p1.y = _cairo_fixed_from_int (rect.y);
- (*boxes)[n].p2.x = _cairo_fixed_from_int (rect.x + rect.width);
- (*boxes)[n].p2.y = _cairo_fixed_from_int (rect.y + rect.height);
- }
-
- *count = num_rects;
- return CAIRO_STATUS_SUCCESS;
- }
-
- /* keep it simple at first */
- if (! _clip_paths_are_rectilinear (clip_path))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- assert (-size >= 1);
- if (_cairo_path_fixed_is_box (&clip_path->path, *boxes)) {
- num_boxes = 1;
- } else {
- status = _rectilinear_clip_to_boxes (&clip_path->path,
- clip_path->fill_rule,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
- }
-
- while (num_boxes > 0 && (clip_path = clip_path->prev) != NULL) {
- cairo_box_t box;
-
- if (clip_path->region != NULL) {
- status = _region_clip_to_boxes (clip_path->region,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
-
- break;
- } else if (_cairo_path_fixed_is_box (&clip_path->path, &box)) {
- int i, j;
-
- for (i = j = 0; i < num_boxes; i++) {
- if (j != i)
- (*boxes)[j] = (*boxes)[i];
-
- if (box.p1.x > (*boxes)[j].p1.x)
- (*boxes)[j].p1.x = box.p1.x;
- if (box.p2.x < (*boxes)[j].p2.x)
- (*boxes)[j].p2.x = box.p2.x;
-
- if (box.p1.y > (*boxes)[j].p1.y)
- (*boxes)[j].p1.y = box.p1.y;
- if (box.p2.y < (*boxes)[j].p2.y)
- (*boxes)[j].p2.y = box.p2.y;
-
- j += (*boxes)[j].p2.x > (*boxes)[j].p1.x &&
- (*boxes)[j].p2.y > (*boxes)[j].p1.y;
- }
-
- num_boxes = j;
- } else {
- status = _rectilinear_clip_to_boxes (&clip_path->path,
- clip_path->fill_rule,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
- }
- }
-
- *count = num_boxes;
- return CAIRO_STATUS_SUCCESS;
+ return clip;
}
-static cairo_surface_t *
-_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
- cairo_surface_t *target,
- int *tx, int *ty)
+cairo_clip_t *
+_cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty)
{
- const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
- cairo_bool_t need_translate;
- cairo_surface_t *surface;
- cairo_clip_path_t *prev;
- cairo_status_t status;
+ cairo_clip_t *copy;
+ int fx, fy, i;
- while (clip_path->prev != NULL &&
- clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- clip_path = clip_path->prev;
- }
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return (cairo_clip_t *)clip;
- clip_extents = &clip_path->extents;
- if (clip_path->surface != NULL &&
- clip_path->surface->backend == target->backend)
- {
- *tx = clip_extents->x;
- *ty = clip_extents->y;
- return clip_path->surface;
- }
+ if (tx == 0 && ty == 0)
+ return _cairo_clip_copy (clip);
- surface = _cairo_surface_create_similar_scratch (target,
- CAIRO_CONTENT_ALPHA,
- clip_extents->width,
- clip_extents->height);
- if (surface == NULL) {
- surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
- clip_extents->width,
- clip_extents->height);
- }
- if (unlikely (surface->status))
- return surface;
-
- need_translate = clip_extents->x | clip_extents->y;
- if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_SOURCE,
- &_cairo_pattern_white.base,
- NULL);
- if (unlikely (status))
- goto BAIL;
- }
- else
- {
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_CLEAR,
- &_cairo_pattern_clear.base,
- NULL);
- if (unlikely (status))
- goto BAIL;
-
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (-clip_extents->x),
- _cairo_fixed_from_int (-clip_extents->y));
- }
- status = _cairo_surface_fill (surface,
- CAIRO_OPERATOR_ADD,
- &_cairo_pattern_white.base,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (clip_extents->x),
- _cairo_fixed_from_int (clip_extents->y));
- }
+ copy = _cairo_clip_create ();
+ if (copy == NULL)
+ return _cairo_clip_set_all_clipped (copy);
- if (unlikely (status))
- goto BAIL;
- }
+ fx = _cairo_fixed_from_int (tx);
+ fy = _cairo_fixed_from_int (ty);
- prev = clip_path->prev;
- while (prev != NULL) {
- if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&prev->path))
- {
- /* a simple box only affects the extents */
- }
- else if (_cairo_path_fixed_fill_is_rectilinear (&prev->path) ||
- prev->surface == NULL ||
- prev->surface->backend != target->backend)
- {
- if (need_translate) {
- _cairo_path_fixed_translate (&prev->path,
- _cairo_fixed_from_int (-clip_extents->x),
- _cairo_fixed_from_int (-clip_extents->y));
- }
- status = _cairo_surface_fill (surface,
- CAIRO_OPERATOR_IN,
- &_cairo_pattern_white.base,
- &prev->path,
- prev->fill_rule,
- prev->tolerance,
- prev->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&prev->path,
- _cairo_fixed_from_int (clip_extents->x),
- _cairo_fixed_from_int (clip_extents->y));
- }
+ if (clip->num_boxes) {
+ copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+ if (unlikely (copy->boxes == NULL))
+ return _cairo_clip_set_all_clipped (copy);
- if (unlikely (status))
- goto BAIL;
- }
- else
- {
- cairo_surface_pattern_t pattern;
- cairo_surface_t *prev_surface;
- int prev_tx, prev_ty;
-
- prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
- status = prev_surface->status;
- if (unlikely (status))
- goto BAIL;
-
- _cairo_pattern_init_for_surface (&pattern, prev_surface);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
- cairo_matrix_init_translate (&pattern.base.matrix,
- clip_extents->x - prev_tx,
- clip_extents->y - prev_ty);
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL);
- _cairo_pattern_fini (&pattern.base);
-
- if (unlikely (status))
- goto BAIL;
-
- break;
+ for (i = 0; i < clip->num_boxes; i++) {
+ copy->boxes[i].p1.x = clip->boxes[i].p1.x + fx;
+ copy->boxes[i].p2.x = clip->boxes[i].p2.x + fx;
+ copy->boxes[i].p1.y = clip->boxes[i].p1.y + fy;
+ copy->boxes[i].p2.y = clip->boxes[i].p2.y + fy;
}
-
- prev = prev->prev;
+ copy->num_boxes = clip->num_boxes;
}
- *tx = clip_extents->x;
- *ty = clip_extents->y;
- cairo_surface_destroy (clip_path->surface);
- return clip_path->surface = surface;
-
- BAIL:
- cairo_surface_destroy (surface);
- return _cairo_surface_create_in_error (status);
-}
-
-cairo_bool_t
-_cairo_clip_contains_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rect)
-{
- cairo_clip_path_t *clip_path;
-
- /* clip == NULL means no clip, so the clip contains everything */
- if (clip == NULL)
- return TRUE;
-
- clip_path = clip->path;
- if (clip_path->extents.x > rect->x ||
- clip_path->extents.y > rect->y ||
- clip_path->extents.x + clip_path->extents.width < rect->x + rect->width ||
- clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
- {
- return FALSE;
- }
+ copy->extents = clip->extents;
+ copy->extents.x += tx;
+ copy->extents.y += ty;
- do {
- cairo_box_t box;
-
- if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
- return FALSE;
-
- if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
- return FALSE;
-
- if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
- box.p1.y > _cairo_fixed_from_int (rect->y) ||
- box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
- box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
- {
- return FALSE;
- }
- } while ((clip_path = clip_path->prev) != NULL);
+ if (clip->path == NULL)
+ return copy;
- return TRUE;
+ return _cairo_clip_path_copy_with_translation (copy, clip->path, fx, fy);
}
cairo_bool_t
-_cairo_clip_contains_extents (cairo_clip_t *clip,
+_cairo_clip_contains_extents (const cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
const cairo_rectangle_int_t *rect;
@@ -1155,149 +336,57 @@ _cairo_clip_contains_extents (cairo_clip_t *clip,
}
void
-_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
+_cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip)
{
- cairo_clip_path_t *clip_path;
+ int i;
if (clip == NULL) {
fprintf (stream, "no clip\n");
return;
}
- if (clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (clip)) {
fprintf (stream, "clip: all-clipped\n");
return;
}
- if (clip->path == NULL) {
- fprintf (stream, "clip: empty\n");
- return;
- }
-
fprintf (stream, "clip:\n");
+ fprintf (stream, " extents: (%d, %d) x (%d, %d)",
+ clip->extents.x, clip->extents.y,
+ clip->extents.width, clip->extents.height);
- clip_path = clip->path;
- do {
- fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
- clip_path->region == NULL ? "no" : "yes",
- clip_path->surface == NULL ? "no" : "yes",
- clip_path->antialias,
- clip_path->tolerance,
- clip_path->fill_rule);
- _cairo_debug_print_path (stream, &clip_path->path);
- fprintf (stream, "\n");
- } while ((clip_path = clip_path->prev) != NULL);
-}
-
-cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty)
-{
- /* XXX is_clear -> all_clipped */
- assert (clip->path != NULL);
- return _cairo_clip_path_get_surface (clip->path, target, tx, ty);
-}
-
-cairo_status_t
-_cairo_clip_combine_with_surface (cairo_clip_t *clip,
- cairo_surface_t *dst,
- int dst_x, int dst_y)
-{
- cairo_clip_path_t *clip_path = clip->path;
- cairo_bool_t need_translate;
- cairo_status_t status;
-
- assert (clip_path != NULL);
-
- need_translate = dst_x | dst_y;
- do {
- if (clip_path->surface != NULL &&
- clip_path->surface->backend == dst->backend)
- {
- cairo_surface_pattern_t pattern;
-
- _cairo_pattern_init_for_surface (&pattern, clip_path->surface);
- cairo_matrix_init_translate (&pattern.base.matrix,
- dst_x - clip_path->extents.x,
- dst_y - clip_path->extents.y);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
- status = _cairo_surface_paint (dst,
- CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL);
-
- _cairo_pattern_fini (&pattern.base);
-
- return status;
- }
-
- if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- continue;
- }
-
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (-dst_x),
- _cairo_fixed_from_int (-dst_y));
- }
- status = _cairo_surface_fill (dst,
- CAIRO_OPERATOR_IN,
- &_cairo_pattern_white.base,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (dst_x),
- _cairo_fixed_from_int (dst_y));
- }
-
- if (unlikely (status))
- return status;
- } while ((clip_path = clip_path->prev) != NULL);
+ fprintf (stream, " num_boxes = %d\n", clip->num_boxes);
+ for (i = 0; i < clip->num_boxes; i++) {
+ fprintf (stream, " [%d] = (%f, %f), (%f, %f)\n", i,
+ _cairo_fixed_to_double (clip->boxes[i].p1.x),
+ _cairo_fixed_to_double (clip->boxes[i].p1.y),
+ _cairo_fixed_to_double (clip->boxes[i].p2.x),
+ _cairo_fixed_to_double (clip->boxes[i].p2.y));
+ }
- return CAIRO_STATUS_SUCCESS;
+ if (clip->path) {
+ cairo_clip_path_t *clip_path = clip->path;
+ do {
+ fprintf (stream, "path: aa=%d, tolerance=%f, rule=%d: ",
+ clip_path->antialias,
+ clip_path->tolerance,
+ clip_path->fill_rule);
+ _cairo_debug_print_path (stream, &clip_path->path);
+ fprintf (stream, "\n");
+ } while ((clip_path = clip_path->prev) != NULL);
+ }
}
-static const cairo_rectangle_int_t _cairo_empty_rectangle_int = { 0, 0, 0, 0 };
-
const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip)
{
- if (clip->all_clipped)
- return &_cairo_empty_rectangle_int;
-
- if (clip->path == NULL)
- return NULL;
-
- return &clip->path->extents;
-}
-
-void
-_cairo_clip_drop_cache (cairo_clip_t *clip)
-{
- cairo_clip_path_t *clip_path;
-
- if (clip->path == NULL)
- return;
+ if (clip == NULL)
+ return &_cairo_unbounded_rectangle;
- clip_path = clip->path;
- do {
- if (clip_path->region != NULL) {
- cairo_region_destroy (clip_path->region);
- clip_path->region = NULL;
- }
+ if (_cairo_clip_is_all_clipped (clip))
+ return &_cairo_empty_rectangle;
- if (clip_path->surface != NULL) {
- cairo_surface_destroy (clip_path->surface);
- clip_path->surface = NULL;
- }
-
- clip_path->flags &= ~CAIRO_CLIP_PATH_HAS_REGION;
- } while ((clip_path = clip_path->prev) != NULL);
+ return &clip->extents;
}
const cairo_rectangle_list_t _cairo_rectangles_nil =
@@ -1329,145 +418,6 @@ _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
return is_tight;
}
-cairo_int_status_t
-_cairo_clip_get_region (cairo_clip_t *clip,
- cairo_region_t **region)
-{
- cairo_int_status_t status;
-
- if (clip->all_clipped)
- goto CLIPPED;
-
- assert (clip->path != NULL);
-
- status = _cairo_clip_path_to_region (clip->path);
- if (status)
- return status;
-
- if (cairo_region_is_empty (clip->path->region)) {
- _cairo_clip_set_all_clipped (clip);
- goto CLIPPED;
- }
-
- if (region)
- *region = clip->path->region;
- return CAIRO_STATUS_SUCCESS;
-
- CLIPPED:
- if (region)
- *region = NULL;
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-}
-
-cairo_int_status_t
-_cairo_clip_get_boxes (cairo_clip_t *clip,
- cairo_box_t **boxes,
- int *count)
-{
- cairo_int_status_t status;
-
- if (clip->all_clipped)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
- assert (clip->path != NULL);
-
- status = _cairo_clip_path_to_boxes (clip->path, boxes, count);
- if (status)
- return status;
-
- if (*count == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
- return
- _cairo_fixed_is_integer (box->p1.x) &&
- _cairo_fixed_is_integer (box->p1.y) &&
- _cairo_fixed_is_integer (box->p2.x) &&
- _cairo_fixed_is_integer (box->p2.y);
-}
-
-static void
-intersect_with_boxes (cairo_composite_rectangles_t *extents,
- cairo_box_t *boxes,
- int num_boxes)
-{
- cairo_rectangle_int_t rect;
- cairo_box_t box;
- int i;
-
- assert (num_boxes > 0);
-
- /* Find the extents over all the clip boxes */
- box = boxes[0];
- for (i = 1; i < num_boxes; i++) {
- if (boxes[i].p1.x < box.p1.x)
- box.p1.x = boxes[i].p1.x;
- if (boxes[i].p1.y < box.p1.y)
- box.p1.y = boxes[i].p1.y;
-
- if (boxes[i].p2.x > box.p2.x)
- box.p2.x = boxes[i].p2.x;
- if (boxes[i].p2.y > box.p2.y)
- box.p2.y = boxes[i].p2.y;
- }
-
- _cairo_box_round_to_rectangle (&box, &rect);
- _cairo_rectangle_intersect (&extents->bounded, &rect);
- _cairo_rectangle_intersect (&extents->unbounded, &rect);
-}
-
-cairo_status_t
-_cairo_clip_to_boxes (cairo_clip_t **clip,
- cairo_composite_rectangles_t *extents,
- cairo_box_t **boxes,
- int *num_boxes)
-{
- cairo_status_t status;
- const cairo_rectangle_int_t *rect;
-
- rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
- if (*clip == NULL)
- goto EXTENTS;
-
- status = _cairo_clip_rectangle (*clip, rect);
- if (unlikely (status))
- return status;
-
- status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
- switch ((int) status) {
- case CAIRO_STATUS_SUCCESS:
- intersect_with_boxes (extents, *boxes, *num_boxes);
- if (rect->width == 0 || rect->height == 0 ||
- extents->is_bounded ||
- (*num_boxes == 1 && box_is_aligned (*boxes)))
- {
- *clip = NULL;
- }
- goto DONE;
-
- case CAIRO_INT_STATUS_UNSUPPORTED:
- goto EXTENTS;
-
- default:
- return status;
- }
-
- EXTENTS:
- status = CAIRO_STATUS_SUCCESS;
- _cairo_box_from_rectangle (&(*boxes)[0], rect);
- *num_boxes = 1;
- DONE:
- return status;
-}
-
cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status)
{
@@ -1499,24 +449,18 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
cairo_region_t *region = NULL;
- cairo_int_status_t status;
int n_rects = 0;
int i;
- if (clip->all_clipped)
- goto DONE;
-
- if (!clip->path)
+ if (clip == NULL)
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- status = _cairo_clip_get_region (clip, &region);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+ if (_cairo_clip_is_all_clipped (clip))
goto DONE;
- } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- } else if (unlikely (status)) {
- return ERROR_LIST (status);
- }
+
+ region = _cairo_clip_get_region (clip);
+ if (region == NULL)
+ return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
n_rects = cairo_region_num_rectangles (region);
if (n_rects) {