[cairo-commit] Branch '1.8' - 6 commits - src/cairo-analysis-surface.c src/cairo-clip.c src/cairo-gstate.c src/cairoint.h src/cairo-pattern.c src/cairo-rectangle.c src/cairo-region.c src/cairo-region-private.h src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c test/clip-operator-pdf-argb32-ref.png test/clip-operator-pdf-rgb24-ref.png test/Makefile.am test/operator-clear-pdf-argb32-ref.png test/operator-clear-pdf-rgb24-ref.png test/operator-source-pdf-argb32-ref.png test/operator-source-pdf-rgb24-ref.png test/user-font-mask-pdf-ref.png test/user-font-mask-ps2-ref.png test/user-font-mask-ps3-ref.png test/user-font-mask-svg11-ref.png

Chris Wilson ickle at kemper.freedesktop.org
Thu Oct 30 09:58:26 PDT 2008


 src/cairo-analysis-surface.c            |   54 +++++++++++++++--------
 src/cairo-clip.c                        |   43 +++++++++---------
 src/cairo-gstate.c                      |   73 ++++++++++++++++++++++----------
 src/cairo-pattern.c                     |   21 +++++----
 src/cairo-rectangle.c                   |   37 +++++++++-------
 src/cairo-region-private.h              |    3 -
 src/cairo-region.c                      |    3 -
 src/cairo-surface-fallback.c            |   31 ++++++++-----
 src/cairo-surface.c                     |   27 ++++++-----
 src/cairo-win32-surface.c               |    4 -
 src/cairo-xcb-surface.c                 |   56 +++++++-----------------
 src/cairo-xlib-surface.c                |   52 +++++++---------------
 src/cairoint.h                          |    5 +-
 test/Makefile.am                        |   15 ++----
 test/clip-operator-pdf-argb32-ref.png   |binary
 test/clip-operator-pdf-rgb24-ref.png    |binary
 test/operator-clear-pdf-argb32-ref.png  |binary
 test/operator-clear-pdf-rgb24-ref.png   |binary
 test/operator-source-pdf-argb32-ref.png |binary
 test/operator-source-pdf-rgb24-ref.png  |binary
 test/user-font-mask-pdf-ref.png         |binary
 test/user-font-mask-ps2-ref.png         |binary
 test/user-font-mask-ps3-ref.png         |binary
 test/user-font-mask-svg11-ref.png       |binary
 24 files changed, 228 insertions(+), 196 deletions(-)

New commits:
commit ab15d7627506a837fea7101661425bb923ef5b4f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 30 16:54:23 2008 +0000

    [test] Remove XFAIL from user-font-mask
    
    user-font-mask should PASS modulo the scaling anomalies in the external
    renderers, so remove it from the XFAIL list.

diff --git a/test/Makefile.am b/test/Makefile.am
index eaeff9a..887bd73 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -938,7 +938,11 @@ REFERENCE_IMAGES = \
 	user-font-ps3-ref.png \
 	user-font-svg12-ref.png	\
 	user-font-svg11-ref.png	\
-	user-font-mask-ref.png	\
+	user-font-mask-ref.png		\
+	user-font-mask-pdf-ref.png	\
+	user-font-mask-ps2-ref.png	\
+	user-font-mask-ps3-ref.png	\
+	user-font-mask-svg11-ref.png	\
 	user-font-proxy-ref.png	\
 	user-font-proxy-pdf-ref.png	\
 	user-font-proxy-ps2-ref.png	\
@@ -1017,13 +1021,6 @@ $(REFERENCE_IMAGES)
 #                         /Interpolate support - which causes a half-pixel
 #                         shift in GS (and consequently virtually every
 #                         image/fallback-image using test to FAIL).
-# user-font-mask	- Two bugs here: an unsigned promotion issue and
-#			  non-negative pattern extents. Chris claims
-#			  to have fixes in hand for both, but doesn't
-#			  feel comfortable pushing them just before
-#			  the 1.8.2 release. So if 1.9.x is open and
-#			  this comment is still here, please pester
-#			  Chris.
 XFAIL_TESTS =					\
 alpha-similar$(EXEEXT)				\
 big-line$(EXEEXT)				\
@@ -1040,7 +1037,7 @@ surface-pattern$(EXEEXT)			\
 surface-pattern-big-scale-down$(EXEEXT)		\
 surface-pattern-scale-down$(EXEEXT)		\
 surface-pattern-scale-up$(EXEEXT)		\
-user-font-mask$(EXEEXT)
+$(NULL)
 
 # Any test that doesn't generate a log file goes here
 NOLOG_TESTS =			\
