diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-02-12 12:20:35 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-02-12 12:24:01 +0000 |
commit | 5390df961f6dff8e25e5aac21062026a81710d88 (patch) | |
tree | 93f8fb3c7616d8b315e6fec8ca8c8f49c9b9f0e8 /src/cairo-clip.c | |
parent | 51047483f462a905567b42275ae061ead4df0a07 (diff) |
clip: Restrict composite extents to clip extents
Fixes test/clip-rectangle-twice.
Diffstat (limited to 'src/cairo-clip.c')
-rw-r--r-- | src/cairo-clip.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/cairo-clip.c b/src/cairo-clip.c index abcf6595..fdb94701 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -1335,6 +1335,90 @@ _cairo_clip_get_boxes (cairo_clip_t *clip, 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; + cairo_bool_t is_empty; + + box.p1.x = box.p1.y = INT_MIN; + box.p2.x = box.p2.y = INT_MAX; + while (num_boxes--) { + if (boxes->p1.x < box.p1.x) + box.p1.x = boxes->p1.x; + if (boxes->p1.y < box.p1.y) + box.p1.y = boxes->p1.y; + + if (boxes->p2.x > box.p2.x) + box.p2.x = boxes->p2.x; + if (boxes->p2.y > box.p2.y) + box.p2.y = boxes->p2.y; + } + + _cairo_box_round_to_rectangle (&box, &rect); + is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect); + is_empty = _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; +} + + static cairo_rectangle_list_t * _cairo_rectangle_list_create_in_error (cairo_status_t status) { |