[cairo-commit] 13 commits - doc/tutorial src/cairo-analysis-surface.c src/cairo-clip.c src/cairo-image-surface.c src/cairoint.h src/cairo-meta-surface.c src/cairo-paginated-surface.c src/cairo-path-bounds.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-rectangle.c src/cairo-scaled-font.c src/cairo-script-surface.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-svg-surface.c src/cairo-type3-glyph-surface.c src/cairo-xlib-surface.c src/test-meta-surface.c src/test-paginated-surface.c test/twin.c test/twin.pdf.ref.png test/twin.ref.png util/cairo-script util/cairo-trace

Chris Wilson ickle at kemper.freedesktop.org
Thu Dec 18 04:12:50 PST 2008


 doc/tutorial/src/twin.c                    |    2 
 src/cairo-analysis-surface.c               |   60 ++++++------------
 src/cairo-clip.c                           |   25 ++++---
 src/cairo-image-surface.c                  |   42 +++++++-----
 src/cairo-meta-surface.c                   |    1 
 src/cairo-paginated-surface.c              |    1 
 src/cairo-path-bounds.c                    |   95 ++++++++++++++---------------
 src/cairo-pattern.c                        |   54 +++++++++++-----
 src/cairo-pdf-surface.c                    |    1 
 src/cairo-rectangle.c                      |   10 +++
 src/cairo-scaled-font.c                    |   44 +++++++------
 src/cairo-script-surface.c                 |    1 
 src/cairo-surface-fallback.c               |    9 +-
 src/cairo-surface.c                        |   41 +++++++-----
 src/cairo-svg-surface.c                    |   18 ++---
 src/cairo-type3-glyph-surface.c            |   20 +-----
 src/cairo-xlib-surface.c                   |   12 +++
 src/cairoint.h                             |   20 ++++--
 src/test-meta-surface.c                    |    1 
 src/test-paginated-surface.c               |    1 
 test/twin.c                                |    2 
 test/twin.pdf.ref.png                      |binary
 test/twin.ref.png                          |binary
 util/cairo-script/cairo-script-operators.c |   54 ++++++----------
 util/cairo-script/csi-replay.c             |    6 +
 util/cairo-trace/trace.c                   |   47 +++++++-------
 26 files changed, 303 insertions(+), 264 deletions(-)

New commits:
commit dea40e61babe608315b6d365094cf518814b134e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 11:50:00 2008 +0000

    [path] Return the fixed-point bounds of the path
    
    When analysing the stroke extents, we need the original fixed-point
    extents so that we do not incur an OBO when we round-to-integer a second
    time. We also need a more accurate estimate than simply using the control
    points of the curve, so pass in tolerance and decompose until someone
    discovers a cheaper algorithm to determine the precise aligned bounding
    box of a bezier curve.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index e098445..b8f2ab4 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -290,11 +290,12 @@ _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 	surface->current_clip.width  = surface->width;
 	surface->current_clip.height = surface->height;
     } else {
-	cairo_rectangle_int_t extent;
+	cairo_box_t extents;
 	cairo_bool_t is_empty;
 
-	_cairo_path_fixed_approximate_extents (path, &extent);
-	is_empty = _cairo_rectangle_intersect (&surface->current_clip, &extent);
+	_cairo_path_fixed_approximate_extents (path, tolerance, &extents);
+	is_empty = _cairo_rectangle_intersect_box (&surface->current_clip,
+						   &extents);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -477,22 +478,19 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_rectangle_int_t mask_extents;
+	cairo_box_t mask_extents;
 	double dx, dy;
 
-	_cairo_path_fixed_approximate_extents (path, &mask_extents);
+	_cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
 
 	_cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy);
 
-	mask_extents.width += mask_extents.x + ceil (dx);
-	mask_extents.x -= ceil (dx);
-	mask_extents.width -= mask_extents.x;
-
-	mask_extents.height += mask_extents.y + ceil (dy);
-	mask_extents.y -= ceil (dy);
-	mask_extents.height -= mask_extents.y;
+	mask_extents.p1.x -= _cairo_fixed_from_double (dx);
+	mask_extents.p2.x += _cairo_fixed_from_double (dx);
+	mask_extents.p1.y -= _cairo_fixed_from_double (dy);
+	mask_extents.p2.y += _cairo_fixed_from_double (dy);
 
-	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
+	is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
     }
     if (stroke_extents)
 	*stroke_extents = extents;
@@ -544,11 +542,11 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_rectangle_int_t mask_extents;
+	cairo_box_t mask_extents;
 
-	_cairo_path_fixed_approximate_extents (path, &mask_extents);
+	_cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
 