diff --git a/test/user-font-mask-pdf-ref.png b/test/user-font-mask-pdf-ref.png
new file mode 100644
index 0000000..ebf1485
Binary files /dev/null and b/test/user-font-mask-pdf-ref.png differ
diff --git a/test/user-font-mask-ps2-ref.png b/test/user-font-mask-ps2-ref.png
new file mode 100644
index 0000000..ebf1485
Binary files /dev/null and b/test/user-font-mask-ps2-ref.png differ
diff --git a/test/user-font-mask-ps3-ref.png b/test/user-font-mask-ps3-ref.png
new file mode 100644
index 0000000..ebf1485
Binary files /dev/null and b/test/user-font-mask-ps3-ref.png differ
diff --git a/test/user-font-mask-svg11-ref.png b/test/user-font-mask-svg11-ref.png
new file mode 100644
index 0000000..55006bf
Binary files /dev/null and b/test/user-font-mask-svg11-ref.png differ
commit 540f555840ba4076e3ab86669daf9bee5695afa2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 14:38:44 2008 +0100

    [analysis] Only limit to mask extends if bounded by mask.
    
    The extents of cairo_mask() is only limited to the mask if the operation
    is bounded by the mask.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 90eb3f5..057be52 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -416,12 +416,16 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 	    return status;
 
 	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+    }
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t mask_extents;
 
-	status = _cairo_pattern_get_extents (mask, &source_extents);
+	status = _cairo_pattern_get_extents (mask, &mask_extents);
 	if (status)
 	    return status;
 
-	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
 
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
diff --git a/test/clip-operator-pdf-argb32-ref.png b/test/clip-operator-pdf-argb32-ref.png
index b00cc00..b3ee143 100644
Binary files a/test/clip-operator-pdf-argb32-ref.png and b/test/clip-operator-pdf-argb32-ref.png differ
diff --git a/test/clip-operator-pdf-rgb24-ref.png b/test/clip-operator-pdf-rgb24-ref.png
index f9377fa..b420f38 100644
Binary files a/test/clip-operator-pdf-rgb24-ref.png and b/test/clip-operator-pdf-rgb24-ref.png differ
diff --git a/test/operator-clear-pdf-argb32-ref.png b/test/operator-clear-pdf-argb32-ref.png
index d36de27..06fc51e 100644
Binary files a/test/operator-clear-pdf-argb32-ref.png and b/test/operator-clear-pdf-argb32-ref.png differ
diff --git a/test/operator-clear-pdf-rgb24-ref.png b/test/operator-clear-pdf-rgb24-ref.png
index 2dec75c..55b44ad 100644
Binary files a/test/operator-clear-pdf-rgb24-ref.png and b/test/operator-clear-pdf-rgb24-ref.png differ
diff --git a/test/operator-source-pdf-argb32-ref.png b/test/operator-source-pdf-argb32-ref.png
index 821112a..f110ff2 100644
Binary files a/test/operator-source-pdf-argb32-ref.png and b/test/operator-source-pdf-argb32-ref.png differ
diff --git a/test/operator-source-pdf-rgb24-ref.png b/test/operator-source-pdf-rgb24-ref.png
index 6faf143..c6b7170 100644
Binary files a/test/operator-source-pdf-rgb24-ref.png and b/test/operator-source-pdf-rgb24-ref.png differ
commit 4b2998893930e4bab19646e6f0a0c8d2a47f12a2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 14:34:30 2008 +0100

    Review users of cairo_rectangle_int_t for incorrect unsigned promotion.
    
    Adrian Johnson discovered cases where we mistakenly compared the result
    of unsigned arithmetic where we need signed quantities. Look for similar
    cases in the users of cairo_rectangle_int_t.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 5093459..90eb3f5 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -285,6 +285,7 @@ _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     double                    x1, y1, x2, y2;
     cairo_rectangle_int_t   extent;
