[prev in list] [next in list] [prev in thread] [next in thread]
List: cairo
Subject: [cairo] 32 bit regions
From: Soeren Sandmann <sandmann () daimi ! au ! dk>
Date: 2008-06-10 22:25:41
Message-ID: ye8r6b5gc62.fsf () camel08 ! daimi ! au ! dk
[Download RAW message or body]
Hi,
Pixman 0.11.4 has 32 bit regions, and cairo should take advantage of
that, so I created a region32 branch and ported cairo_region_t to make
use them.
The branch also contains a new test that attempts to clip to a
rectangle that doesn't fit in 16 bits. With master it fails; with 32
bit regions it passes.
With the 32 bit regions, the XFAIL test large-source *almost* passes -
the reason it still fails is that the X server rejects a pixmap
created with BadAlloc. I believe this is actually a bug in the X
server[1].
I am attaching the only two commits that could conceivably be
controversial; unless I hear otherwise, I'll merge the branch soon.
Soren
[1] Introduced by me when fixing an integer overflow bug, and
incorrectly deciding that nobody would possibly want a pixmap larger
than 32768 pixels in any dimension - or something like that.
["0003-Use-32-bit-pixman-regions-for-cairo_region_t.patch" (text/x-patch)]
From 75fdccc1db2d78a546528164054a54509dac1490 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Søren Sandmann?= <sandmann@redhat.com>
Date: Mon, 9 Jun 2008 00:43:47 -0400
Subject: [PATCH] Use 32 bit pixman regions for cairo_region_t
---
src/cairo-image-surface.c | 2 +-
src/cairo-region-private.h | 2 +-
src/cairo-region.c | 38 +++++++++++++++++++-------------------
3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index cd80aed..d25cb96 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1193,7 +1193,7 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
- if (! pixman_image_set_clip_region (surface->pixman_image, ®ion->rgn))
+ if (! pixman_image_set_clip_region32 (surface->pixman_image, ®ion->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
surface->has_clip = region != NULL;
diff --git a/src/cairo-region-private.h b/src/cairo-region-private.h
index 4e2d723..53c1e8a 100644
--- a/src/cairo-region-private.h
+++ b/src/cairo-region-private.h
@@ -44,7 +44,7 @@
/* #cairo_region_t is defined in cairoint.h */
struct _cairo_region {
- pixman_region16_t rgn;
+ pixman_region32_t rgn;
};
cairo_private void
diff --git a/src/cairo-region.c b/src/cairo-region.c
index d78628e..746b3b1 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -40,14 +40,14 @@
void
_cairo_region_init (cairo_region_t *region)
{
- pixman_region_init (®ion->rgn);
+ pixman_region32_init (®ion->rgn);
}
void
_cairo_region_init_rect (cairo_region_t *region,
cairo_rectangle_int_t *rect)
{
- pixman_region_init_rect (®ion->rgn,
+ pixman_region32_init_rect (®ion->rgn,
rect->x, rect->y,
rect->width, rect->height);
}
@@ -57,13 +57,13 @@ _cairo_region_init_boxes (cairo_region_t *region,
cairo_box_int_t *boxes,
int count)
{
- pixman_box16_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box16_t)];
- pixman_box16_t *pboxes = stack_pboxes;
+ pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
+ pixman_box32_t *pboxes = stack_pboxes;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
int i;
if (count > ARRAY_LENGTH(stack_pboxes)) {
- pboxes = _cairo_malloc_ab (count, sizeof(pixman_box16_t));
+ pboxes = _cairo_malloc_ab (count, sizeof(pixman_box32_t));
if (pboxes == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@@ -75,7 +75,7 @@ _cairo_region_init_boxes (cairo_region_t *region,
pboxes[i].y2 = boxes[i].p2.y;
}
- if (!pixman_region_init_rects (®ion->rgn, pboxes, count))
+ if (!pixman_region32_init_rects (®ion->rgn, pboxes, count))
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (pboxes != stack_pboxes)
@@ -87,13 +87,13 @@ _cairo_region_init_boxes (cairo_region_t *region,
void
_cairo_region_fini (cairo_region_t *region)
{
- pixman_region_fini (®ion->rgn);
+ pixman_region32_fini (®ion->rgn);
}
cairo_int_status_t
_cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
{
- if (!pixman_region_copy (&dst->rgn, &src->rgn))
+ if (!pixman_region32_copy (&dst->rgn, &src->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@@ -102,18 +102,18 @@ _cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
int
_cairo_region_num_boxes (cairo_region_t *region)
{
- return pixman_region_n_rects (®ion->rgn);
+ return pixman_region32_n_rects (®ion->rgn);
}
cairo_int_status_t
_cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes)
{
int nboxes;
- pixman_box16_t *pboxes;
+ pixman_box32_t *pboxes;
cairo_box_int_t *cboxes;
int i;
- pboxes = pixman_region_rectangles (®ion->rgn, &nboxes);
+ pboxes = pixman_region32_rectangles (®ion->rgn, &nboxes);
if (nboxes == 0) {
*num_boxes = 0;
@@ -154,7 +154,7 @@ _cairo_region_boxes_fini (cairo_region_t *region, cairo_box_int_t *boxes)
void
_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
{
- pixman_box16_t *pextents = pixman_region_extents (®ion->rgn);
+ pixman_box32_t *pextents = pixman_region32_extents (®ion->rgn);
extents->x = pextents->x1;
extents->y = pextents->y1;
@@ -165,7 +165,7 @@ _cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extent
cairo_int_status_t
_cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
- if (!pixman_region_subtract (&dst->rgn, &a->rgn, &b->rgn))
+ if (!pixman_region32_subtract (&dst->rgn, &a->rgn, &b->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@@ -174,7 +174,7 @@ _cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *
cairo_int_status_t
_cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
- if (!pixman_region_intersect (&dst->rgn, &a->rgn, &b->rgn))
+ if (!pixman_region32_intersect (&dst->rgn, &a->rgn, &b->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@@ -185,7 +185,7 @@ _cairo_region_union_rect (cairo_region_t *dst,
cairo_region_t *src,
cairo_rectangle_int_t *rect)
{
- if (!pixman_region_union_rect (&dst->rgn, &src->rgn,
+ if (!pixman_region32_union_rect (&dst->rgn, &src->rgn,
rect->x, rect->y,
rect->width, rect->height))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -196,25 +196,25 @@ _cairo_region_union_rect (cairo_region_t *dst,
cairo_bool_t
_cairo_region_not_empty (cairo_region_t *region)
{
- return (cairo_bool_t) pixman_region_not_empty (®ion->rgn);
+ return (cairo_bool_t) pixman_region32_not_empty (®ion->rgn);
}
void
_cairo_region_translate (cairo_region_t *region,
int x, int y)
{
- pixman_region_translate (®ion->rgn, x, y);
+ pixman_region32_translate (®ion->rgn, x, y);
}
pixman_region_overlap_t
_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *rect)
{
- pixman_box16_t pbox;
+ pixman_box32_t pbox;
pbox.x1 = rect->x;
pbox.y1 = rect->y;
pbox.x2 = rect->x + rect->width;
pbox.y2 = rect->y + rect->height;
- return pixman_region_contains_rectangle (®ion->rgn, &pbox);
+ return pixman_region32_contains_rectangle (®ion->rgn, &pbox);
}
--
1.5.4.5
["0004-Fix-xlib-incarnation-of-the-large-clip-bug.patch" (text/x-patch)]
From c3121543f87e372d18aaa5b8a132d28bcc4bf450 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Søren Sandmann?= <sandmann@redhat.com>
Date: Mon, 9 Jun 2008 01:11:38 -0400
Subject: [PATCH] Fix xlib incarnation of the large-clip bug.
Intersect the clip region with the bounds of the surface to prevent
overflows when converting from 32 to 16 bits.
---
src/cairo-xlib-surface.c | 29 ++++++++++++++++++++++++++---
1 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 7397573..0c29968 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1995,15 +1995,36 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
cairo_status_t status;
XRectangle *rects = NULL;
int n_boxes, i;
+ cairo_rectangle_int_t rect;
+ cairo_region_t bound, bounded;
+
+ rect.x = rect.y = 0;
+ rect.width = surface->width;
+ rect.height = surface->height;
+
+ /* Intersect the region with the bounds of the surface. This
+ * is necessary so we don't wrap around when we convert cairo's
+ * 32 bit region into 16 bit rectangles.
+ */
+ _cairo_region_init_rect (&bound, &rect);
+ _cairo_region_init (&bounded);
+ status = _cairo_region_intersect (&bounded, &bound, region);
+ if (status) {
+ _cairo_region_fini (&bound);
+ _cairo_region_fini (&bounded);
+ return status;
+ }
- status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
+ status = _cairo_region_get_boxes (&bounded, &n_boxes, &boxes);
if (status)
return status;
if (n_boxes > ARRAY_LENGTH (surface->embedded_clip_rects)) {
rects = _cairo_malloc_ab (n_boxes, sizeof (XRectangle));
if (rects == NULL) {
- _cairo_region_boxes_fini (region, boxes);
+ _cairo_region_boxes_fini (&bounded, boxes);
+ _cairo_region_fini (&bound);
+ _cairo_region_fini (&bounded);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
} else {
@@ -2017,7 +2038,9 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
}
- _cairo_region_boxes_fini (region, boxes);
+ _cairo_region_boxes_fini (&bounded, boxes);
+ _cairo_region_fini (&bounded);
+ _cairo_region_fini (&bound);
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
--
1.5.4.5
_______________________________________________
cairo mailing list
cairo@cairographics.org
http://lists.cairographics.org/mailman/listinfo/cairo
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic