summaryrefslogtreecommitdiff
path: root/src/cairo-clip.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-02-12 12:20:35 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2010-02-12 12:24:01 +0000
commit5390df961f6dff8e25e5aac21062026a81710d88 (patch)
tree93f8fb3c7616d8b315e6fec8ca8c8f49c9b9f0e8 /src/cairo-clip.c
parent51047483f462a905567b42275ae061ead4df0a07 (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.c84
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)
{