+    cairo_bool_t is_empty;
 
     if (path == NULL) {
 	surface->current_clip.x = 0;
@@ -303,7 +304,7 @@ _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 	extent.width  = ceil (x2) - extent.x;
 	extent.height = ceil (y2) - extent.y;
 
-	_cairo_rectangle_intersect (&surface->current_clip, &extent);
+	is_empty = _cairo_rectangle_intersect (&surface->current_clip, &extent);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -326,6 +327,7 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t  extents;
+    cairo_bool_t is_empty;
 
     if (!surface->target->backend->paint)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -342,14 +344,15 @@ _cairo_analysis_surface_paint (void			*abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -365,6 +368,7 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_int_status_t	      status, backend_status;
     cairo_rectangle_int_t   extents;
+    cairo_bool_t is_empty;
 
     if (!surface->target->backend->mask)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -411,16 +415,16 @@ _cairo_analysis_surface_mask (void		*abstract_surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
 
 	status = _cairo_pattern_get_extents (mask, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     status = _add_operation (surface, &extents, backend_status);
 
@@ -441,7 +445,8 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_traps_t            traps;
-    cairo_rectangle_int_t  extents;
+    cairo_rectangle_int_t    extents;
+    cairo_bool_t             is_empty;
 
     if (!surface->target->backend->stroke)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -460,14 +465,15 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_box_t box;
@@ -509,7 +515,8 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_traps_t            traps;
-    cairo_rectangle_int_t  extents;
+    cairo_rectangle_int_t    extents;
+    cairo_bool_t             is_empty;
 
     if (!surface->target->backend->fill)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -527,14 +534,15 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_box_t box;
@@ -575,6 +583,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
+    cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
     if (surface->target->backend->show_glyphs)
@@ -603,14 +612,15 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
@@ -620,7 +630,7 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &glyph_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
 
     status = _add_operation (surface, &extents, backend_status);
@@ -652,6 +662,7 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
+    cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
     backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -684,14 +695,15 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
@@ -701,7 +713,7 @@ _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &glyph_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
 
     status = _add_operation (surface, &extents, backend_status);
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 308da32..8a0d4db 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -166,7 +166,8 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
         _cairo_traps_fini (&traps);
 
         _cairo_box_round_to_rectangle (&extents, &extents_rect);
-        _cairo_rectangle_intersect (rectangle, &extents_rect);
+        if (! _cairo_rectangle_intersect (rectangle, &extents_rect))
+	    return CAIRO_STATUS_SUCCESS;
 
         clip_path = clip_path->prev;
     }
@@ -178,6 +179,9 @@ cairo_status_t
 _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
 				    cairo_rectangle_int_t *rectangle)
 {
+    cairo_status_t status;
+    cairo_bool_t is_empty;
+
     if (!clip)
 	return CAIRO_STATUS_SUCCESS;
 
@@ -187,8 +191,6 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
     }
 
     if (clip->path) {
-        cairo_status_t status;
-
         status = _cairo_clip_path_intersect_to_rectangle (clip->path,
                                                           rectangle);
         if (status)
@@ -196,7 +198,6 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
     }
 
     if (clip->has_region) {
-	cairo_status_t status = CAIRO_STATUS_SUCCESS;
 	cairo_region_t intersection;
 
 	_cairo_region_init_rect (&intersection, rectangle);
@@ -214,7 +215,7 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
     }
 
     if (clip->surface)
-	_cairo_rectangle_intersect (rectangle, &clip->surface_rect);
+	is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -421,7 +422,7 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
     cairo_pattern_union_t pattern;
     cairo_box_t extents;
     cairo_rectangle_int_t surface_rect, target_rect;
-    cairo_surface_t *surface;
+    cairo_surface_t *surface = NULL;
     cairo_status_t status;
 
     if (clip->all_clipped)
@@ -434,22 +435,21 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
     _cairo_traps_extents (traps, &extents);
     _cairo_box_round_to_rectangle (&extents, &surface_rect);
 
-    if (clip->surface != NULL)
-	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);
+    if (clip->surface != NULL) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	    goto DONE;
+    }
 
     /* Intersect with the target surface rectangle so we don't use
      * more memory and time than we need to. */
     status = _cairo_surface_get_extents (target, &target_rect);
-    if (status == CAIRO_STATUS_SUCCESS)
-	_cairo_rectangle_intersect (&surface_rect, &target_rect);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &target_rect))
+	    goto DONE;
+    }
 
-    if (surface_rect.width == 0 || surface_rect.height == 0) {
-	surface = NULL;
-	status = CAIRO_STATUS_SUCCESS;
-	if (clip->surface != NULL)
-	    cairo_surface_destroy (clip->surface);
+    if (surface_rect.width == 0 || surface_rect.height == 0)
 	goto DONE;
-    }
 
     _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
 			       CAIRO_CONTENT_COLOR);
@@ -539,11 +539,10 @@ _cairo_clip_intersect_mask (cairo_clip_t      *clip,
 	    cairo_surface_destroy (surface);
 	    return status;
 	}
-
-	cairo_surface_destroy (clip->surface);
     }
 
  DONE:
+    cairo_surface_destroy (clip->surface);
     clip->surface = surface;
     clip->surface_rect = surface_rect;
     clip->serial = _cairo_surface_allocate_clip_serial (target);
@@ -740,10 +739,12 @@ _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
 
     double x1 = clip_rect->x;
     double y1 = clip_rect->y;
-    double x2 = clip_rect->x + clip_rect->width;
-    double y2 = clip_rect->y + clip_rect->height;
+    double x2 = clip_rect->x + (int) clip_rect->width;
+    double y2 = clip_rect->y + (int) clip_rect->height;
 
-    _cairo_gstate_backend_to_user_rectangle (gstate, &x1, &y1, &x2, &y2, &is_tight);
+    _cairo_gstate_backend_to_user_rectangle (gstate,
+					     &x1, &y1, &x2, &y2,
+					     &is_tight);
 
     user_rect->x = x1;
     user_rect->y = y1;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index e1b4693..fe8d279 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1785,8 +1785,8 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
 	     */
 	    x1 = surface_extents.x - 2*scale;
 	    y1 = surface_extents.y - 2*scale;