-	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
+	is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
     }
     if (fill_extents)
 	*fill_extents = extents;
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index c679e9f..cd36924 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -143,11 +143,13 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
 				         cairo_rectangle_int_t   *rectangle)
 {
     while (clip_path) {
-        cairo_rectangle_int_t extents;
+        cairo_box_t extents;
 
-	_cairo_path_fixed_approximate_extents (&clip_path->path, &extents);
+	_cairo_path_fixed_approximate_extents (&clip_path->path,
+					       clip_path->tolerance,
+					       &extents);
 
-        if (! _cairo_rectangle_intersect (rectangle, &extents))
+        if (! _cairo_rectangle_intersect_box (rectangle, &extents))
 	    return CAIRO_STATUS_SUCCESS;
 
         clip_path = clip_path->prev;
@@ -568,20 +570,21 @@ _cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
 	goto BAIL;
     }
 
+    status = _cairo_surface_get_extents (target, &surface_rect);
+    if (status)
+	goto BAIL;
+
     /* We'll create a new surface the size of the intersection of the
      * old mask surface and the extents of the new clip path. */
     {
-	cairo_rectangle_int_t target_rect;
+	cairo_box_t extents;
 
-	_cairo_path_fixed_approximate_extents (path, &surface_rect);
-
-	if (clip->surface != NULL &&
-	    !_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	_cairo_path_fixed_approximate_extents (path, tolerance, &extents);
+	if (! _cairo_rectangle_intersect_box (&surface_rect, &extents))
 	    goto SUCCESS;
 
-	status = _cairo_surface_get_extents (target, &target_rect);
-	if (status != CAIRO_STATUS_SUCCESS &&
-	    !_cairo_rectangle_intersect (&surface_rect, &target_rect))
+	if (clip->surface != NULL &&
+	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
 	    goto SUCCESS;
     }
 
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index b7411d2..25737e8 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -37,19 +37,19 @@
 #include "cairoint.h"
 
 typedef struct cairo_path_bounder {
+    double tolerance;
+
     cairo_point_t move_to_point;
     cairo_bool_t has_move_to_point;
     cairo_bool_t has_point;
 
-    cairo_fixed_t min_x;
-    cairo_fixed_t min_y;
-    cairo_fixed_t max_x;
-    cairo_fixed_t max_y;
+    cairo_box_t extents;
 } cairo_path_bounder_t;
 
 static void
-_cairo_path_bounder_init (cairo_path_bounder_t *bounder)
+_cairo_path_bounder_init (cairo_path_bounder_t *bounder, double tolerance)
 {
+    bounder->tolerance = tolerance;
     bounder->has_move_to_point = FALSE;
     bounder->has_point = FALSE;
 }
@@ -66,22 +66,22 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder,
 			       const cairo_point_t *point)
 {
     if (bounder->has_point) {
-	if (point->x < bounder->min_x)
-	    bounder->min_x = point->x;
+	if (point->x < bounder->extents.p1.x)
+	    bounder->extents.p1.x = point->x;
 
-	if (point->y < bounder->min_y)
-	    bounder->min_y = point->y;
+	if (point->y < bounder->extents.p1.y)
+	    bounder->extents.p1.y = point->y;
 
-	if (point->x > bounder->max_x)
-	    bounder->max_x = point->x;
+	if (point->x > bounder->extents.p2.x)
+	    bounder->extents.p2.x = point->x;
 
-	if (point->y > bounder->max_y)
-	    bounder->max_y = point->y;
+	if (point->y > bounder->extents.p2.y)
+	    bounder->extents.p2.y = point->y;
     } else {
-	bounder->min_x = point->x;
-	bounder->min_y = point->y;
-	bounder->max_x = point->x;
-	bounder->max_y = point->y;
+	bounder->extents.p1.x = point->x;
+	bounder->extents.p1.y = point->y;
+	bounder->extents.p2.x = point->x;
+	bounder->extents.p2.y = point->y;
 
 	bounder->has_point = TRUE;
     }
@@ -123,18 +123,21 @@ _cairo_path_bounder_curve_to (void *closure,
 			      const cairo_point_t *d)
 {
     cairo_path_bounder_t *bounder = closure;
-
-    if (bounder->has_move_to_point) {
-	_cairo_path_bounder_add_point (bounder,
-				       &bounder->move_to_point);
-	bounder->has_move_to_point = FALSE;
+    cairo_spline_t spline;
+
+    /* XXX Is there a faster way to determine the bounding box of a
+     * Bezier curve than its decomposition?
+     *
+     * Using the control points alone can be wildly inaccurate.
+     */
+    if (! _cairo_spline_init (&spline,
+			      _cairo_path_bounder_line_to, bounder,
+			      &bounder->move_to_point, b, c, d))
+    {
+	return _cairo_path_bounder_line_to (bounder, d);
     }
 
-    _cairo_path_bounder_add_point (bounder, b);
-    _cairo_path_bounder_add_point (bounder, c);
-    _cairo_path_bounder_add_point (bounder, d);
-
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_spline_decompose (&spline, bounder->tolerance);
 }
 
 static cairo_status_t
@@ -149,12 +152,13 @@ _cairo_path_bounder_close_path (void *closure)
  */
 void
 _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
-				       cairo_rectangle_int_t *extents)
+				       double tolerance,
+				       cairo_box_t *extents)
 {
     cairo_path_bounder_t bounder;
     cairo_status_t status;
 
-    _cairo_path_bounder_init (&bounder);
+    _cairo_path_bounder_init (&bounder, tolerance);
 
     status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
 					  _cairo_path_bounder_move_to,
@@ -165,15 +169,10 @@ _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
     assert (status == CAIRO_STATUS_SUCCESS);
 
     if (bounder.has_point) {
-	extents->x = _cairo_fixed_integer_floor (bounder.min_x);
-	extents->y = _cairo_fixed_integer_floor (bounder.min_y);
-	extents->width =
-	    _cairo_fixed_integer_ceil (bounder.max_x) - extents->x;
-	extents->height =
-	    _cairo_fixed_integer_ceil (bounder.max_y) - extents->y;
+	*extents = bounder.extents;
     } else {
-	extents->x = extents->y = 0;
-	extents->width = extents->height = 0;
+	extents->p1.x = extents->p1.y = 0;
+	extents->p2.x = extents->p2.y = 0;
     }
 
     _cairo_path_bounder_fini (&bounder);
@@ -188,21 +187,21 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
     cairo_path_bounder_t bounder;
     cairo_status_t status;
 
-    _cairo_path_bounder_init (&bounder);
+    _cairo_path_bounder_init (&bounder, tolerance);
 
-    status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD,
-					       _cairo_path_bounder_move_to,
-					       _cairo_path_bounder_line_to,
-					       _cairo_path_bounder_close_path,
-					       &bounder,
-					       tolerance);
+    status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
+					  _cairo_path_bounder_move_to,
+					  _cairo_path_bounder_line_to,
+					  _cairo_path_bounder_curve_to,
+					  _cairo_path_bounder_close_path,
+					  &bounder);
     assert (status == CAIRO_STATUS_SUCCESS);
 
     if (bounder.has_point) {
-	*x1 = _cairo_fixed_to_double (bounder.min_x);
-	*y1 = _cairo_fixed_to_double (bounder.min_y);
-	*x2 = _cairo_fixed_to_double (bounder.max_x);
-	*y2 = _cairo_fixed_to_double (bounder.max_y);
+	*x1 = _cairo_fixed_to_double (bounder.extents.p1.x);
+	*y1 = _cairo_fixed_to_double (bounder.extents.p1.y);
+	*x2 = _cairo_fixed_to_double (bounder.extents.p2.x);
+	*y2 = _cairo_fixed_to_double (bounder.extents.p2.y);
     } else {
 	*x1 = 0.0;
 	*y1 = 0.0;
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index b139624..31a530e 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -126,6 +126,16 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
     }
 }
 
