[PATCH 1/2] XCB: Work around wrong extent computation in the X server [v4]

Uli Schlachter psychon at znc.in
Sat Nov 27 12:52:59 PST 2010

The X server calculates the bounding box for traps and then allocates a
temporary picture for this. When the X server calculates different values than
cairo got in extents->bounded, unbounded operators will have wrong results. The
X server only ever calculates bounds that are larger than the correct values.

Fix this by explicitly clipping the drawing to the expected bounds.

Thanks to Andrea Canciani for pointing out how to avoid a memory allocation by
using _cairo_region_init_rectangle and a lot more feedback.

This fixes the clip-fill-{eo,nz}-unbounded and clip-stroke-unbounded tests.

Signed-off-by: Uli Schlachter <psychon at znc.in>
Reviewed-by: Andrea Canciani <ranma42 at gmail.com>
 src/cairo-xcb-surface-render.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index f712818..f90d6c8 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -2391,6 +2391,7 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
     cairo_status_t status;
     cairo_region_t *clip_region = NULL;
+    cairo_region_t extents_region;
     cairo_bool_t need_clip_surface = FALSE;
     if (clip != NULL) {
@@ -2414,6 +2415,14 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 	    if (unlikely (is_empty && extents->is_bounded))
+    } else if (!extents->is_bounded) {
+	/* The X server will estimate the affected region of the unbounded
+	 * operation and will apply the operation to that rectangle.
+	 * However, there are cases where this estimate is too high (e.g.
+	 * the test suite's clip-fill-{eo,nz}-unbounded tests).
+	 */
+	_cairo_region_init_rectangle (&extents_region, &extents->unbounded);
+	clip_region = &extents_region;
     status = _cairo_xcb_connection_acquire (dst->connection);
@@ -2482,6 +2491,8 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
     if (clip_region != NULL)
 	_cairo_xcb_surface_clear_clip_region (dst);
+    if (clip_region == &extents_region)
+	_cairo_region_fini (&extents_region);
     _cairo_xcb_connection_release (dst->connection);

Content-Type: text/x-diff;
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;

More information about the cairo mailing list