-	    x2 = surface_extents.x + surface_extents.width  + scale;
-	    y2 = surface_extents.y + surface_extents.height + scale;
+	    x2 = surface_extents.x + (int) surface_extents.width  + scale;
+	    y2 = surface_extents.y + (int) surface_extents.height + scale;
 	}
 
 	if (!drop)
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 83d371c..81fa62a 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1908,6 +1908,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 	attr->acquired = TRUE;
     } else {
 	cairo_rectangle_int_t extents;
+	cairo_bool_t is_empty;
 
 	status = _cairo_surface_get_extents (pattern->surface, &extents);
 	if (status)
@@ -1932,8 +1933,8 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 	    } else {
 		double x1 = x;
 		double y1 = y;
-		double x2 = x + width;
-		double y2 = y + height;
+		double x2 = x + (int) width;
+		double y2 = y + (int) height;
 
 		_cairo_matrix_transform_bounding_box  (&attr->matrix,
 						       &x1, &y1, &x2, &y2,
@@ -1950,9 +1951,11 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 	    sampled_area.y += ty;
 
 	    /* Never acquire a larger area than the source itself */
-	    _cairo_rectangle_intersect (&extents, &sampled_area);
+	    is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
 	}
 
+	/* XXX can we use is_empty? */
+
 	status = _cairo_surface_clone_similar (dst, pattern->surface,
 					       extents.x, extents.y,
 					       extents.width, extents.height,
@@ -2237,8 +2240,8 @@ _cairo_pattern_get_extents (cairo_pattern_t         *pattern,
 	_cairo_pattern_analyze_filter (surface_pattern, &pad);
 	x1 = surface_extents.x - pad;
 	y1 = surface_extents.y - pad;
-	x2 = surface_extents.x + surface_extents.width + pad;
-	y2 = surface_extents.y + surface_extents.height + pad;
+	x2 = surface_extents.x + (int) surface_extents.width  + pad;
+	y2 = surface_extents.y + (int) surface_extents.height + pad;
 
 	imatrix = pattern->matrix;
 	status = cairo_matrix_invert (&imatrix);
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index ec08db4..2143f0c 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -95,7 +95,7 @@ _cairo_box_round_to_rectangle (const cairo_box_t     *box,
     rectangle->height = _cairo_fixed_integer_ceil (box->p2.y) - rectangle->y;
 }
 
-void
+cairo_bool_t
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 			    const cairo_rectangle_int_t *src)
 {
@@ -114,11 +114,15 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 	dst->y = 0;
 	dst->width  = 0;
 	dst->height = 0;
+
+	return FALSE;
     } else {
 	dst->x = x1;
 	dst->y = y1;
 	dst->width  = x2 - x1;
 	dst->height = y2 - y1;
+
+	return TRUE;
     }
 }
 
diff --git a/src/cairo-region-private.h b/src/cairo-region-private.h
index 352a23f..588762e 100644
--- a/src/cairo-region-private.h
+++ b/src/cairo-region-private.h
@@ -108,7 +108,8 @@ _cairo_region_translate (cairo_region_t *region,
 			 int x, int y);
 
 cairo_private pixman_region_overlap_t
-_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box);
+_cairo_region_contains_rectangle (cairo_region_t *region,
+				  const cairo_rectangle_int_t *box);
 
 
 CAIRO_END_DECLS
diff --git a/src/cairo-region.c b/src/cairo-region.c
index 746b3b1..23a042f 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -207,7 +207,8 @@ _cairo_region_translate (cairo_region_t *region,
 }
 
 pixman_region_overlap_t