+cairo_bool_t
+_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
+				const cairo_box_t *src)
+{
+    cairo_rectangle_int_t rect;
+
+    _cairo_box_round_to_rectangle (src, &rect);
+    return _cairo_rectangle_intersect (dst, &rect);
+}
+
 #define P1x (line->p1.x)
 #define P1y (line->p1.y)
 #define P2x (line->p2.x)
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index b48435d..0fd1dee 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -955,9 +955,12 @@ _cairo_surface_fallback_fill (cairo_surface_t		*surface,
 	info.antialias = antialias;
 
 	if (_cairo_operator_bounded_by_mask (op)) {
-	    cairo_rectangle_int_t path_extents;
-	    _cairo_path_fixed_approximate_extents (path, &path_extents);
-	    if (! _cairo_rectangle_intersect (&extents, &path_extents))
+	    cairo_box_t path_extents;
+
+	    _cairo_path_fixed_approximate_extents (path,
+						   tolerance,
+						   &path_extents);
+	    if (! _cairo_rectangle_intersect_box (&extents, &path_extents))
 		return CAIRO_STATUS_SUCCESS;
 	}
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 8166436..88945a3 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -259,6 +259,10 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 			    const cairo_rectangle_int_t *src);
 
 cairo_private cairo_bool_t
+_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
+				const cairo_box_t *src);
+
+cairo_private cairo_bool_t
 _cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
 
 cairo_private cairo_bool_t
@@ -1540,8 +1544,9 @@ _cairo_path_fixed_append (cairo_path_fixed_t		  *path,
 			  cairo_direction_t		   dir);
 
 cairo_private void
-_cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
-				       cairo_rectangle_int_t *extents);
+_cairo_path_fixed_approximate_extents (cairo_path_fixed_t	*path,
+				       double			 tolerance,
+				       cairo_box_t		*extents);
 
 cairo_private void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
commit 3a53e0261b1b5af21bf37e2a211eefd501bd5358
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 11:10:17 2008 +0000

    [test] Update twin reference images.
    
    Closing the 'o' in twin has removed a slight artefact - update the reference
    images to match.

diff --git a/test/twin.pdf.ref.png b/test/twin.pdf.ref.png
index b9121e0..366ad9a 100644
Binary files a/test/twin.pdf.ref.png and b/test/twin.pdf.ref.png differ
diff --git a/test/twin.ref.png b/test/twin.ref.png
index 29c2e9e..5c1cf2d 100644
Binary files a/test/twin.ref.png and b/test/twin.ref.png differ
commit c2478de26cc1781b8f8604191a9f75ad29eac746
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 10:50:45 2008 +0000

    [twin] Switch internal users to the new name.
    
    s/<cairo>/@cairo:/

