[cairo-commit] 11 commits - src/cairo-analysis-surface.c src/cairoint.h src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-region.c src/cairo-scaled-font-subsets.c src/cairo-type3-glyph-surface.c src/cairo-xlib-surface.c test/cairo-test.c test/show-glyphs-many.c test/surface-finish-twice.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Apr 16 01:34:42 PDT 2009


 src/cairo-analysis-surface.c    |   26 ++++++++--------
 src/cairo-pattern.c             |   21 ++++++-------
 src/cairo-pdf-surface.c         |   11 ++++++
 src/cairo-region.c              |   23 ++++++++++++++
 src/cairo-scaled-font-subsets.c |   63 ++++++++++++++++++++++------------------
 src/cairo-type3-glyph-surface.c |   36 +++++++++++++++++++---
 src/cairo-xlib-surface.c        |   58 ++++++++++++++++++++++++------------
 src/cairoint.h                  |   10 ++++++
 test/cairo-test.c               |    2 -
 test/show-glyphs-many.c         |    2 -
 test/surface-finish-twice.c     |   17 ++++++----
 11 files changed, 185 insertions(+), 84 deletions(-)

New commits:
commit 5a76c233bffda65140c6ada9b5f2ed7d3bcc999e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Apr 14 11:02:40 2009 +0100

    [type3] Propagate error from font creation.
    
    Perform an error check after creating a scaled-font to prevent operations
    on a nil-object.

diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 2ffc018..104da53 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -285,6 +285,8 @@ _cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
 				     &scaled_font->font_matrix,
 				     &new_ctm,
 				     &scaled_font->options);
+    if (unlikely (font->status))
+	return font->status;
 
     status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
 						    NULL, 0,
commit d46bd67c8b3f63d6286845e814f8f1e040f89737
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 10 14:55:24 2009 +0100

    [type3] Add status checks.
    
    Propagate error from the stream when creating the surface and add status
    guards before writing to the potential nil object.

diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index c52915f..2ffc018 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -46,14 +46,17 @@
 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
 
 cairo_surface_t *
-_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 		 *scaled_font,
-				   cairo_output_stream_t 		 *stream,
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t			 *scaled_font,
+				   cairo_output_stream_t		 *stream,
 				   cairo_type3_glyph_surface_emit_image_t emit_image,