-_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *rect)
+_cairo_region_contains_rectangle (cairo_region_t *region,
+				  const cairo_rectangle_int_t *rect)
 {
     pixman_box32_t pbox;
 
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index c44dfaf..5b9c99a 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -548,7 +548,6 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
 
         if (has_trap_region) {
             status = _cairo_clip_intersect_to_region (clip, &trap_region);
-
             if (status)
                 goto out;
 
@@ -559,9 +558,12 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
             _cairo_box_round_to_rectangle (&trap_box, &trap_extents);
         }
 
-        _cairo_rectangle_intersect (&extents, &trap_extents);
-        status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+        if (! _cairo_rectangle_intersect (&extents, &trap_extents)) {
+	    status = CAIRO_STATUS_SUCCESS;
+	    goto out;
+	}
 
+        status = _cairo_clip_intersect_to_rectangle (clip, &extents);
         if (status)
             goto out;
     } else {
@@ -688,7 +690,8 @@ _cairo_surface_fallback_paint (cairo_surface_t	*surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	if (! _cairo_rectangle_intersect (&extents, &source_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@@ -756,7 +759,8 @@ _cairo_surface_fallback_mask (cairo_surface_t		*surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	if (! _cairo_rectangle_intersect (&extents, &source_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     if (_cairo_operator_bounded_by_mask (op)) {
@@ -764,7 +768,8 @@ _cairo_surface_fallback_mask (cairo_surface_t		*surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &mask_extents);
+	if (! _cairo_rectangle_intersect (&extents, &mask_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@@ -807,7 +812,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	if (! _cairo_rectangle_intersect (&extents, &source_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@@ -863,11 +869,13 @@ _cairo_surface_fallback_fill (cairo_surface_t		*surface,
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	if (! _cairo_rectangle_intersect (&extents, &source_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@@ -996,7 +1004,8 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
 	if (status)
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &glyph_extents);
+	if (! _cairo_rectangle_intersect (&extents, &glyph_extents))
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@@ -1142,9 +1151,9 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
 	if (rects[i].y < y1)
 	    y1 = rects[i].y;
 
-	if ((int)(rects[i].x + rects[i].width) > x2)
+	if ((int) (rects[i].x + rects[i].width) > x2)
 	    x2 = rects[i].x + rects[i].width;
-	if ((int)(rects[i].y + rects[i].height) > y2)
+	if ((int) (rects[i].y + rects[i].height) > y2)
 	    y2 = rects[i].y + rects[i].height;
     }
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index d1df186..609a0e0 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2388,7 +2388,6 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t         *dst,
     cairo_rectangle_int_t dst_rectangle;
     cairo_rectangle_int_t drawn_rectangle;
     cairo_bool_t has_drawn_region = FALSE;
-    cairo_bool_t has_clear_region = FALSE;
     cairo_region_t drawn_region;
     cairo_region_t clear_region;
     cairo_status_t status;
@@ -2400,36 +2399,40 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t         *dst,
     dst_rectangle.y = dst_y;
     dst_rectangle.width = width;
     dst_rectangle.height = height;
+    _cairo_region_init_rect (&clear_region, &dst_rectangle);
 
     drawn_rectangle = dst_rectangle;
 
-    if (src_rectangle)
-        _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
+    if (src_rectangle) {
+        if (! _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle))
+	    goto EMPTY;
+    }
 
-    if (mask_rectangle)
-        _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
+    if (mask_rectangle) {
+        if (! _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle))
+	    goto EMPTY;
+    }
 
     /* Now compute the area that is in dst_rectangle but not in drawn_rectangle
      */
     _cairo_region_init_rect (&drawn_region, &drawn_rectangle);
-    _cairo_region_init_rect (&clear_region, &dst_rectangle);
-
     has_drawn_region = TRUE;
-    has_clear_region = TRUE;
 
-    status = _cairo_region_subtract (&clear_region, &clear_region, &drawn_region);
+    status = _cairo_region_subtract (&clear_region,
+				     &clear_region,
+				     &drawn_region);
     if (status)
         goto CLEANUP_REGIONS;
 
+  EMPTY:
     status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
                                          CAIRO_COLOR_TRANSPARENT,
                                          &clear_region);
 
-CLEANUP_REGIONS:
+  CLEANUP_REGIONS:
     if (has_drawn_region)
         _cairo_region_fini (&drawn_region);
-    if (has_clear_region)
-        _cairo_region_fini (&clear_region);
+    _cairo_region_fini (&clear_region);
 
     return _cairo_surface_set_error (dst, status);
 }
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index a473c38..5787e26 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -638,9 +638,9 @@ _cairo_win32_surface_acquire_dest_image (void                    *abstract_surfa
 	x1 = interest_rect->x;
     if (interest_rect->y > y1)
 	y1 = interest_rect->y;
-    if (interest_rect->x + interest_rect->width < x2)
+    if ((int) (interest_rect->x + interest_rect->width) < x2)
 	x2 = interest_rect->x + interest_rect->width;
-    if (interest_rect->y + interest_rect->height < y2)
+    if ((int) (interest_rect->y + interest_rect->height) < y2)
 	y2 = interest_rect->y + interest_rect->height;
 
     if (x1 >= x2 || y1 >= y2) {
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 1760bcb..dede00f 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -302,45 +302,25 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
     cairo_image_surface_t *image;
     xcb_get_image_reply_t *imagerep;
     int bpp, bytes_per_line;
-    short x1, y1, x2, y2;
+    cairo_rectangle_int_t extents;
     unsigned char *data;
     cairo_format_masks_t masks;
     cairo_format_t format;
 
-    x1 = 0;
-    y1 = 0;
-    x2 = surface->width;
-    y2 = surface->height;
+    extents.x = 0;
+    extents.y = 0;
+    extents.width  = surface->width;
+    extents.height = surface->height;
 
     if (interest_rect) {
-	cairo_rectangle_int_t rect;
-
-	rect.x = interest_rect->x;
-	rect.y = interest_rect->y;
-	rect.width = interest_rect->width;
-	rect.height = interest_rect->height;
-
-	if (rect.x > x1)
-	    x1 = rect.x;
-	if (rect.y > y1)
-	    y1 = rect.y;
-	if (rect.x + rect.width < x2)
-	    x2 = rect.x + rect.width;
-	if (rect.y + rect.height < y2)
-	    y2 = rect.y + rect.height;
-
-	if (x1 >= x2 || y1 >= y2) {
+	if (! _cairo_rectangle_intersect (&extents, interest_rect)) {
 	    *image_out = NULL;
 	    return CAIRO_STATUS_SUCCESS;
 	}
     }
 
-    if (image_rect) {
-	image_rect->x = x1;
-	image_rect->y = y1;
-	image_rect->width = x2 - x1;
-	image_rect->height = y2 - y1;
-    }
+    if (image_rect)
+	*image_rect = extents;
 
     /* XXX: This should try to use the XShm extension if available */
 
@@ -350,8 +330,8 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
 	imagerep = xcb_get_image_reply(surface->dpy,
 				    xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
 						surface->drawable,
-						x1, y1,
-						x2 - x1, y2 - y1,
+						extents.x, extents.y,
+						extents.width, extents.height,
 						AllPlanes), &error);
 
 	/* If we get an error, the surface must have been a window,
@@ -380,17 +360,17 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
 			 surface->depth,
 			 pixmap,
 			 surface->drawable,
-			 x2 - x1, y2 - y1);
+			 extents.width, extents.height);
 	_cairo_xcb_surface_ensure_gc (surface);
 
 	xcb_copy_area (surface->dpy, surface->drawable, pixmap, surface->gc,
-		     x1, y1, 0, 0, x2 - x1, y2 - y1);
+		     extents.x, extents.y, 0, 0, extents.width, extents.height);
 
 	imagerep = xcb_get_image_reply(surface->dpy,
 				    xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
 						pixmap,
-						x1, y1,
-						x2 - x1, y2 - y1,
+						extents.x, extents.y,
+						extents.width, extents.height,
 						AllPlanes), 0);
 	xcb_free_pixmap (surface->dpy, pixmap);
 
@@ -447,8 +427,8 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
 	image = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (data,
 						 format,
-						 x2 - x1,
-						 y2 - y1,
+						 extents.width,
+						 extents.height,
 						 bytes_per_line);
 	if (image->base.status)
 	    goto FAIL;
@@ -462,8 +442,8 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
 	image = (cairo_image_surface_t *)
 	    _cairo_image_surface_create_with_masks (data,
 						    &masks,
-						    x2 - x1,
-						    y2 - y1,
+						    extents.width,
+						    extents.height,
 						    bytes_per_line);
 	if (image->base.status)
 	    goto FAIL;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 619eb36..ba38f5d 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -612,44 +612,24 @@ _get_image_surface (cairo_xlib_surface_t    *surface,
     cairo_int_status_t status;
     cairo_image_surface_t *image = NULL;
     XImage *ximage;
-    unsigned short x1, y1, x2, y2;
+    cairo_rectangle_int_t extents;
     pixman_format_code_t pixman_format;
     cairo_format_masks_t xlib_masks;
 
-    x1 = 0;
-    y1 = 0;
-    x2 = surface->width;
-    y2 = surface->height;
+    extents.x = 0;
+    extents.y = 0;
+    extents.width  = surface->width;
+    extents.height = surface->height;
 
     if (interest_rect) {
-	cairo_rectangle_int_t rect;
-
-	rect.x = interest_rect->x;
-	rect.y = interest_rect->y;
-	rect.width = interest_rect->width;
-	rect.height = interest_rect->height;
-
-	if (rect.x > x1)
-	    x1 = rect.x;
-	if (rect.y > y1)
-	    y1 = rect.y;
-	if (rect.x + rect.width < x2)
-	    x2 = rect.x + rect.width;
-	if (rect.y + rect.height < y2)
-	    y2 = rect.y + rect.height;
-
-	if (x1 >= x2 || y1 >= y2) {
+	if (! _cairo_rectangle_intersect (&extents, interest_rect)) {
 	    *image_out = NULL;
 	    return CAIRO_STATUS_SUCCESS;
 	}
     }
 
-    if (image_rect) {
-	image_rect->x = x1;
-	image_rect->y = y1;
-	image_rect->width = x2 - x1;
-	image_rect->height = y2 - y1;
-    }
+    if (image_rect)
+	*image_rect = extents;
 
     /* XXX: This should try to use the XShm extension if available */
 
@@ -661,8 +641,8 @@ _get_image_surface (cairo_xlib_surface_t    *surface,
 
 	ximage = XGetImage (surface->dpy,
 			    surface->drawable,
-			    x1, y1,
-			    x2 - x1, y2 - y1,
+			    extents.x, extents.y,
+			    extents.width, extents.height,
 			    AllPlanes, ZPixmap);
 
 	XSetErrorHandler (old_handler);
@@ -695,16 +675,18 @@ _get_image_surface (cairo_xlib_surface_t    *surface,
 
 	pixmap = XCreatePixmap (surface->dpy,
 				surface->drawable,
-				x2 - x1, y2 - y1,
+				extents.width, extents.height,
 				surface->depth);
 	if (pixmap) {
 	    XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
-		       x1, y1, x2 - x1, y2 - y1, 0, 0);
+		       extents.x, extents.y,
+		       extents.width, extents.height,
+		       0, 0);
 
 	    ximage = XGetImage (surface->dpy,
 				pixmap,
 				0, 0,
-				x2 - x1, y2 - y1,
+				extents.width, extents.height,
 				AllPlanes, ZPixmap);
 
 	    XFreePixmap (surface->dpy, pixmap);
@@ -807,8 +789,8 @@ _get_image_surface (cairo_xlib_surface_t    *surface,
 	data = cairo_image_surface_get_data (&image->base);
 	rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
 	row = (uint32_t *) data;
-	x0 = x1 + surface->base.device_transform.x0;
-	y0 = y1 + surface->base.device_transform.y0;
+	x0 = extents.x + surface->base.device_transform.x0;
+	y0 = extents.y + surface->base.device_transform.y0;
 	for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
 	     y < ximage->height;
 	     y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
diff --git a/src/cairoint.h b/src/cairoint.h
index 5172b9e..43c5ae8 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -253,7 +253,7 @@ cairo_private void
 _cairo_box_round_to_rectangle (const cairo_box_t     *box,
 			       cairo_rectangle_int_t *rectangle);
 
-cairo_private void
+cairo_private cairo_bool_t
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 			    const cairo_rectangle_int_t *src);
 
commit 0e4156121f05b14f800289ea34c5382de1f20869
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 13:37:41 2008 +0100

    [rectangle] Fix unsigned promotion whilst computing intersect.
    
    _cairo_rectangle_intersect() incorrectly allows unsigned promotion during
    its arithmetic.

diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 3618ba0..ec08db4 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -96,29 +96,32 @@ _cairo_box_round_to_rectangle (const cairo_box_t     *box,
 }
 
 void
-_cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src)
+_cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
+			    const cairo_rectangle_int_t *src)
 {
     int x1, y1, x2, y2;
 
-    x1 = MAX (dest->x, src->x);
-    y1 = MAX (dest->y, src->y);
-    x2 = MIN (dest->x + dest->width, src->x + src->width);
-    y2 = MIN (dest->y + dest->height, src->y + src->height);
+    x1 = MAX (dst->x, src->x);
+    y1 = MAX (dst->y, src->y);
+    /* Beware the unsigned promotion, fortunately we have bits to spare
+     * as (CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN) < UINT_MAX
+     */
+    x2 = MIN (dst->x + (int) dst->width,  src->x + (int) src->width);
+    y2 = MIN (dst->y + (int) dst->height, src->y + (int) src->height);
 
     if (x1 >= x2 || y1 >= y2) {
-	dest->x = 0;
-	dest->y = 0;
-	dest->width = 0;
-	dest->height = 0;
+	dst->x = 0;
+	dst->y = 0;
+	dst->width  = 0;
+	dst->height = 0;
     } else {
-	dest->x = x1;
-	dest->y = y1;
-	dest->width = x2 - x1;
-	dest->height = y2 - y1;
+	dst->x = x1;
+	dst->y = y1;
+	dst->width  = x2 - x1;
+	dst->height = y2 - y1;
     }
 }
 
-
 #define P1x (line->p1.x)
 #define P1y (line->p1.y)
 #define P2x (line->p2.x)
diff --git a/src/cairoint.h b/src/cairoint.h
index a00e6e1..5172b9e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -254,7 +254,8 @@ _cairo_box_round_to_rectangle (const cairo_box_t     *box,
 			       cairo_rectangle_int_t *rectangle);
 
 cairo_private void
-_cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src);
+_cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
+			    const cairo_rectangle_int_t *src);
 
 cairo_private cairo_bool_t
 _cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
commit 2464b8a0a9f7db7421c257eb4e3ac0d98af34761
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 13:36:19 2008 +0100

    [pattern] Allow the projected surface extents to be negative.
    
    In order to handle projection of analysis surface with user-fonts we need
    to accommodate patterns extending into negative coordinate space.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index d83142a..83d371c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2250,11 +2250,11 @@ _cairo_pattern_get_extents (cairo_pattern_t         *pattern,
 					      NULL);
 
 	x1 = floor (x1);
-	if (x1 < 0)
-	    x1 = 0;
+	if (x1 < CAIRO_RECT_INT_MIN)
+	    x1 = CAIRO_RECT_INT_MIN;
 	y1 = floor (y1);
-	if (y1 < 0)
-	    y1 = 0;
+	if (y1 < CAIRO_RECT_INT_MIN)
+	    y1 = CAIRO_RECT_INT_MIN;
 
 	x2 = ceil (x2);
 	if (x2 > CAIRO_RECT_INT_MAX)
commit d5d29075bdbb7f412fa6dc182573da18fd81af54
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 23 15:24:13 2008 +0100

    [gstate] Allocate temporary variable for backend_to_user transform.
    
    _cairo_gstate_backend_to_user_rectangle() requires that its input
    arguments are non-NULL and describe the input rectangle to be transformed.
    However, we were passing through output parameters from the public API
    which were allowed to be NULL. So we need to allocate temporary variables
    in which to compute the output rectangle, but only copy them as required.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 00f498e..e1b4693 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -785,12 +785,25 @@ _cairo_gstate_path_extents (cairo_gstate_t     *gstate,
 			    double *x2, double *y2)
 {
     cairo_status_t status;
+    double px1, py1, px2, py2;
 
-    status = _cairo_path_fixed_bounds (path, x1, y1, x2, y2, gstate->tolerance);
+    status = _cairo_path_fixed_bounds (path,
+				       &px1, &py1, &px2, &py2,
+				       gstate->tolerance);
     if (status)
 	return status;
 
-    _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
+    _cairo_gstate_backend_to_user_rectangle (gstate,
+					     &px1, &py1, &px2, &py2,
+					     NULL);
+    if (x1)
+	*x1 = px1;
+    if (y1)
+	*y1 = py1;
+    if (x2)
+	*x2 = px2;
+    if (y2)
+	*y2 = py2;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1083,18 +1096,26 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t	  *gstate,
 	if (y2)
 	    *y2 = 0.0;
     } else {
+	double px1, py1, px2, py2;
+
 	_cairo_traps_extents (traps, &extents);
 
+	px1 = _cairo_fixed_to_double (extents.p1.x);
+	py1 = _cairo_fixed_to_double (extents.p1.y);
+	px2 = _cairo_fixed_to_double (extents.p2.x);
+	py2 = _cairo_fixed_to_double (extents.p2.y);
+
+        _cairo_gstate_backend_to_user_rectangle (gstate,
+						 &px1, &py1, &px2, &py2,
+						 NULL);
 	if (x1)
-	    *x1 = _cairo_fixed_to_double (extents.p1.x);
+	    *x1 = px1;
 	if (y1)
-	    *y1 = _cairo_fixed_to_double (extents.p1.y);
+	    *y1 = py1;
 	if (x2)
-	    *x2 = _cairo_fixed_to_double (extents.p2.x);
+	    *x2 = px2;
 	if (y2)
-	    *y2 = _cairo_fixed_to_double (extents.p2.y);
-
-        _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
+	    *y2 = py2;
     }
 }
 
@@ -1128,7 +1149,8 @@ _cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
 						gstate->tolerance,
 						&traps);
     if (status == CAIRO_STATUS_SUCCESS) {
-        _cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2);
+	_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
+						       x1, y1, x2, y2);
     }
 
     _cairo_traps_fini (&traps);
@@ -1152,7 +1174,8 @@ _cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
 					      gstate->tolerance,
 					      &traps);
     if (status == CAIRO_STATUS_SUCCESS) {
-        _cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2);
+	_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
+						       x1, y1, x2, y2);
     }
 
     _cairo_traps_fini (&traps);
@@ -1195,26 +1218,34 @@ cairo_status_t
 _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
 		            double         *x1,
 		            double         *y1,
-        		    double         *x2,
-        		    double         *y2)
+			    double         *x2,
+			    double         *y2)
 {
     cairo_rectangle_int_t extents;
+    double px1, py1, px2, py2;
     cairo_status_t status;
-    
+
     status = _cairo_gstate_int_clip_extents (gstate, &extents);
     if (status)
         return status;
 
+    px1 = extents.x;
+    py1 = extents.y;
+    px2 = extents.x + (int) extents.width;
+    py2 = extents.y + (int) extents.height;
+
+    _cairo_gstate_backend_to_user_rectangle (gstate,
+					     &px1, &py1, &px2, &py2,
+					     NULL);
+
     if (x1)
-	*x1 = extents.x;
+	*x1 = px1;
     if (y1)
-	*y1 = extents.y;
+	*y1 = py1;
     if (x2)
-	*x2 = extents.x + extents.width;
+	*x2 = px2;
     if (y2)
-	*y2 = extents.y + extents.height;
-
-    _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
+	*y2 = py2;
 
     return CAIRO_STATUS_SUCCESS;
 }


More information about the cairo-commit mailing list