diff --git a/doc/tutorial/src/twin.c b/doc/tutorial/src/twin.c
index e167f26..14347ba 100644
--- a/doc/tutorial/src/twin.c
+++ b/doc/tutorial/src/twin.c
@@ -20,7 +20,7 @@ draw (cairo_t *cr, int width, int height)
 
     cairo_set_source_rgb (cr, 0, 0, 0);
     cairo_select_font_face (cr,
-			    "<cairo>",
+			    "@cairo:",
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
 
diff --git a/test/twin.c b/test/twin.c
index a53b796..b04caf5 100644
--- a/test/twin.c
+++ b/test/twin.c
@@ -33,7 +33,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_set_source_rgb (cr, 0, 0, 0);
 
     cairo_select_font_face (cr,
-			    "<cairo>",
+			    "@cairo:",
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
     cairo_set_font_size (cr, 16);
commit 3424b5f8c8cb1f2ef16b9e8429e64f720106f4d8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 10:47:44 2008 +0000

    [scaled-font] Make check-doc happy
    
    Replace a structure marker '#' with a macro marker '%'.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 52b6fa5..8ffbcb4 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -248,7 +248,7 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
  *
  * This function returns the type of the backend used to create
  * a scaled font. See #cairo_font_type_t for available types.
- * However, this function never returns #CAIRO_FONT_TYPE_TOY.
+ * However, this function never returns %CAIRO_FONT_TYPE_TOY.
  *
  * Return value: The type of @scaled_font.
  *
@@ -2466,7 +2466,7 @@ _cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font)
  *
  * Gets the font face that this scaled font uses.  This is the
  * font face passed to cairo_scaled_font_create() if that font face
- * was not of type #CAIRO_FONT_TYPE_TOY.
+ * was not of type %CAIRO_FONT_TYPE_TOY.
  *
  * Return value: The #cairo_font_face_t with which @scaled_font was
  * created.
commit 449bf0bb7bff38da1c5d0286cb4f22c858bcc3a9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 10:45:22 2008 +0000

    [script] Silence incorrect compiler warnings
    
    Bah, the compiler failed to do its IPA correctly and wrongly complained
    about potential use of uninitialised out-params guarded by the return
    value. Silence them!

diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 28e449e..935ca7f 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -692,7 +692,7 @@ _add_color_stop (csi_t *ctx)
 {
     csi_status_t status;
     double offset, r, g, b, a;
-    cairo_pattern_t *pattern;
+    cairo_pattern_t *pattern = NULL; /* silence the compiler */
 
     check (6);
 
@@ -1103,7 +1103,7 @@ _curve_to (csi_t *ctx)
 static csi_status_t
 _def (csi_t *ctx)
 {
-    csi_name_t name;
+    csi_name_t name = 0; /* silence the compiler */
     csi_status_t status;
 
     check (2);
@@ -1246,7 +1246,7 @@ _filter (csi_t *ctx)
     csi_object_t *src;
     csi_dictionary_t *dict = NULL;
     csi_status_t status;
-    const char *name;
+    const char *name = NULL; /* silence the compiler */
     const struct filters {
 	const char *name;
 	csi_status_t (*constructor) (csi_t *t,
@@ -1771,7 +1771,7 @@ _font (csi_t *ctx)
 {
     csi_dictionary_t *font;
     csi_status_t status;
-    cairo_font_face_t *font_face;
+    cairo_font_face_t *font_face = NULL; /* silence the compiler */
     csi_proxy_t *proxy;
     csi_object_t obj;
     long type;
@@ -2310,7 +2310,7 @@ static csi_status_t
 _if (csi_t *ctx)
 {
     csi_array_t *proc;
-    csi_boolean_t predicate;
+    csi_boolean_t predicate = FALSE; /* silence the compiler */
     csi_status_t status;
 
     check (2);
@@ -2339,7 +2339,7 @@ static csi_status_t
 _ifelse (csi_t *ctx)
 {
     csi_array_t *true_proc, *false_proc;
-    csi_boolean_t predicate;
+    csi_boolean_t predicate = FALSE; /* silence the compiler */
     csi_status_t status;
 
     check (3);
@@ -2654,7 +2654,7 @@ _image_load_from_dictionary (csi_t *ctx,
     long width;
     long height;
     long format;
-    cairo_surface_t *image;
+    cairo_surface_t *image = NULL; /* silence the compiler */
     csi_status_t status;
 
     /* check for "status? */
@@ -2989,9 +2989,9 @@ _null (csi_t *ctx)
 static csi_status_t
 _mask (csi_t *ctx)
 {
-    csi_status_t status;
     cairo_t *cr;
-    cairo_pattern_t *pattern;
+    cairo_pattern_t *pattern = NULL; /* silence the compiler */
+    csi_status_t status;
 
     check (2);
 
@@ -3682,10 +3682,10 @@ _scaled_font (csi_t *ctx)
 {
     csi_object_t obj;
     csi_dictionary_t *dict;
-    csi_status_t status;
-    cairo_font_face_t *font_face;
+    cairo_font_face_t *font_face = NULL; /* silence the compiler */
     cairo_matrix_t font_matrix, ctm;
     cairo_font_options_t *options;
+    csi_status_t status;
 
     check (4);
 
@@ -4063,9 +4063,9 @@ _set_filter (csi_t *ctx)
 static csi_status_t
 _set_font_face (csi_t *ctx)
 {
-    csi_status_t status;
-    cairo_font_face_t *font;
     cairo_t *cr;
+    cairo_font_face_t *font = NULL; /* silence the compiler */
+    csi_status_t status;
 
     check (2);
 
@@ -4264,7 +4264,7 @@ _set_mime_data (csi_t *ctx)
 {
     csi_status_t status;
     csi_object_t *obj;
-    const char *mime;
+    const char *mime = NULL; /* silence the compiler */
     csi_object_t source;
     cairo_surface_t *surface;
     struct _mime_tag *tag;
@@ -4365,9 +4365,9 @@ _set_operator (csi_t *ctx)
 static csi_status_t
 _set_scaled_font (csi_t *ctx)
 {
-    csi_status_t status;
-    cairo_scaled_font_t *font;
     cairo_t *cr;
+    cairo_scaled_font_t *font = NULL; /* silence the compiler */
+    csi_status_t status;
 
     check (2);
 
@@ -4387,7 +4387,7 @@ static csi_status_t
 _set_source (csi_t *ctx)
 {
     cairo_t *cr;
-    cairo_pattern_t *pattern;
+    cairo_pattern_t *pattern = NULL; /* silence the compiler */
     csi_status_t status;
 
     check (2);
@@ -5288,7 +5288,7 @@ _text_path (csi_t *ctx)
 static csi_status_t
 _undef (csi_t *ctx)
 {
-    csi_name_t name;
+    csi_name_t name = 0; /* silence the compiler */
     csi_status_t status;
 
     check (1);
@@ -5309,7 +5309,7 @@ static csi_status_t
 _unset (csi_t *ctx)
 {
     csi_object_t *dst;
-    csi_name_t name;
+    csi_name_t name = 0; /* silence the compiler */
     csi_status_t status;
 
     check (2);
commit ce0b136a441382b25d0932cd66a906a30a693365
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 20:34:45 2008 +0000

    Query the backend to see if we can repaint the solid pattern.
    
    If we are dithering on the Xlib backend we can not simply repaint the
    surface used for a solid pattern and must recreate it from scratch.
    However, for ordinary XRender usage we do not want to have to pay that
    price - so query the backend to see if we can reuse the surface.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 0529a74..e098445 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -749,6 +749,7 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
     _cairo_analysis_surface_has_show_text_glyphs,
     _cairo_analysis_surface_show_text_glyphs
 };
@@ -966,6 +967,7 @@ static const cairo_surface_backend_t cairo_null_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
     NULL, /* has_show_text_glyphs */
     NULL  /* show_text_glyphs */
 };
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 0f6e632..6938526 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -678,6 +678,7 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
 
     _cairo_meta_surface_has_show_text_glyphs,
     _cairo_meta_surface_show_text_glyphs
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index ce4e4de..5d4e08f 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -701,6 +701,7 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
     _cairo_paginated_surface_has_show_text_glyphs,
     _cairo_paginated_surface_show_text_glyphs
 };
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 5862c4b..d453f20 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -5335,6 +5335,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
     NULL, /* reset */
     _cairo_pdf_surface_fill_stroke,
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
     _cairo_pdf_surface_has_show_text_glyphs,
     _cairo_pdf_surface_show_text_glyphs,
 };
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 906e4ed..2585a50 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -2452,6 +2452,7 @@ _cairo_script_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
 
     /* The alternate high-level text operation */
     _cairo_script_surface_has_show_text_glyphs,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 077af5b..4dd034e 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -334,19 +334,19 @@ cairo_surface_t *
 _cairo_surface_create_solid_pattern_surface (cairo_surface_t	   *other,
 					     const cairo_solid_pattern_t *solid_pattern)
 {
-    cairo_surface_t *surface;
+    if (other->backend->create_solid_pattern_surface != NULL) {
+	cairo_surface_t *surface;
 
-    if (other->backend->create_solid_pattern_surface) {
-	surface = other->backend->create_solid_pattern_surface (other, solid_pattern);
+	surface = other->backend->create_solid_pattern_surface (other,
+								solid_pattern);
 	if (surface)
 	    return surface;
     }
 
-    surface = _cairo_surface_create_similar_solid (other,
-						   solid_pattern->content,
-						   1, 1,
-						   &solid_pattern->color);
-    return surface;
+    return _cairo_surface_create_similar_solid (other,
+						solid_pattern->content,
+						1, 1,
+						&solid_pattern->color);
 }
 
 cairo_int_status_t
@@ -354,17 +354,24 @@ _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t	    *other,
 					      cairo_surface_t       *solid_surface,
 					      const cairo_solid_pattern_t *solid_pattern)
 {
-    if (other->backend->create_solid_pattern_surface)
-	/* Solid pattern surface for this backend are not trivial to make.
-	 * Skip repainting.
-	 *
-	 * This does not work optimally with things like analysis surface that
-	 * are proxies.  But returning UNSUPPORTED is *safe* as it only
-	 * disables some caching.
-	 */
+    /* Solid pattern surface for these backends are special and not trivial
+     * to repaint.  Skip repainting.
+     *
+     * This does not work optimally with things like analysis surface that
+     * are proxies.  But returning UNSUPPORTED is *safe* as it only
+     * disables some caching.
+     */
+    if (other->backend->create_solid_pattern_surface != NULL &&
+	! other->backend->can_repaint_solid_pattern_surface (solid_surface,
+							     solid_pattern))
+    {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
-    return _cairo_surface_paint (solid_surface, CAIRO_OPERATOR_SOURCE, &solid_pattern->base, NULL);
+    return _cairo_surface_paint (solid_surface,
+				 CAIRO_OPERATOR_SOURCE,
+				 &solid_pattern->base,
+				 NULL);
 }
 
 cairo_clip_mode_t
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 68d8192..1826ed9 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1310,6 +1310,15 @@ _cairo_xlib_surface_create_solid_pattern_surface (void                  *abstrac
     return &surface->base;
 }
 
+static cairo_bool_t
+_cairo_xlib_surface_can_repaint_solid_pattern_surface (void *abstract_surface,
+						       const cairo_solid_pattern_t *solid_pattern)
+{
+    cairo_xlib_surface_t *other = abstract_surface;
+    return CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other);
+}
+
+
 static cairo_status_t
 _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
 				cairo_matrix_t	     *matrix,
@@ -2469,7 +2478,8 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
     _cairo_xlib_surface_is_similar,
     _cairo_xlib_surface_reset,
     NULL, /* fill_stroke */
-    _cairo_xlib_surface_create_solid_pattern_surface
+    _cairo_xlib_surface_create_solid_pattern_surface,
+    _cairo_xlib_surface_can_repaint_solid_pattern_surface
 };
 
 /**
diff --git a/src/cairoint.h b/src/cairoint.h
index 21c5d62..8166436 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -823,6 +823,11 @@ struct _cairo_surface_backend {
 				 const cairo_solid_pattern_t  *solid_pattern);
 
     cairo_bool_t
+    (*can_repaint_solid_pattern_surface)
+			        (void			      *surface,
+				 const cairo_solid_pattern_t  *solid_pattern);
+
+    cairo_bool_t
     (*has_show_text_glyphs)	(void			    *surface);
 
     cairo_warn cairo_int_status_t
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 42bf6b0..d5e14d7 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -336,6 +336,7 @@ static const cairo_surface_backend_t test_meta_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
     _test_meta_surface_has_show_text_glyphs,
     _test_meta_surface_show_text_glyphs
 };
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 4c56647..d42700c 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -326,6 +326,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend = {
     NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
+    NULL, /* can_repaint_solid_pattern_surface */
 
     _test_paginated_surface_has_show_text_glyphs,
     _test_paginated_surface_show_text_glyphs
commit 0df43251d4b4641d16c0a2e2c49d18dd2a9c832e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 23:45:39 2008 +0000

    [replay] Take advantage of unresolved fonts
    
    As Behdad has changed the underlying ft-font to accept unresolved patterns,
    take advantage of that to simplify the replay code.

diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index b97d936..28e449e 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -1628,8 +1628,7 @@ _ft_create_for_pattern (csi_t *ctx,
     struct _ft_face_data *data;
     csi_list_t *link;
     cairo_font_face_t *font_face;
-    FcPattern *pattern, *resolved;
-    FcResult result;
+    FcPattern *pattern;
     csi_status_t status;
 
     _csi_blob_init (&tmpl, (uint8_t *) string->string, string->len);
@@ -1646,18 +1645,7 @@ _ft_create_for_pattern (csi_t *ctx,
     if (_csi_unlikely (pattern == NULL))
 	return _csi_error (CSI_STATUS_NO_MEMORY);
 
-    FcConfigSubstitute (NULL, pattern, FcMatchPattern);
-    FcDefaultSubstitute (pattern);
-
-    resolved = FcFontMatch (NULL, pattern, &result);
-    if (_csi_unlikely (resolved == NULL)) {
-	FcPatternDestroy (pattern);
-	return _csi_error (CSI_STATUS_NO_MEMORY);
-    }
-
-    font_face = cairo_ft_font_face_create_for_pattern (resolved);
-
-    FcPatternDestroy (resolved);
+    font_face = cairo_ft_font_face_create_for_pattern (pattern);
     FcPatternDestroy (pattern);
 
     data = _csi_slab_alloc (ctx, sizeof (*data));
commit 97a00bdd4eefade8d0808b5572bcdbba26c9c8f3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 17:32:07 2008 +0000

    [cairoint.h] Wrap macro in parenthesis
    
    Ensure that the stride calculation macro is not influenced by surrounding
    precedence issues by enclosing it in a pair of parenthesis.

diff --git a/src/cairoint.h b/src/cairoint.h
index 819d534..21c5d62 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2067,7 +2067,7 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
 /* pixman-required stride alignment in bytes. */
 #define CAIRO_STRIDE_ALIGNMENT (sizeof (uint32_t))
 #define CAIRO_STRIDE_FOR_WIDTH_BPP(w,bpp) \
-   (((bpp)*(w)+7)/8 + CAIRO_STRIDE_ALIGNMENT-1) & ~(CAIRO_STRIDE_ALIGNMENT-1)
+   ((((bpp)*(w)+7)/8 + CAIRO_STRIDE_ALIGNMENT-1) & -CAIRO_STRIDE_ALIGNMENT)
 
 #define CAIRO_CONTENT_VALID(content) ((content) && 			         \
 				      (((content) & ~(CAIRO_CONTENT_COLOR |      \
commit aa65e756d496f4c3a8b43d2100e17dc39c2c26b7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Dec 5 11:21:11 2008 +0000

    [script] Avoid creating 0x0 windows
    
    XCreateWindow dies if asked to create a 0x0 window, so don't and use a 1x1
    pixel window for a zero-sized surface.

diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index 0b4a6bf..ea2b0d4 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -56,8 +56,10 @@ _surface_create (void *closure,
 
     attr.override_redirect = True;
     w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
-			width, height, 0, xrender_format->depth,
-			InputOutput, visual, CWOverrideRedirect, &attr);
+		       width <= 0 ? 1 : width,
+		       height <= 0 ? 1 : height,
+		       0, xrender_format->depth,
+		       InputOutput, visual, CWOverrideRedirect, &attr);
     XMapWindow (dpy, w);
 
     surface = cairo_xlib_surface_create_with_xrender_format (dpy, w,
commit 6458903c95c2bba3f1b9ceaaafb6979d180ab039
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 10:07:32 2008 +0000

    [image] Eliminate the short-lived context used for coercing.
    
    When coercing from one image format to another we performed a paint
    operation using a temporary context - this is overkill as we can just call
    _cairo_surface_paint() directly.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 9b997a9..e9e544d 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1524,35 +1524,41 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
 /* A convenience function for when one needs to coerce an image
  * surface to an alternate format. */
 cairo_image_surface_t *
-_cairo_image_surface_clone (cairo_image_surface_t	*surface,
-			    cairo_format_t		 format)
+_cairo_image_surface_coerce (cairo_image_surface_t	*surface,
+			     cairo_format_t		 format)
 {
     cairo_image_surface_t *clone;
+    cairo_surface_pattern_t pattern;
     cairo_status_t status;
-    cairo_t *cr;
-    double x, y;
 
-    clone = (cairo_image_surface_t *)
-	cairo_image_surface_create (format,
-				    surface->width, surface->height);
+    status = surface->base.status;
+    if (unlikely (status))
+	return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
 
-    cairo_surface_get_device_offset (&surface->base, &x, &y);
-    cairo_surface_set_device_offset (&clone->base, x, y);
-    clone->transparency = CAIRO_IMAGE_UNKNOWN;
+    if (surface->format == format)
+	return (cairo_image_surface_t *)cairo_surface_reference(&surface->base);
 
-    /* XXX Use _cairo_surface_composite directly */
-    cr = cairo_create (&clone->base);
-    cairo_set_source_surface (cr, &surface->base, 0, 0);
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_paint (cr);
-    status = cairo_status (cr);
-    cairo_destroy (cr);
+    clone = (cairo_image_surface_t *)
+	cairo_image_surface_create (format, surface->width, surface->height);
+    if (unlikely (clone->base.status))
+	return clone;
+
+    _cairo_pattern_init_for_surface (&pattern, &surface->base);
+    status = _cairo_surface_paint (&clone->base,
+				   CAIRO_OPERATOR_SOURCE,
+				   &pattern.base, NULL);
+    _cairo_pattern_fini (&pattern.base);
 
     if (unlikely (status)) {
 	cairo_surface_destroy (&clone->base);
-	return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
+	return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
     }
 
+    clone->base.device_transform =
+	surface->base.device_transform;
+    clone->base.device_transform_inverse =
+	surface->base.device_transform_inverse;
+
     return clone;
 }
 
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ffae4d6..52b6fa5 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2077,32 +2077,34 @@ static cairo_status_t
 _trace_mask_to_path (cairo_image_surface_t *mask,
 		     cairo_path_fixed_t *path)
 {
-    cairo_status_t status;
-    cairo_image_surface_t *a1_mask;
-    uint8_t *row, *byte_ptr, byte;
+    const uint8_t *row;
     int rows, cols, bytes_per_row;
     int x, y, bit;
     double xoff, yoff;
+    cairo_status_t status;
 
-    if (mask->format == CAIRO_FORMAT_A1)
-	a1_mask = (cairo_image_surface_t *) cairo_surface_reference (&mask->base);
-    else
-	a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1);
-
-    status = cairo_surface_status (&a1_mask->base);
-    if (unlikely (status)) {
-	cairo_surface_destroy (&a1_mask->base);
+    mask = _cairo_image_surface_coerce (mask, CAIRO_FORMAT_A1);
+    status = mask->base.status;
+    if (unlikely (status))
 	return status;
-    }
 
     cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
 
-    bytes_per_row = (a1_mask->width + 7) / 8;
-    for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) {
-	for (x = 0, byte_ptr = row, cols = bytes_per_row; cols; byte_ptr++, cols--) {
-	    byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
-	    for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
-		if (byte & (1 << bit)) {
+    bytes_per_row = (mask->width + 7) / 8;
+    row = mask->data;
+    for (y = 0, rows = mask->height; rows--; row += mask->stride, y++) {
+	const uint8_t *byte_ptr = row;
+	x = 0;
+	for (cols = bytes_per_row; cols--; ) {
+	    uint8_t byte = *byte_ptr++;
+	    if (byte == 0) {
+		x += 8;
+		continue;
+	    }
+
+	    byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (byte);
+	    for (bit = 1 << 7; bit && x < mask->width; bit >>= 1, x++) {
+		if (byte & bit) {
 		    status = _add_unit_rectangle_to_path (path,
 							  x - xoff, y - yoff);
 		    if (unlikely (status))
@@ -2113,7 +2115,7 @@ _trace_mask_to_path (cairo_image_surface_t *mask,
     }
 
 BAIL:
-    cairo_surface_destroy (&a1_mask->base);
+    cairo_surface_destroy (&mask->base);
 
     return status;
 }
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index e81ccd8..db554a1 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -657,8 +657,8 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t	*document,
 					    cairo_scaled_font_t		*scaled_font,
 					    unsigned long		 glyph_index)
 {
-    cairo_image_surface_t *image;
     cairo_scaled_glyph_t *scaled_glyph;
+    cairo_image_surface_t *image;
     cairo_status_t status;
     uint8_t *row, *byte;
     int rows, cols;
@@ -666,18 +666,17 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t	*document,
 
     status = _cairo_scaled_glyph_lookup (scaled_font,
 					 glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_METRICS|
+					 CAIRO_SCALED_GLYPH_INFO_METRICS |
 					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					 &scaled_glyph);
     if (unlikely (status))
 	return status;
 
-    image = scaled_glyph->surface;
-    if (image->format != CAIRO_FORMAT_A1) {
-	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	if (cairo_surface_status (&image->base))
-	    return cairo_surface_status (&image->base);
-    }
+    image = _cairo_image_surface_coerce (scaled_glyph->surface,
+					 CAIRO_FORMAT_A1);
+    status = image->base.status;
+    if (unlikely (status))
+	return status;
 
     _cairo_output_stream_printf (document->xml_node_glyphs, "<g");
     _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform",
@@ -698,8 +697,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t	*document,
     }
     _cairo_output_stream_printf (document->xml_node_glyphs, "</g>\n");
 
-    if (image != scaled_glyph->surface)
-	cairo_surface_destroy (&image->base);
+    cairo_surface_destroy (&image->base);
 
     return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index b3a4831..3ff5003 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -87,18 +87,6 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 				       cairo_matrix_t              *image_matrix)
 {
     cairo_status_t status;
-    cairo_image_surface_t *image_mask;
-
-    /* The only image type supported by Type 3 fonts are 1-bit image
-     * masks */
-    if (image->format == CAIRO_FORMAT_A1) {
-	image_mask = image;
-    } else {
-	image_mask = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	status = cairo_surface_status (&image->base);
-	if (unlikely (status))
-	    return status;
-    }
 
     _cairo_output_stream_printf (surface->stream,
 				 "q %f %f %f %f %f %f cm\n",
@@ -109,14 +97,14 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 				 image_matrix->x0,
 				 image_matrix->y0);
 
-    status = surface->emit_image (image_mask, surface->stream);
+    /* 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);
 
     _cairo_output_stream_printf (surface->stream,
 				 "Q\n");
 
-    if (image_mask != image)
-	cairo_surface_destroy (&image_mask->base);
-
     return status;
 }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 55752f5..819d534 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2139,8 +2139,8 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
 				      cairo_region_t *region);
 
 cairo_private cairo_image_surface_t *
-_cairo_image_surface_clone (cairo_image_surface_t	*surface,
-			    cairo_format_t		 format);
+_cairo_image_surface_coerce (cairo_image_surface_t	*surface,
+			     cairo_format_t		 format);
 
 cairo_private cairo_image_transparency_t
 _cairo_image_analyze_transparency (cairo_image_surface_t      *image);
commit 9b46d13b6cd58c711010df89a41b216c5cc8c881
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 23:52:32 2008 +0000

    [trace] Runtime version check.
    
    Check that the application is using cairo >= 1.9 before attempting to
    query the mime-data.

diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 1b27fe4..30656a1 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -1137,11 +1137,6 @@ _emit_image (cairo_surface_t *image,
     uint8_t *rowdata;
     uint8_t *data;
     struct _data_stream stream;
-    const char *mime_types[] = {
-	CAIRO_MIME_TYPE_JPEG,
-	CAIRO_MIME_TYPE_PNG,
-	NULL
-    }, **mime_type;
 
     if (cairo_surface_status (image)) {
 	fprintf (logfile,
@@ -1173,24 +1168,32 @@ _emit_image (cairo_surface_t *image,
 	va_end (ap);
     }
 
-    for (mime_type = mime_types; *mime_type; mime_type++) {
-	const unsigned char *mime_data;
-	unsigned int mime_length;
+    if (cairo_version () >= CAIRO_VERSION_ENCODE (1, 9, 0)) {
+	const char *mime_types[] = {
+	    CAIRO_MIME_TYPE_JPEG,
+	    CAIRO_MIME_TYPE_PNG,
+	    NULL
+	}, **mime_type;
 
-	cairo_surface_get_mime_data (image, *mime_type,
-				     &mime_data, &mime_length);
-	if (mime_data != NULL) {
-	    fprintf (logfile,
-		     "  /mime-type (%s) set\n"
-		     "  /source <~",
-		     *mime_type);
-	    _write_base85_data_start (&stream);
-	    _write_base85_data (&stream, mime_data, mime_length);
-	    _write_base85_data_end (&stream);
-	    fprintf (logfile,
-		     "~> set\n"
-		     "  image");
-	    return;
+	for (mime_type = mime_types; *mime_type; mime_type++) {
+	    const unsigned char *mime_data;
+	    unsigned int mime_length;
+
+	    cairo_surface_get_mime_data (image, *mime_type,
+					 &mime_data, &mime_length);
+	    if (mime_data != NULL) {
+		fprintf (logfile,
+			 "  /mime-type (%s) set\n"
+			 "  /source <~",
+			 *mime_type);
+		_write_base85_data_start (&stream);
+		_write_base85_data (&stream, mime_data, mime_length);
+		_write_base85_data_end (&stream);
+		fprintf (logfile,
+			 "~> set\n"
+			 "  image");
+		return;
+	    }
 	}
     }
 
commit 2d790daa957471670f4ae0d3b22da89e4ee7111f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 00:47:08 2008 +0000

    [pattern] Use a solid pattern for a uniform gradient.
    
    If each color stop in a gradient is identical, replace the gradient
    surface with a simple solid surface. As seen in the wild.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 9477f87..3a4a9c8 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2073,19 +2073,15 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 
 	    if (src->n_stops)
 	    {
-		cairo_color_t color;
-
-		_cairo_color_init_rgba (&color,
-					src->stops->color.red,
-					src->stops->color.green,
-					src->stops->color.blue,
-					src->stops->color.alpha);
-
-		_cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA);
+		_cairo_pattern_init_solid (&solid,
+					   &src->stops->color,
+					   CAIRO_CONTENT_COLOR_ALPHA);
 	    }
 	    else
 	    {
-		_cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
+		_cairo_pattern_init_solid (&solid,
+					   CAIRO_COLOR_TRANSPARENT,
+					   CAIRO_CONTENT_ALPHA);
 	    }
 
 	    status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
@@ -2096,11 +2092,39 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 	}
 	else
 	{
-	    status = _cairo_pattern_acquire_surface_for_gradient (src, dst,
-								  x, y,
-								  width, height,
-								  surface_out,
-								  attributes);
+	    unsigned int i;
+
+	    /* Is the gradient a uniform colour?
+	     * Happens more often than you would believe.
+	     */
+	    for (i = 1; i < src->n_stops; i++) {
+		if (! _cairo_color_equal (&src->stops[0].color,
+					  &src->stops[i].color))
+		{
+		    break;
+		}
+	    }
+	    if (i == src->n_stops) {
+		cairo_solid_pattern_t solid;
+
+		_cairo_pattern_init_solid (&solid,
+					   &src->stops->color,
+					   CAIRO_CONTENT_COLOR_ALPHA);
+
+		status =
+		    _cairo_pattern_acquire_surface_for_solid (&solid, dst,
+							      x, y,
+							      width, height,
+							      surface_out,
+							      attributes);
+	    } else {
+		status =
+		    _cairo_pattern_acquire_surface_for_gradient (src, dst,
+								 x, y,
+								 width, height,
+								 surface_out,
+								 attributes);
+	    }
 	}
     } break;
     case CAIRO_PATTERN_TYPE_SURFACE: {
commit 25a4677200ea6689be0dca9d533842dc7da54837
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 17 09:29:35 2008 +0000

    [analysis] Use approximate extents.
    
    Use the approximate path based extents to avoid tessellation.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 50005c2..0529a74 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -446,7 +446,6 @@ _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_bool_t             is_empty;
 
@@ -478,26 +477,22 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t box;
-
-	_cairo_box_from_rectangle (&box, &extents);
-
-	_cairo_traps_init (&traps);
-	_cairo_traps_limit (&traps, &box);
-	status = _cairo_path_fixed_stroke_to_traps (path,
-						    style,
-						    ctm, ctm_inverse,
-						    tolerance,
-						    &traps);
-	if (unlikely (status)) {
-	    _cairo_traps_fini (&traps);
-	    return status;
-	}
+	cairo_rectangle_int_t mask_extents;
+	double dx, dy;
+
+	_cairo_path_fixed_approximate_extents (path, &mask_extents);
+
+	_cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy);
+
+	mask_extents.width += mask_extents.x + ceil (dx);
+	mask_extents.x -= ceil (dx);
+	mask_extents.width -= mask_extents.x;
 
-	_cairo_traps_extents (&traps, &box);
-	_cairo_traps_fini (&traps);
+	mask_extents.height += mask_extents.y + ceil (dy);
+	mask_extents.y -= ceil (dy);
+	mask_extents.height -= mask_extents.y;
 
-        _cairo_box_round_to_rectangle (&box, &extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
     if (stroke_extents)
 	*stroke_extents = extents;
@@ -519,7 +514,6 @@ _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_bool_t             is_empty;
 
@@ -550,25 +544,11 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t box;
-
-	_cairo_box_from_rectangle (&box, &extents);
-
-	_cairo_traps_init (&traps);
-	_cairo_traps_limit (&traps, &box);
-	status = _cairo_path_fixed_fill_to_traps (path,
-						  fill_rule,
-						  tolerance,
-						  &traps);
-	if (unlikely (status)) {
-	    _cairo_traps_fini (&traps);
-	    return status;
-	}
+	cairo_rectangle_int_t mask_extents;
 
-	_cairo_traps_extents (&traps, &box);
-	_cairo_traps_fini (&traps);
+	_cairo_path_fixed_approximate_extents (path, &mask_extents);
 
-        _cairo_box_round_to_rectangle (&box, &extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
     if (fill_extents)
 	*fill_extents = extents;


More information about the cairo-commit mailing list