-				   cairo_scaled_font_subsets_t 		 *font_subsets)
+				   cairo_scaled_font_subsets_t		 *font_subsets)
 {
     cairo_type3_glyph_surface_t *surface;
     cairo_matrix_t invert_y_axis;
 
+    if (unlikely (stream != NULL && stream->status))
+	return _cairo_surface_create_in_error (stream->status);
+
     surface = malloc (sizeof (cairo_type3_glyph_surface_t));
     if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -379,6 +382,9 @@ _cairo_type3_glyph_surface_set_font_subsets_callback (void		     		    *abstract
 {
     cairo_type3_glyph_surface_t *surface = abstract_surface;
 
+    if (unlikely (surface->base.status))
+	return;
+
     _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
 						    use_font_subset,
 						    closure);
@@ -393,7 +399,13 @@ _cairo_type3_glyph_surface_analyze_glyph (void		     *abstract_surface,
     cairo_status_t status, status2;
     cairo_output_stream_t *null_stream;
 
+    if (unlikely (surface->base.status))
+	return surface->base.status;
+
     null_stream = _cairo_null_stream_create ();
+    if (unlikely (null_stream->status))
+	return null_stream->status;
+
     _cairo_type3_glyph_surface_set_stream (surface, null_stream);
 
     _cairo_scaled_font_freeze_cache (surface->scaled_font);
@@ -446,6 +458,9 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
     double x_advance, y_advance;
     cairo_matrix_t font_matrix_inverse;
 
+    if (unlikely (surface->base.status))
+	return surface->base.status;
+
     _cairo_type3_glyph_surface_set_stream (surface, stream);
 
     _cairo_scaled_font_freeze_cache (surface->scaled_font);
@@ -496,6 +511,10 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
 	cairo_output_stream_t *mem_stream;
 
 	mem_stream = _cairo_memory_stream_create ();
+	status = mem_stream->status;
+	if (unlikely (status))
+	    goto FAIL;
+
 	_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
 
 	_cairo_output_stream_printf (surface->stream, "q\n");
@@ -520,6 +539,7 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
     if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
 	status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
 
+  FAIL:
     _cairo_scaled_font_thaw_cache (surface->scaled_font);
 
     return status;
commit a6ffb69a54f15659dac7c6b2e1c98bd7893ccdf1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 3 17:28:05 2009 +0100

    [type3] Check error status before emit_image().
    
    Be careful not to pass an error object down to emit_image() hook,
    propagate the error instead. This relieves the burden of the error check
    from the callee -- which was causing an assertion failure in the ps
    backend.

diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 3ff5003..c52915f 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -88,6 +88,12 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 {
     cairo_status_t status;
 
+    /* The only image type supported by Type 3 fonts are 1-bit masks */
+    image = _cairo_image_surface_coerce (image, CAIRO_FORMAT_A1);
+    status = image->base.status;
+    if (unlikely (status))
+	return status;
+
     _cairo_output_stream_printf (surface->stream,
 				 "q %f %f %f %f %f %f cm\n",
 				 image_matrix->xx,
@@ -97,8 +103,6 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 				 image_matrix->x0,
 				 image_matrix->y0);
 
-    /* The only image type supported by Type 3 fonts are 1-bit masks */
-    image = _cairo_image_surface_coerce (image, CAIRO_FORMAT_A1);
     status = surface->emit_image (image, surface->stream);
     cairo_surface_destroy (&image->base);
 
commit 21d1138da9bcf9c006e0cf3f3d1d50e1c7cec1de
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 10 14:53:55 2009 +0100

    [scaled-font-subsets] Check for malloc failure.
    
    Check that the utf8 string is successfully allocated before writing to it,
    otherwise propagate the error status back to the callers.

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 44e850e..02b32aa 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -372,13 +372,16 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_bool_t
+static cairo_status_t
 _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
 				      const char	     *utf8,
-				      int		      utf8_len)
+				      int		      utf8_len,
+				      cairo_bool_t	     *is_mapped)
 {
+    *is_mapped = FALSE;
+
     if (utf8_len < 0)
-	return FALSE;
+	return CAIRO_STATUS_SUCCESS;
 
     if (utf8 != NULL && utf8_len != 0 && utf8[utf8_len - 1] == '\0')
 	utf8_len--;
@@ -389,28 +392,25 @@ _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
 		memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
 	    {
 		/* Requested utf8 mapping matches the existing mapping */
-		return TRUE;
-	    }
-	    else
-	    {
-		/* Requested utf8 mapping does not match the existing mapping */
-		return FALSE;
+		*is_mapped = TRUE;
 	    }
 	} else {
 	    /* No existing mapping. Use the requested mapping */
 	    sub_font_glyph->utf8 = malloc (utf8_len + 1);
+	    if (unlikely (sub_font_glyph->utf8 == NULL))
+		return CAIRO_STATUS_NO_MEMORY;
+
 	    memcpy (sub_font_glyph->utf8, utf8, utf8_len);
 	    sub_font_glyph->utf8[utf8_len] = 0;
 	    sub_font_glyph->utf8_len = utf8_len;
-	    return TRUE;
+	    *is_mapped = TRUE;
 	}
     }
 
-    /* No mapping was requested. */
-    return FALSE;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_bool_t
+static cairo_int_status_t
 _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
                               unsigned long	                 scaled_font_glyph_index,
 			      const char			*utf8,
@@ -418,6 +418,7 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
                               cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
+    cairo_int_status_t status;
 
     _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
     sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
@@ -430,13 +431,15 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
         subset_glyph->is_composite = sub_font->is_composite;
         subset_glyph->x_advance = sub_font_glyph->x_advance;
         subset_glyph->y_advance = sub_font_glyph->y_advance;
-	subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+	status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
+						       utf8, utf8_len,
+						       &subset_glyph->utf8_is_mapped);
 	subset_glyph->unicode = sub_font_glyph->unicode;
 
-	return TRUE;
+	return status;
     }
 
-    return FALSE;
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static cairo_status_t
@@ -524,10 +527,12 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
     subset_glyph->is_composite = sub_font->is_composite;
     subset_glyph->x_advance = sub_font_glyph->x_advance;
     subset_glyph->y_advance = sub_font_glyph->y_advance;
-    subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+    status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
+						   utf8, utf8_len,
+						   &subset_glyph->utf8_is_mapped);
     subset_glyph->unicode = sub_font_glyph->unicode;
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static void
@@ -686,11 +691,12 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 	sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
 					     &key.base);
         if (sub_font != NULL) {
-            if (_cairo_sub_font_lookup_glyph (sub_font,
-                                              scaled_font_glyph_index,
-					      utf8, utf8_len,
-                                              subset_glyph))
-                return CAIRO_STATUS_SUCCESS;
+            status = _cairo_sub_font_lookup_glyph (sub_font,
+						   scaled_font_glyph_index,
+						   utf8, utf8_len,
+						   subset_glyph);
+	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+                return status;
         }
     }
 
@@ -700,11 +706,12 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
     sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
 					 &key.base);
     if (sub_font != NULL) {
-        if (_cairo_sub_font_lookup_glyph (sub_font,
-                                          scaled_font_glyph_index,
-					  utf8, utf8_len,
-                                          subset_glyph))
-            return CAIRO_STATUS_SUCCESS;
+	status = _cairo_sub_font_lookup_glyph (sub_font,
+					       scaled_font_glyph_index,
+					       utf8, utf8_len,
+					       subset_glyph);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
     }
 
     /* Glyph not found. Determine whether the glyph is outline or
commit 0f0e2d738437176e72317b37ef66fbc56c60ba93
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 10 14:52:48 2009 +0100

    [pdf] Propagate failure from type3 glyph surface creation.
    
    Add an early check that we successfully created the glyph surface.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 886dd6b..b1458d8 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3934,6 +3934,11 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
 						       null_stream,
 						       _cairo_pdf_emit_imagemask,
 						       surface->font_subsets);
+    if (unlikely (type3_surface->status)) {
+	status2 = _cairo_output_stream_destroy (null_stream);
+	return type3_surface->status;
+    }
+
     _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
 							  _cairo_pdf_surface_add_font,
 							  surface);
@@ -3990,6 +3995,12 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 						       NULL,
 						       _cairo_pdf_emit_imagemask,
 						       surface->font_subsets);
+    if (unlikely (type3_surface->status)) {
+        free (glyphs);
+        free (widths);
+	return type3_surface->status;
+    }
+
     _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
 							  _cairo_pdf_surface_add_font,
 							  surface);
commit 1496c5cf51a2304dfd4e9d359a0645ff44fadd3e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 10 14:50:26 2009 +0100

    [analysis] Use _cairo_region_init()
    
    Avoid secondary allocations of the thin region wrappers during surface
    creation by embedding them into the parent structure. This has the
    satisfactory side-effect of not requiring status checks which current code
    lacks.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index cd79985..c767d07 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -51,8 +51,8 @@ typedef struct {
     cairo_bool_t has_supported;
     cairo_bool_t has_unsupported;
 
-    cairo_region_t *supported_region;
-    cairo_region_t *fallback_region;
+    cairo_region_t supported_region;
+    cairo_region_t fallback_region;
     cairo_rectangle_int_t current_clip;
     cairo_box_t page_bbox;
 
@@ -214,7 +214,7 @@ _add_operation  (cairo_analysis_surface_t *surface,
      * region there is no benefit in emitting a native operation as
      * the fallback image will be painted on top.
      */
-    if (cairo_region_contains_rectangle (surface->fallback_region, rect) == CAIRO_REGION_OVERLAP_IN)
+    if (cairo_region_contains_rectangle (&surface->fallback_region, rect) == CAIRO_REGION_OVERLAP_IN)
 	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 
     if (backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) {
@@ -225,7 +225,7 @@ _add_operation  (cairo_analysis_surface_t *surface,
 	 * natively supported and the backend will blend the
 	 * transparency into the white background.
 	 */
-	if (cairo_region_contains_rectangle (surface->supported_region, rect) == CAIRO_REGION_OVERLAP_OUT)
+	if (cairo_region_contains_rectangle (&surface->supported_region, rect) == CAIRO_REGION_OVERLAP_OUT)
 	    backend_status = CAIRO_STATUS_SUCCESS;
     }
 
@@ -234,7 +234,7 @@ _add_operation  (cairo_analysis_surface_t *surface,
 	 * this region will be emitted as native operations.
 	 */
 	surface->has_supported = TRUE;
-	status = cairo_region_union_rectangle (surface->supported_region, rect);
+	status = cairo_region_union_rectangle (&surface->supported_region, rect);
 	return status;
     }
 
@@ -243,7 +243,7 @@ _add_operation  (cairo_analysis_surface_t *surface,
      * emitted.
      */
     surface->has_unsupported = TRUE;
-    status = cairo_region_union_rectangle (surface->fallback_region, rect);
+    status = cairo_region_union_rectangle (&surface->fallback_region, rect);
 
     /* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate
      * unsupported operations to the meta surface as using
@@ -262,8 +262,8 @@ _cairo_analysis_surface_finish (void *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
-    cairo_region_destroy (surface->supported_region);
-    cairo_region_destroy (surface->fallback_region);
+    _cairo_region_fini (&surface->supported_region);
+    _cairo_region_fini (&surface->fallback_region);
 
     cairo_surface_destroy (surface->target);
 
@@ -773,14 +773,14 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
 
+    _cairo_region_init (&surface->supported_region);
+    _cairo_region_init (&surface->fallback_region);
+
     surface->page_bbox.p1.x = 0;
     surface->page_bbox.p1.y = 0;
     surface->page_bbox.p2.x = 0;
     surface->page_bbox.p2.y = 0;
 
-    surface->supported_region = cairo_region_create ();
-    surface->fallback_region = cairo_region_create ();
-
     if (width == -1 && height == -1) {
 	surface->current_clip.x      = CAIRO_RECT_INT_MIN;
 	surface->current_clip.y      = CAIRO_RECT_INT_MIN;
@@ -826,7 +826,7 @@ _cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
-    return surface->supported_region;
+    return &surface->supported_region;
 }
 
 cairo_region_t *
@@ -834,7 +834,7 @@ _cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
-    return surface->fallback_region;
+    return &surface->fallback_region;
 }
 
 cairo_bool_t
commit ad83765a1441cb369c3e7f3de77c243297406c7a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 3 09:23:58 2009 +0100

    [xlib] Allocate bounded region on stack.
    
    Eliminate the extremely short-lived and oft unnecessary heap allocation
    of the region by first checking to see whether the clip exceeds the
    surface bounds and only then intersect the clip with a local
    stack-allocated region.

diff --git a/src/cairo-region.c b/src/cairo-region.c
index 15bf2f1..5d1f2c5 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -76,6 +76,29 @@ _cairo_region_set_error (cairo_region_t *region,
     return _cairo_error (status);
 }
 
+void
+_cairo_region_init (cairo_region_t *region)
+{
+    region->status = CAIRO_STATUS_SUCCESS;
+    pixman_region32_init (&region->rgn);
+}
+
+void
+_cairo_region_init_rectangle (cairo_region_t *region,
+			      const cairo_rectangle_int_t *rectangle)
+{
+    region->status = CAIRO_STATUS_SUCCESS;
+    pixman_region32_init_rect (&region->rgn,
+			       rectangle->x, rectangle->y,
+			       rectangle->width, rectangle->height);
+}
+
+void
+_cairo_region_fini (cairo_region_t *region)
+{
+    pixman_region32_fini (&region->rgn);
+}
+
 /**
  * cairo_region_create:
  *
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index a6820af..d1e7391 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2269,6 +2269,32 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	op,
     return status;
 }
 
+static cairo_region_t *
+_surface_maybe_clip_region (cairo_xlib_surface_t *surface,
+			    cairo_region_t *clip,
+			    cairo_region_t *bounded)
+{
+    cairo_rectangle_int_t rect;
+
+    cairo_region_get_extents (clip, &rect);
+    if (rect.x >= 0 &&
+	rect.y >= 0 &&
+	rect.x + rect.width <= surface->width &&
+	rect.y + rect.height <= surface->height)
+    {
+	return clip;
+    }
+
+    rect.x = rect.y = 0;
+    rect.width = surface->width;
+    rect.height = surface->height;
+    _cairo_region_init_rectangle (bounded, &rect);
+
+    bounded->status = cairo_region_intersect (bounded, clip);
+
+    return bounded;
+}
+
 static cairo_int_status_t
 _cairo_xlib_surface_set_clip_region (void           *abstract_surface,
 				     cairo_region_t *region)
@@ -2288,33 +2314,24 @@ _cairo_xlib_surface_set_clip_region (void           *abstract_surface,
     surface->num_clip_rects = 0;
 
     if (region != NULL) {
-	cairo_status_t status;
 	XRectangle *rects = NULL;
 	int n_rects, i;
-	cairo_rectangle_int_t rect;
-	cairo_region_t *bounded;
-
-	rect.x = rect.y = 0;
-	rect.width = surface->width;
-	rect.height = surface->height;
+	cairo_region_t bounded;
 
 	/* 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.
 	 */
-	bounded = cairo_region_create_rectangle (&rect);
-	status = cairo_region_intersect (bounded, region);
-	if (unlikely (status)) {
-	    cairo_region_destroy (bounded);
-	    return status;
-	}
-
-	n_rects = cairo_region_num_rectangles (bounded);
+	region = _surface_maybe_clip_region (surface, region, &bounded);
+	if (unlikely (region->status))
+	    return region->status;
 
+	n_rects = cairo_region_num_rectangles (region);
 	if (n_rects > ARRAY_LENGTH (surface->embedded_clip_rects)) {
 	    rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
 	    if (unlikely (rects == NULL)) {
-		cairo_region_destroy (bounded);
+		if (unlikely (region == &bounded))
+		    _cairo_region_fini (&bounded);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 	} else {
@@ -2323,16 +2340,17 @@ _cairo_xlib_surface_set_clip_region (void           *abstract_surface,
 
 	for (i = 0; i < n_rects; i++) {
 	    cairo_rectangle_int_t rect;
-	    
-	    cairo_region_get_rectangle (bounded, i, &rect);
+
+	    cairo_region_get_rectangle (region, i, &rect);
 
 	    rects[i].x = rect.x;
 	    rects[i].y = rect.y;
 	    rects[i].width = rect.width;
 	    rects[i].height = rect.height;
 	}
-	
-	cairo_region_destroy (bounded);
+
+	if (unlikely (region == &bounded))
+	    _cairo_region_fini (&bounded);
 
 	surface->have_clip_rects = TRUE;
 	surface->clip_rects = rects;
diff --git a/src/cairoint.h b/src/cairoint.h
index 21b2864..29e7ccf 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2534,6 +2534,16 @@ struct _cairo_region {
     pixman_region32_t rgn;
 };
 
+cairo_private void
+_cairo_region_init (cairo_region_t *region);
+
+cairo_private void
+_cairo_region_init_rectangle (cairo_region_t *region,
+			      const cairo_rectangle_int_t *rectangle);
+
+cairo_private void
+_cairo_region_fini (cairo_region_t *region);
+
 /* cairo-unicode.c */
 
 cairo_private int
commit 75b06b8bdb5efaf030e063c1f66583d8fde347dc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Apr 1 11:43:16 2009 +0100

    [pattern] Do not modify outparam on error path.
    
    The pdf backend was crashing as a failed pattern copy stored an invalid
    pointer with the resource group.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index bd7e07a..0ecfbe3 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -250,9 +250,10 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
 }
 
 cairo_status_t
-_cairo_pattern_create_copy (cairo_pattern_t	  **pattern,
+_cairo_pattern_create_copy (cairo_pattern_t	  **pattern_out,
 			    const cairo_pattern_t  *other)
 {
+    cairo_pattern_t *pattern;
     cairo_status_t status;
 
     if (other->status)
@@ -260,29 +261,29 @@ _cairo_pattern_create_copy (cairo_pattern_t	  **pattern,
 
     switch (other->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	*pattern = malloc (sizeof (cairo_solid_pattern_t));
+	pattern = malloc (sizeof (cairo_solid_pattern_t));
 	break;
     case CAIRO_PATTERN_TYPE_SURFACE:
-	*pattern = malloc (sizeof (cairo_surface_pattern_t));
+	pattern = malloc (sizeof (cairo_surface_pattern_t));
 	break;
     case CAIRO_PATTERN_TYPE_LINEAR:
-	*pattern = malloc (sizeof (cairo_linear_pattern_t));
+	pattern = malloc (sizeof (cairo_linear_pattern_t));
 	break;
     case CAIRO_PATTERN_TYPE_RADIAL:
-	*pattern = malloc (sizeof (cairo_radial_pattern_t));
+	pattern = malloc (sizeof (cairo_radial_pattern_t));
 	break;
     }
-    if (unlikely (*pattern == NULL))
+    if (unlikely (pattern == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    status = _cairo_pattern_init_copy (*pattern, other);
+    status = _cairo_pattern_init_copy (pattern, other);
     if (unlikely (status)) {
-	free (*pattern);
+	free (pattern);
 	return status;
     }
 
-    CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
-
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
+    *pattern_out = pattern;
     return CAIRO_STATUS_SUCCESS;
 }
 
commit 82cccb26723697492504f395fed33afba28d84ba
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Apr 14 11:01:39 2009 +0100

    [test] Handle memfaults during surface-finish-twice
    
    Check and report memory allocation failures.

diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index 5154e99..f63b501 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -45,21 +45,26 @@
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
+    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
     cairo_surface_t *surface;
+    cairo_status_t status;
 
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
 
     cairo_surface_finish (surface);
-    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
-	return CAIRO_TEST_FAILURE;
+    status = cairo_surface_status (surface);
+    if (status != CAIRO_STATUS_SUCCESS)
+	return cairo_test_status_from_status (ctx, status);
 
     cairo_surface_finish (surface);
-    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
-	return CAIRO_TEST_FAILURE;
+    status = cairo_surface_status (surface);
+    if (status != CAIRO_STATUS_SUCCESS)
+	return cairo_test_status_from_status (ctx, status);
 
     cairo_surface_finish (surface);
-    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
-	return CAIRO_TEST_FAILURE;
+    status = cairo_surface_status (surface);
+    if (status != CAIRO_STATUS_SUCCESS)
+	return cairo_test_status_from_status (ctx, status);
 
     cairo_surface_destroy (surface);
 
commit f12d52bfcae0792729b33a1fd1b2d23bd3fc7cf3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Apr 4 19:02:15 2009 +0100

    [test] Use xmalloc() to evade memfault.
    
    Do not use the simple malloc() as memfault will inject allocation failures
    (unlike xmalloc() for which faults are excluded) - as this is unnecessary
    inside the test harness and thus does not exercise any cairo code paths.

diff --git a/test/show-glyphs-many.c b/test/show-glyphs-many.c
index 9657e28..dbfd6a1 100644
--- a/test/show-glyphs-many.c
+++ b/test/show-glyphs-many.c
@@ -109,7 +109,7 @@ get_glyph (cairo_t *cr, const char *utf8, cairo_glyph_t *glyph)
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
-    cairo_glyph_t *glyphs = malloc(NUM_GLYPHS * sizeof(cairo_glyph_t));
+    cairo_glyph_t *glyphs = xmalloc (NUM_GLYPHS * sizeof (cairo_glyph_t));
     const char *characters[] = { /* try to exercise different widths of index */
 	"m", /* Latin letter m, index=0x50 */
 	"μ", /* Greek letter mu, index=0x349 */
commit ca501d99bbec432252cbb134d863801d4a792a44
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Apr 1 11:41:59 2009 +0100

    [test] Disable signal handling under valgrind
    
    Capturing and handling the signals prevents valgrind from providing
    backtraces for fatal signals -- which is often more useful.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 568d8f8..897332a 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1228,7 +1228,7 @@ _cairo_test_context_run_for_target (cairo_test_context_t *ctx,
     }
 
 #if defined(HAVE_SIGNAL_H) && defined(HAVE_SETJMP_H)
-    if (ctx->thread == 0) {
+    if (ctx->thread == 0 && ! RUNNING_ON_VALGRIND) {
 	void (* volatile old_segfault_handler)(int);
 	void (* volatile old_sigpipe_handler)(int);
 	void (* volatile old_sigabrt_handler)(int);


More information about the cairo-commit mailing list