[cairo-commit] Branch '1.4' - 60 commits - autogen.sh ChangeLog.mk configure.in pixman/src src/cairo-array.c src/cairo-atsui-font.c src/cairo.c src/cairo-cff-subset.c src/cairo-ft-font.c src/cairo-glitz-surface.c src/cairo-gstate.c src/cairo-image-surface.c src/cairo-lzw.c src/cairo-malloc-private.h src/cairo-meta-surface.c src/cairo-mutex-type-private.h src/cairo-path.c src/cairo-path-stroke.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-pen.c src/cairo-polygon.c src/cairo-quartz-surface.c src/cairo-spline.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-surface-fallback-private.h src/cairo-traps.c src/cairo-truetype-subset.c src/cairo-type1-subset.c src/cairo-win32-font.c src/cairo-win32-surface.c src/cairo-xlib-display.c src/cairo-xlib-surface.c src/Makefile.am test/bitmap-font.c test/copy-path.c test/ft-text-vertical-layout-type1-ps-argb32-ref.png test/ft-text-vertical-layout-type3-ps-argb32-ref.png test/Makefile.am

Carl Worth cworth at kemper.freedesktop.org
Wed Nov 21 10:59:57 PST 2007


Rebased ref, commits from common ancestor:
commit 4df0d28bf0c5488370b216f83367adf282c9183c
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 20 20:48:47 2007 -0800

    Mark bitmap-font as XFAIL
    
    I don't know where the PDF failure is coming from, (it appears
    to be using a too-small font in the rotate cairo_show_text
    case), but I'm seeing the same behavior in 1.4.10 so this
    is not a regression compared to that for the purpose of the
    1.4.12 release.

diff --git a/test/Makefile.am b/test/Makefile.am
index 14d3717..716f558 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -437,6 +437,7 @@ $(REFERENCE_IMAGES)
 XFAIL_TESTS =			\
 a8-mask				\
 big-trap			\
+bitmap-font			\
 extend-pad			\
 filter-nearest-offset		\
 long-lines			\
diff --git a/test/bitmap-font.c b/test/bitmap-font.c
index 2a9754e..ca38f36 100644
--- a/test/bitmap-font.c
+++ b/test/bitmap-font.c
@@ -40,7 +40,8 @@ static cairo_test_draw_function_t draw;
 
 cairo_test_t test = {
     "bitmap-font",
-    "Test drawing with a font consisting only of bitmaps",
+    "Test drawing with a font consisting only of bitmaps"
+    "\nPDF backend is failing for an unknown reason (not a regression compared to 1.4.10",
     246 + 1, 2 * TEXT_SIZE,
     draw
 };
commit 34235941fd558d1e2b603f8765e78ed9e8e407af
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 20 20:45:42 2007 -0800

    Update two PS reference images for mysterious single-pixel change
    
    It seems ft-vertical-layout-type1 and ft-vertical-layout-type3
    change rasterization slightly from time to time, (may be due
    to changes in the system installation of ghostscript).

diff --git a/test/ft-text-vertical-layout-type1-ps-argb32-ref.png b/test/ft-text-vertical-layout-type1-ps-argb32-ref.png
index bc71bbc..56943e4 100644
Binary files a/test/ft-text-vertical-layout-type1-ps-argb32-ref.png and b/test/ft-text-vertical-layout-type1-ps-argb32-ref.png differ
diff --git a/test/ft-text-vertical-layout-type3-ps-argb32-ref.png b/test/ft-text-vertical-layout-type3-ps-argb32-ref.png
index e5b12bf..08581e5 100644
Binary files a/test/ft-text-vertical-layout-type3-ps-argb32-ref.png and b/test/ft-text-vertical-layout-type3-ps-argb32-ref.png differ
commit 6e0f840d0636b7a0bccb84a9fe9871edb2591df9
Author: Richard Hult <richard at imendio.com>
Date:   Mon Nov 5 10:05:07 2007 +0000

    [atsui] Use ascent+descent+leading to get the distance between baselines
    
    The height is currently mapped to the atsui metrics property capHeight, which
    is documented as "The height of a capital letter in the font from the baseline
    to the top of the letter".
    
    That doesn't match what height is in cairo, it should be the disctance between
    baselines. This patch that fixes that (and makes webkit on GTK+ OS X
    layout nicely).
    (cherry picked from commit 4270cd3358fabf0d3e6ac4e866099b172082b592)

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 68bcae4..211cf66 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -221,7 +221,7 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
 
             extents.ascent = metrics.ascent;
             extents.descent = -metrics.descent;
-            extents.height = metrics.capHeight;
+            extents.height = extents.ascent + extents.descent + metrics.leading;
             extents.max_x_advance = metrics.maxAdvanceWidth;
 
             /* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
commit 3fa690904281b2f3c04e0cf7a480c04f08502018
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Nov 5 10:05:04 2007 +0000

    [configure.in] fix atsui experimental warning
    
    The 'experimental' warning for atsui was appearing
    for --enable-quartz not --enable-atsui as it should.
    (cherry picked from commit 3141b21c0c581dabc09a6ec9cdf0a071701b0e42)

diff --git a/configure.in b/configure.in
index a448115..515b06e 100644
--- a/configure.in
+++ b/configure.in
@@ -1007,7 +1007,7 @@ if test x"$use_quartz" = "xyes" ; then
    echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/Quartz/'
 fi
 
-if test x"$use_quartz" = "xyes" ; then
+if test x"$use_atsui" = "xyes" ; then
    echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/ATSUI/'
 fi
 
commit 7c2fecc01d499ab5b95ae69c3dce11cfe66959b3
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Oct 30 22:00:59 2007 -0700

    Force non-AA text when using a bitmap strike with only scaling transform.
    
    When the current font size matches one of the available fixed sizes, and
    the overall transform has only scaling components, FreeType will use the
    fixed size bitmaps by default. For glyphs which do not have bitmaps,
    force them to be rendered in monochrome instead of anti-aliased so
    that they all match nicely.
    (cherry picked from commit 06af5c2891b89da28581c30afcde06c5442884db)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 914dc0b..804ecc2 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1512,6 +1512,30 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t	 *unscaled,
 	return NULL;
     }
 
+    /*
+     * Force non-AA drawing when using a bitmap strike that
+     * won't be resampled due to non-scaling transform
+     */
+    if (!unscaled->have_shape &&
+	(scaled_font->ft_options.load_flags & FT_LOAD_NO_BITMAP) == 0 &&
+	scaled_font->ft_options.base.antialias != CAIRO_ANTIALIAS_NONE &&
+	(face->face_flags & FT_FACE_FLAG_FIXED_SIZES))
+    {
+	int		i;
+	FT_Size_Metrics	*size_metrics = &face->size->metrics;
+
+	for (i = 0; i < face->num_fixed_sizes; i++)
+	{
+	    FT_Bitmap_Size  *bitmap_size = &face->available_sizes[i];
+
+	    if (bitmap_size->x_ppem == size_metrics->x_ppem * 64 &&
+		bitmap_size->y_ppem == size_metrics->y_ppem * 64)
+	    {
+		scaled_font->ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
+		break;
+	    }
+	}
+    }
 
     metrics = &face->size->metrics;
 
commit a84f6783dad24970c6d4193691b6192a6f750391
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Oct 30 17:09:56 2007 -0700

    Fix degenerate-pen test case by removing the triggering assertion
    
    Instead we choose either the first or last pen vertex as
    appropriate.
    
    This makes the degenerate-pen pass stop failing on an
    assertion, and passes for most backends. It's still failing
    for the PDF backend, but that looks like a new, PDF-specific
    bug.
    (cherry picked from commit 448c9314252bba779194d2b01950b8738b26fd13)

diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index a181925..24c3eae 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -322,7 +322,13 @@ _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
 	    break;
     }
 
-    assert (i < pen->num_vertices);
+    /* If the desired slope cannot be found between any of the pen
+     * vertices, then we must have a degenerate pen, (such as a pen
+     * that's been transformed to a line). In that case, we consider
+     * the first pen vertex as the appropriate clockwise vertex.
+     */
+    if (i == pen->num_vertices)
+	i = 0;
 
     *active = i;
 
@@ -352,6 +358,14 @@ _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
 	    break;
     }
 
+    /* If the desired slope cannot be found between any of the pen
+     * vertices, then we must have a degenerate pen, (such as a pen
+     * that's been transformed to a line). In that case, we consider
+     * the last pen vertex as the appropriate counterclockwise vertex.
+     */
+    if (i < 0)
+	i = pen->num_vertices - 1;
+
     *active = i;
 
     return CAIRO_STATUS_SUCCESS;
commit b97705a680d9d3cc06e7aef578edf6ba94fda096
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Oct 29 17:55:28 2007 -0700

    Limit miters for small angles
    
    This fixes the current failure get-path-extents, which is a
    demonstration of the following bug:
    
    	cairo_stroke_extents() gives wrong result for arcs in some cases
    	https://bugs.freedesktop.org/show_bug.cgi?id=7245
    
    Many thanks to Michael Urman whose review of early versions of
    this work found a fatal mistake in my algebra.
    (cherry picked from commit 00d701ff7de68609aa8cec7871d93b27a108fd14)

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 6502a94..8535828 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -280,6 +280,9 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
 	double	in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+
 			      (-in->usr_vector.y * out->usr_vector.y));
 	double	ml = stroker->style->miter_limit;
+	double tolerance_squared = stroker->tolerance * stroker->tolerance;
+	double line_width_squared = (stroker->style->line_width *
+				     stroker->style->line_width);
 
 	/*
 	 * Check the miter limit -- lines meeting at an acute angle
@@ -308,8 +311,79 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
 	 *
 	 *	2 <= ml² (1 - in · out)
 	 *
+	 *
+	 * That gives us the condition to avoid generating miters that
+	 * are too large from angles that are too large. But we also
+	 * need to avoid generating miters when the angle is very small.
+	 *
+	 * The miter formed from a tiny angle is also tiny, so the
+	 * miter limit is not a concern. But with a tiny angle we will
+	 * be computing the intersection of two lines that are very
+	 * near parallel. Also, the limits of the fixed-point grid on
+	 * the input face coordinates mean that the resulting
+	 * intersection could be wildly wrong. (See the
+	 * get-path-extents test case for a call to cairo_arc that
+	 * results in two problematic faces.)
+	 *
+	 * Fortunately we can also derive an expression for when using
+	 * a bevel join instead of a miter will introduce an error no
+	 * larger than the tolerance. Consider the same join from
+	 * before but with the miter now chopped off and replaced with
+	 * a bevel join. The drawing is zoomed in a bit again, the
+	 * point marked as '*' is the center of the stroke---the point
+	 * where the two line segments of interest intersect:
+	 *
+	 *    ----- .
+	 *    ^     ..
+	 *    |     . .
+	 *    |     .  .
+	 *   1/2    .   .
+	 *  miter   .    .         |
+	 *  length  .     .        |
+	 *    |     .______.    ___v___
+	 *    |     |     . \   1/2 bevel
+	 *    v     |  .     \   width
+	 *    ----  *         \ -------
+	 *	    |          \   ^
+	 *
+	 *
+	 * The length of interest here is the vertical length of the
+	 * miter that is eliminated. It's length can be obtained by
+	 * starting with 1/2 the miter length and the subtracting off
+	 * the vertical length that is included by the bevel join,
+	 * (here termed 1/2 bevel width). To determine this new bevel
+	 * width, we have a small right triangle shown, the hypotenuse
+	 * of which has a length of 1/2 the line width, and the small
+	 * angle at the upper right of the figure is psi/2.
+	 *
+	 * So we have:
+	 *
+	 *	sin (psi/2) = (bevel_width / 2) / (line_width / 2)
+	 *
+	 * And we can determine when the miter is required by
+	 * calculating when the eliminated portion of the miter is
+	 * greater than the tolerance:
+	 *
+	 *	(miter_length / 2) - (bevel_width / 2) > tolerance
+	 *
+	 * Substituting in the above expressions for miter_length and
+	 * bevel_width:
+	 *
+	 *	(line_width/2) / sin (psi/2) - (line_width/2) * sin (psi/2) > tolerance
+	 *	1 / sin(psi/2) - sin (psi/2) > 2 * tolerance / line_width
+	 *	1 / sin²(psi/2) -2 +  sin²(psi/2) > 4 * (tolerance/line_width)²
+	 *
+	 * Use identity: sin²(psi/2) = (1-cos(psi))/2
+
+	 *	2/(1 - cos(psi)) - 2 + (1-cos(psi))/2 > 4 * (tolerance/line_width)²
+	 *	4/(1 - cos(psi)) - 4 + (1-cos(psi)) > 8 * (tolerance/line_width)²
+	 *	4/(1 - cos(psi)) + (1-cos(psi)) > 8 * ((tolerance/line_width)² + 0.5)
 	 */
-	if (2 <= ml * ml * (1 - in_dot_out)) {
+	if ((2 <= ml * ml * (1 - in_dot_out)) &&
+	    ((8 * (tolerance_squared / line_width_squared + 0.5)) <
+	     4 / (1 - in_dot_out) + (1 - in_dot_out))
+	    )
+	{
 	    double		x1, y1, x2, y2;
 	    double		mx, my;
 	    double		dx1, dx2, dy1, dy2;
commit 5eb2507f785d742d330cf8f394f343095810d8c1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Oct 30 11:13:44 2007 +0000

    [cairo-surface] Fix typo in doc.
    
    s/INVALUE_FORMAT/INVALID_FORMAT/
    (cherry picked from commit 0d42af2427d1de27845cb8a6b3d290a562c28fc6)

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index b6720c4..0d31d04 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -164,7 +164,7 @@ slim_hidden_def(cairo_surface_get_content);
  *
  * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NULL_POINTER,
  * %CAIRO_STATUS_NO_MEMORY, %CAIRO_STATUS_READ_ERROR,
- * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALUE_FORMAT, or
+ * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALID_FORMAT, or
  * %CAIRO_STATUS_INVALID_VISUAL.
  **/
 cairo_status_t
commit 2012e14cf3305f4cc7a1eafa012aedbe6bb5e3e8
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Oct 26 22:58:57 2007 -0700

    Fix typo in _cairo_gstate_fini
    
    Obrigado a Luiz Americo Pereira Camara <luizmed at oi.com.br>
    (cherry picked from commit a69d4731300b430b802222d317698c313c75a31a)

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 21a6395..185224d 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -170,7 +170,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
     gstate->parent_target = NULL;
 
     cairo_surface_destroy (gstate->original_target);
-    gstate->target = NULL;
+    gstate->original_target = NULL;
 
     cairo_pattern_destroy (gstate->source);
     gstate->source = NULL;
commit 4a99c781f47a13ecd299f23f60d572c405cf3a37
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Oct 20 23:41:46 2007 +0100

    [quartz] return status instead of CGPatternRef
    
    Returning status improves error handling, since
    returning NULL doesn't let us distinguish different
    types of error.
    (cherry picked from commit 8f6abdbc26ee15451b5a386610f7d5a7a9114d63)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 95c8380..b7b52b0 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -555,9 +555,10 @@ _init_pattern_with_snapshot (cairo_pattern_t *pattern,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static CGPatternRef
+static cairo_int_status_t
 _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest,
-							  cairo_pattern_t *abspat)
+							 cairo_pattern_t *abspat,
+							 CGPatternRef *cgpat)
 {
     cairo_surface_pattern_t *spat;
     cairo_surface_t *pat_surf;
@@ -568,7 +569,6 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     CGPatternCallbacks cb = { 0,
 			      SurfacePatternDrawFunc,
 			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
-    CGPatternRef cgpat;
     float rw, rh;
     cairo_status_t status;
 
@@ -578,14 +578,14 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     cairo_matrix_t m;
     /* SURFACE is the only type we'll handle here */
     if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
-	return NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     spat = (cairo_surface_pattern_t *) abspat;
     pat_surf = spat->surface;
 
     status = _cairo_surface_get_extents (pat_surf, &extents);
     if (status)
-	return NULL;
+	return status;
 
     pbounds.origin.x = 0;
     pbounds.origin.y = 0;
@@ -638,14 +638,14 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
 	target_pattern = abspat;
     }
 
-    cgpat = CGPatternCreate (target_pattern,
+    *cgpat = CGPatternCreate (target_pattern,
 			     pbounds,
 			     ptransform,
 			     rw, rh,
 			     kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
 			     TRUE,
 			     &cb);
-    return cgpat;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 typedef enum {
@@ -726,9 +726,11 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
     } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	float patternAlpha = 1.0f;
 	CGColorSpaceRef patternSpace;
+	CGPatternRef pattern;
+	cairo_int_status_t status;
 
-	CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
-	if (!pattern)
+	status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
+	if (status)
 	    return DO_UNSUPPORTED;
 
 	// Save before we change the pattern, colorspace, etc. so that
commit f41163707167225cc1bb7639ff075b3f27c43f1c
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Oct 20 23:41:32 2007 +0100

    [quartz] return status instead of cairo_quartz_surface_t
    
    Returning status improves error handling, since
    returning NULL doesn't let us distinguish different
    types of error.
    (cherry picked from commit cfb26fdf0f490b4902106b50d02628cffd53a0eb)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 6ca4605..95c8380 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -427,10 +427,11 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat,
 }
 
 /* generic cairo surface -> cairo_quartz_surface_t function */
-static cairo_quartz_surface_t *
-_cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_surf)
+static cairo_int_status_t
+_cairo_quartz_surface_to_quartz (cairo_surface_t *target,
+				 cairo_surface_t *pat_surf,
+				 cairo_quartz_surface_t **quartz_surf)
 {
-    cairo_quartz_surface_t *quartz_surf = NULL;
 
     if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
 	/* XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
@@ -447,7 +448,7 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_s
 
 	status = _cairo_surface_get_extents (pat_surf, &rect);
 	if (status)
-	    return NULL;
+	    return status;
 
 	status = _cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
 				      rect.width, rect.height, &new_surf);
@@ -455,18 +456,18 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_s
 	    cairo_surface_destroy(ref_type);
 
         if (status)
-	    return NULL;
+	    return status;
 
-	quartz_surf = (cairo_quartz_surface_t *) new_surf;
+	*quartz_surf = (cairo_quartz_surface_t *) new_surf;
     } else {
 	/* If it's a quartz surface, we can try to see if it's a CGBitmapContext;
 	 * we do this when we call CGBitmapContextCreateImage below.
 	 */
 	cairo_surface_reference (pat_surf);
-	quartz_surf = (cairo_quartz_surface_t*) pat_surf;
+	*quartz_surf = (cairo_quartz_surface_t*) pat_surf;
     }
 
-    return quartz_surf;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 /* Generic cairo_pattern -> CGPattern function */
@@ -475,13 +476,14 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
 {
     cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
     cairo_surface_t *pat_surf = spat->surface;
+    cairo_int_status_t status;
 
     cairo_quartz_surface_t *quartz_surf;
     CGImageRef img;
     CGRect imageBounds;
 
-    quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
-    if (!quartz_surf)
+    status = _cairo_quartz_surface_to_quartz (NULL, pat_surf, &quartz_surf);
+    if (status)
 	return;
 
     img = CGBitmapContextCreateImage (quartz_surf->cgContext);
@@ -699,8 +701,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	    cairo_rectangle_int16_t extents;
 	    cairo_status_t status;
 
-	    quartz_surf = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf);
-	    if (!quartz_surf)
+	    status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf);
+	    if (status)
 		return DO_UNSUPPORTED;
 
 	    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
@@ -1492,7 +1494,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 }
 #endif /* CAIRO_HAS_ATSUI_FONT */
 
-static cairo_status_t
+static cairo_int_status_t
 _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
                                          cairo_operator_t op,
                                          cairo_pattern_t *source,
@@ -1509,7 +1511,9 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
     if (status)
 	return status;
 
-    quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
+    status = _cairo_quartz_surface_to_quartz (NULL, pat_surf, &quartz_surf);
+    if (status)
+	return status;
 
     img = CGBitmapContextCreateImage (quartz_surf->cgContext);
     if (!img) {
commit 6aebde2224aada5ba4589493cbaf174d716efd45
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Oct 20 22:45:30 2007 +0100

    [quartz] return status instead of CGShadingRef
    
    Returning status improves error handling, since
    returning NULL doesn't let us distinguish different
    types of error. Suggested by Chris Wilson.
    (cherry picked from commit dec3099585eeb184ed51b5c720eb891314d7ea51)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 7f1a3f1..6ca4605 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -338,22 +338,23 @@ CreateGradientFunction (cairo_gradient_pattern_t *gpat)
 			     &callbacks);
 }
 
-static CGShadingRef
-_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
+static cairo_int_status_t
+_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat,
+						CGShadingRef *shading)
 {
     cairo_matrix_t mat;
     double x0, y0;
 
     if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
 	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
-	return NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* bandaid for mozilla bug 379321, also visible in the
      * linear-gradient-reflect test. 
      */
     if (abspat->extend == CAIRO_EXTEND_REFLECT ||
 	abspat->extend == CAIRO_EXTEND_REPEAT)
-	return NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 	
     /* We can only do this if we have an identity pattern matrix;
      * otherwise fall back through to the generic pattern case.
@@ -364,14 +365,13 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
      */
     cairo_pattern_get_matrix (abspat, &mat);
     if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
-	return NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     x0 = mat.x0;
     y0 = mat.y0;
 
     if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) {
 	cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat;
-	CGShadingRef shading;
 	CGPoint start, end;
 	CGFunctionRef gradFunc;
 	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
@@ -384,19 +384,18 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 
 	cairo_pattern_reference (abspat);
 	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
-	shading = CGShadingCreateAxial (rgb,
+	*shading = CGShadingCreateAxial (rgb,
 					start, end,
 					gradFunc,
 					extend, extend);
 	CGColorSpaceRelease(rgb);
 	CGFunctionRelease(gradFunc);
 
-	return shading;
+	return CAIRO_STATUS_SUCCESS;
     }
 
     if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) {
 	cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat;
-	CGShadingRef shading;
 	CGPoint start, end;
 	CGFunctionRef gradFunc;
 	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
@@ -409,7 +408,7 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 
 	cairo_pattern_reference (abspat);
 	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
-	shading = CGShadingCreateRadial (rgb,
+	*shading = CGShadingCreateRadial (rgb,
 					 start,
 					 _cairo_fixed_to_double (rpat->gradient.c1.radius),
 					 end,
@@ -419,12 +418,12 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 	CGColorSpaceRelease(rgb);
 	CGFunctionRelease(gradFunc);
 
-	return shading;
+	return CAIRO_STATUS_SUCCESS;
     }
 
     /* Shouldn't be reached */
     ASSERT_NOT_REACHED;
-    return NULL;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 /* generic cairo surface -> cairo_quartz_surface_t function */
@@ -679,8 +678,11 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
     } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR ||
 	       source->type == CAIRO_PATTERN_TYPE_RADIAL)
     {
-	CGShadingRef shading = _cairo_quartz_cairo_gradient_pattern_to_quartz (source);
-	if (!shading)
+	CGShadingRef shading = NULL;
+	cairo_int_status_t status;
+
+	status = _cairo_quartz_cairo_gradient_pattern_to_quartz (source, &shading);
+	if (status)
 	    return DO_UNSUPPORTED;
 
 	surface->sourceShading = shading;
commit aea3eb85b04fb61a05ed1bf4fca8401af4f29eef
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Jul 1 14:37:57 2007 +0100

    implement clipping with surface masks.
    
    This implements clipping using CGContextClipToMask, which
    means that it will only have an effect on OS X 10.4+.
    No additional tests pass with this fix - mainly due to
    text effects and problems with the IN, OUT, DEST_IN, DEST_ATOP
    operators.
    (cherry picked from commit 481ce2b8cb2dc376419e7d6cbdd73bd4ebcd5b5b)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 889e8e2..7f1a3f1 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -89,6 +89,8 @@ CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
 CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
 #endif
 
+/* missing in 10.3.9 */
+extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import));
 
 /*
  * Utility functions
@@ -1488,6 +1490,43 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 }
 #endif /* CAIRO_HAS_ATSUI_FONT */
 
+static cairo_status_t
+_cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
+                                         cairo_operator_t op,
+                                         cairo_pattern_t *source,
+                                         cairo_surface_pattern_t *mask)
+{
+    cairo_rectangle_int16_t extents;
+    cairo_quartz_surface_t *quartz_surf;
+    CGRect rect;
+    CGImageRef img;
+    cairo_surface_t *pat_surf = mask->surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    status = _cairo_surface_get_extents (pat_surf, &extents);
+    if (status)
+	return status;
+
+    quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
+
+    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+    if (!img) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL;
+    }
+
+    rect = CGRectMake (-mask->base.matrix.x0, -mask->base.matrix.y0, extents.width, extents.height);
+    CGContextSaveGState (surface->cgContext);
+    CGContextClipToMask (surface->cgContext, rect, img);
+    status = _cairo_quartz_surface_paint (surface, op, source);
+
+    CGContextRestoreGState (surface->cgContext);
+    CGImageRelease (img);
+  BAIL:
+    cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
+    return status;
+}
+
 static cairo_int_status_t
 _cairo_quartz_surface_mask (void *abstract_surface,
 			     cairo_operator_t op,
@@ -1504,6 +1543,10 @@ _cairo_quartz_surface_mask (void *abstract_surface,
 	cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
 
 	CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha);
+    } else if (CGContextClipToMask &&
+               mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	       mask->extend == CAIRO_EXTEND_NONE) {
+	return _cairo_quartz_surface_mask_with_surface (surface, op, source, (cairo_surface_pattern_t *) mask);
     } else {
 	/* So, CGContextClipToMask is not present in 10.3.9, so we're
 	 * doomed; if we have imageData, we can do fallback, otherwise
commit b36a5a9c9002a3d085acb307d556dc04773bdac4
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Jun 24 23:53:47 2007 +0100

    fix dash-zero-length test
    
    Quartz was failing the dash-zero-length test for odd numbers
    of dashes; it seems cairo wants 3 dashes to be on-off-on,
    off-on-off, wheras quartz uses on-off-on, on-off-on. Fixed
    by doubling the number of dashes used.
    (cherry picked from commit b9c065df74027b06e15e105fee5e4a4d350e0abf)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 40bdfdd..889e8e2 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1284,15 +1284,21 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
 #define STATIC_DASH 32
 	float sdash[STATIC_DASH];
 	float *fdash = sdash;
+	unsigned int max_dashes = style->num_dashes;
 	unsigned int k;
-	if (style->num_dashes > STATIC_DASH)
+
+	if (style->num_dashes%2)
+	    max_dashes *= 2;
+	if (max_dashes > STATIC_DASH)
 	    fdash = _cairo_malloc_ab (style->num_dashes, sizeof (float));
 
-	for (k = 0; k < style->num_dashes; k++)
-	    fdash[k] = (float) style->dash[k];
-	
-	CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, style->num_dashes);
+	if (max_dashes > STATIC_DASH)
+	    fdash = malloc (sizeof(float)*max_dashes);
 
+	for (k = 0; k < max_dashes; k++)
+	    fdash[k] = (float) style->dash[k % style->num_dashes];
+	
+	CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, max_dashes);
 	if (fdash != sdash)
 	    free (fdash);
     }
commit c3b6cb6f493701fe6f9962913371b633d2b10be2
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Jun 24 01:17:58 2007 +0100

    Implement EXTEND_NONE for gradients.
    
    Fixes linear and radial gradients, which were displaying with
    extend_pad when extend_none was requested. Makes the
    radial-gradient test pass.
    (cherry picked from commit f334ee0397963e12c9efcb2690792aac83734661)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 42dd595..40bdfdd 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -373,6 +373,7 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 	CGPoint start, end;
 	CGFunctionRef gradFunc;
 	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+	bool extend = abspat->extend == CAIRO_EXTEND_PAD;
 
 	start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
 			     _cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
@@ -384,7 +385,7 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 	shading = CGShadingCreateAxial (rgb,
 					start, end,
 					gradFunc,
-					true, true);
+					extend, extend);
 	CGColorSpaceRelease(rgb);
 	CGFunctionRelease(gradFunc);
 
@@ -397,6 +398,7 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 	CGPoint start, end;
 	CGFunctionRef gradFunc;
 	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+	bool extend = abspat->extend == CAIRO_EXTEND_PAD;
 
 	start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c1.x) - x0,
 			     _cairo_fixed_to_double (rpat->gradient.c1.y) - y0);
@@ -411,7 +413,7 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
 					 end,
 					 _cairo_fixed_to_double (rpat->gradient.c2.radius),
 					 gradFunc,
-					 true, true);
+					 extend, extend);
 	CGColorSpaceRelease(rgb);
 	CGFunctionRelease(gradFunc);
 
commit 553f82f194d4f321615bfb07a9542efa4ed84b9e
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Jun 23 23:36:32 2007 +0100

    call _cairo_error on failure
    
    Call _cairo_error to enable setting a breakpoint on quartz errors.
    (cherry picked from commit 0eeec372c0e7849d81bde8c8c5bf491919f51a6e)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index dc65e6d..42dd595 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -485,6 +485,7 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
     if (!img) {
 	// ... give up.
 	ND((stderr, "CGBitmapContextCreateImage failed\n"));
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
 	return;
     }
commit 2f99c7e46a4dd52ea6b8d30761061bf37a940ebe
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Jun 23 12:34:24 2007 +0100

    do not return a cairo_status_t of UNSUPPORTED
    
    We had a bug which converted cairo_int_status_t to cairo_status_t,
    causing an assertion; reported at http://developer.imendio.com/node/128.
    Return the generic out of memory error instead.
    (cherry picked from commit 8c8ec63903f8ad67a88394eff1359607bb93cf88)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 5b57d28..dc65e6d 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -899,13 +899,18 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface,
 					     cairo_image_surface_t **image_out,
 					     void **image_extra)
 {
+    cairo_int_status_t status;
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
 
     //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface));
 
     *image_extra = NULL;
 
-    return _cairo_quartz_get_image (surface, image_out, NULL);
+    status = _cairo_quartz_get_image (surface, image_out, NULL);
+    if (status)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -934,7 +939,7 @@ _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
 
     status = _cairo_quartz_get_image (surface, image_out, &data);
     if (status)
-	return status;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     *image_extra = data;
 
commit df69925e2b40978100009e3369496cc5dc8c61ab
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Jun 18 00:07:33 2007 +0100

    do not ignore errors, return NULL instead (moz#874315)
    
    In the quartz backend there are occasional errors where returning NULL
    can be used to signal that an error has occured.
    
    Mozilla bug #874315.
    (cherry picked from commit 6fec51990e90901ebafbb872a9e618cb70d17911)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 48e57d5..5b57d28 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -437,17 +437,23 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_s
 	cairo_surface_t *ref_type = target;
 	cairo_surface_t *new_surf = NULL;
 	cairo_rectangle_int16_t rect;
+	cairo_status_t status;
+
 	if (ref_type == NULL)
 	    ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
 
-	_cairo_surface_get_extents (pat_surf, &rect);
+	status = _cairo_surface_get_extents (pat_surf, &rect);
+	if (status)
+	    return NULL;
 
-	_cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
+	status = _cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
 				      rect.width, rect.height, &new_surf);
-
 	if (target == NULL)
 	    cairo_surface_destroy(ref_type);
 
+        if (status)
+	    return NULL;
+
 	quartz_surf = (cairo_quartz_surface_t *) new_surf;
     } else {
 	/* If it's a quartz surface, we can try to see if it's a CGBitmapContext;
@@ -455,7 +461,6 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_s
 	 */
 	cairo_surface_reference (pat_surf);
 	quartz_surf = (cairo_quartz_surface_t*) pat_surf;
-
     }
 
     return quartz_surf;
@@ -468,10 +473,15 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
     cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
     cairo_surface_t *pat_surf = spat->surface;
 
-    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
-    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+    cairo_quartz_surface_t *quartz_surf;
+    CGImageRef img;
     CGRect imageBounds;
 
+    quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
+    if (!quartz_surf)
+	return;
+
+    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
     if (!img) {
 	// ... give up.
 	ND((stderr, "CGBitmapContextCreateImage failed\n"));
@@ -554,6 +564,7 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
 			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
     CGPatternRef cgpat;
     float rw, rh;
+    cairo_status_t status;
 
     cairo_pattern_union_t *snap_pattern = NULL;
     cairo_pattern_t *target_pattern = abspat;
@@ -566,7 +577,10 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     spat = (cairo_surface_pattern_t *) abspat;
     pat_surf = spat->surface;
 
-    _cairo_surface_get_extents (pat_surf, &extents);
+    status = _cairo_surface_get_extents (pat_surf, &extents);
+    if (status)
+	return NULL;
+
     pbounds.origin.x = 0;
     pbounds.origin.y = 0;
 
@@ -672,12 +686,17 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
     {
 	    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
 	    cairo_surface_t *pat_surf = spat->surface;
-	    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf);
-	    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+	    cairo_quartz_surface_t *quartz_surf;
+	    CGImageRef img;
 	    cairo_matrix_t m = spat->base.matrix;
 	    cairo_rectangle_int16_t extents;
 	    cairo_status_t status;
 
+	    quartz_surf = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf);
+	    if (!quartz_surf)
+		return DO_UNSUPPORTED;
+
+	    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
 	    if (!img)
 		return DO_UNSUPPORTED;
 
commit f236fb41df46df7e11738f88d72296696bb5a517
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Jun 18 00:07:33 2007 +0100

    do not ignore errors in setup_source
    
    In setup_source we were ignoring a return value, but we can't relay
    it to the caller. This patch treats the error as an unsupported
    operation.
    (cherry picked from commit 07fd091e3e6b925c588b9a16f6f10efcd46615c2)

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index b63b139..48e57d5 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -676,6 +676,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
 	    cairo_matrix_t m = spat->base.matrix;
 	    cairo_rectangle_int16_t extents;
+	    cairo_status_t status;
 
 	    if (!img)
 		return DO_UNSUPPORTED;
@@ -685,7 +686,10 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	    cairo_matrix_invert(&m);
 	    _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform);
 
-	    _cairo_surface_get_extents (pat_surf, &extents);
+	    status = _cairo_surface_get_extents (pat_surf, &extents);
+	    if (status)
+		return DO_UNSUPPORTED;
+
 	    surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
 
 	    surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
commit 3a79043f8631c6ec1ea343dbf77f4184fa4cf8dd
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Tue Jun 19 21:13:39 2007 +0100

    do not ignore errors when creating styles.
    
    This fixes statuses being ignored when calling
    CreateSizedCopyOfStyle. As a side effect, it cleans up
    two other bugs - the font object was sometimes not
    freed, and a the scaled font mutex was aquired recursively,
    causing a hang in the invalid-matrix test.
    (cherry picked from commit b6b9cef7136453f97543173bcb2ade46b1c46b77)

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 004b0bf..68bcae4 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -175,30 +175,35 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
     return &font_face->base;
 }
 
-static ATSUStyle
+static OSStatus
 CreateSizedCopyOfStyle(ATSUStyle inStyle, 
 		       const Fixed *theSize, 
-		       const CGAffineTransform *theTransform)
+                      const CGAffineTransform *theTransform,
+                      ATSUStyle *style)
 {
-    ATSUStyle style;
     OSStatus err;
     const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, 
-						  kATSUFontMatrixTag };
+                                                 kATSUFontMatrixTag };
     const ByteCount theFontStyleSizes[] = { sizeof(Fixed), 
-					    sizeof(CGAffineTransform) };
+                                           sizeof(CGAffineTransform) };
     ATSUAttributeValuePtr theFontStyleValues[] = { (Fixed *)theSize, 
-						   (CGAffineTransform *)theTransform };
+                                                  (CGAffineTransform *)theTransform };
 
-    err = ATSUCreateAndCopyStyle(inStyle, &style);
+    err = ATSUCreateAndCopyStyle (inStyle, style);
+    if (err != noErr)
+	return err;
 
-    err = ATSUSetAttributes(style,
+    err = ATSUSetAttributes(*style,
                             sizeof(theFontStyleTags) /
                             sizeof(ATSUAttributeTag), theFontStyleTags,
                             theFontStyleSizes, theFontStyleValues);
+    if (err != noErr)
+	ATSUDisposeStyle (*style);
 
-    return style;
+    return err;
 }
 
+
 static cairo_status_t
 _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
 {
@@ -265,7 +270,12 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
 					       0., 0.);
     font->size = FloatToFixed (xscale);
 
-    font->style = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix);
+    err = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix, &font->style);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto FAIL;
+    }
 
     {
 	Fixed theSize = FloatToFixed(1.0);
@@ -292,7 +302,12 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
 
   FAIL:
     if (status) {
-	cairo_scaled_font_destroy (&font->base);
+	if (font) {
+	    if (font->style)
+		ATSUDisposeStyle(font->style);
+	    free (font);
+	}
+
 	return status;
     }
 
commit 63e0bc28584c7d661a3a6f7e91630b39792b6de0
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Jun 18 00:07:33 2007 +0100

    do not ignore ATSUI errors.
    
    This fixes multiple instances where the return value of an ATSUI
    call was ignored and converts them into CAIRO_STATUS_NO_MEMORY.
    As a side effect it fixes a utf8 array not being freed.
    (cherry picked from commit 4885a12c6863321a566e7103bf6dccdd5d13a986)

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 6df7d87..004b0bf 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -111,6 +111,7 @@ _cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
 					   const cairo_font_options_t *options,
 					   cairo_scaled_font_t **font)
 {
+    cairo_status_t status;
     cairo_atsui_font_face_t *font_face = abstract_face;
     OSStatus err;
     ATSUAttributeTag styleTags[] = { kATSUFontTag };
@@ -119,11 +120,22 @@ _cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
     ATSUStyle style;
 
     err = ATSUCreateStyle (&style);
+    if (err != noErr)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
     err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
                             styleTags, styleSizes, styleValues);
+    if (err != noErr) {
+        ATSUDisposeStyle (style);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-    return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
+    status = _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
 					    font_matrix, ctm, options, font);
+    if (status)
+        ATSUDisposeStyle (style);
+
+    return status;
 }
 
 static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
@@ -294,6 +306,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 			     const cairo_font_options_t *options,
 			     cairo_scaled_font_t **font_out)
 {
+    cairo_status_t status;
     ATSUStyle style;
     ATSUFontID fontID;
     OSStatus err;
@@ -302,6 +315,9 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
     const char *full_name;
 
     err = ATSUCreateStyle(&style);
+    if (err != noErr) {
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     switch (toy_face->weight) {
     case CAIRO_FONT_WEIGHT_BOLD:
@@ -375,6 +391,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 				       kFontNoPlatformCode,
 				       kFontRomanScript,
 				       kFontNoLanguageCode, &fontID);
+	    if (err != noErr) {
+		ATSUDisposeStyle (style);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
 	}
     }
 
@@ -387,10 +407,18 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 
 	err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
 				styleTags, styleSizes, styleValues);
+	if (err != noErr) {
+	    ATSUDisposeStyle (style);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
     }
 
-    return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
+    status = _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
 					    font_matrix, ctm, options, font_out);
+    if (status)
+	ATSUDisposeStyle (style);
+
+    return status;
 }
 
 static void
@@ -601,6 +629,10 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
 				 lineProc,
 				 curveProc,
 				 closePathProc, (void *)&scaled_path, &err);
+    if (err != noErr) {
+	_cairo_path_fixed_destroy (scaled_path.path);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
 				  scaled_path.path);
@@ -664,6 +696,10 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
     err = ATSUGlyphGetScreenMetrics (scaled_font->style,
 				     1, &theGlyph, 0, false,
 				     false, &metricsH);    
+    if (err != noErr) {
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
     left = metricsH.sideBearing.x - 1.0;
     width = metricsH.deviceAdvance.x 
 	- metricsH.sideBearing.x 
@@ -809,27 +845,44 @@ _cairo_atsui_font_text_to_glyphs (void		*abstract_font,
 
     status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
     if (status)
-	return status;
+	goto BAIL3;
 
     err = ATSUCreateTextLayout(&textLayout);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL3;
+    }
 
     err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     /* Set the style for all of the text */
     err = ATSUSetRunStyle(textLayout,
 			  font->style, kATSUFromTextBeginning, kATSUToTextEnd);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
 							0,
 							kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 							(void *)&layoutRecords,
 							&glyphCount);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     *num_glyphs = glyphCount - 1;
     *glyphs =
 	(cairo_glyph_t *) _cairo_malloc_ab(*num_glyphs, sizeof (cairo_glyph_t));
     if (*glyphs == NULL) {
-	return CAIRO_STATUS_NO_MEMORY;
+	status = CAIRO_STATUS_NO_MEMORY);
+	goto BAIL1;
     }
 
     _cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1);
@@ -847,14 +900,17 @@ _cairo_atsui_font_text_to_glyphs (void		*abstract_font,
 	(*glyphs)[i].y = y;
     }
 
-    free (utf16);
-
+  BAIL1:
+    /* TODO ignored return value. Is there anything we should do? */
     ATSUDirectReleaseLayoutDataArrayPtr(NULL,
 					kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 					(void *) &layoutRecords);
+  BAIL2:
     ATSUDisposeTextLayout(textLayout);
+  BAIL3:
+    free (utf16);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 ATSUStyle
commit b0b35d55dd1707744ff017e8a6d9c56f238120e8
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Jun 18 00:07:33 2007 +0100

    do not ignore errors in glyph paths
    
    When interpreting glyph paths in ATSUI callbacks we were ignoring
    the cairo status. We need to return this to the caller. In order
    to do this we introduce a custom OSStatus code in the range that
    Apple reccommend.
    (cherry picked from commit b498c928be73635614596243d17a922e9d5ff008)

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index d1196f0..6df7d87 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -63,6 +63,9 @@
 /* Public in 10.4, present in 10.3.9 */
 CG_EXTERN CGRect CGRectApplyAffineTransform (CGRect, CGAffineTransform);
 
+/* Error code for path callbacks */
+static OSStatus CAIRO_CG_PATH_ERROR = 1001;
+
 typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
 typedef struct _cairo_atsui_font cairo_atsui_font_t;
 typedef struct _cairo_atsui_scaled_path cairo_atsui_scaled_path_t;
@@ -462,16 +465,22 @@ static OSStatus
 _move_to (const Float32Point *point,
 	  void *callback_data)
 {
+    cairo_status_t status;
     cairo_atsui_scaled_path_t *scaled_path = callback_data;
     double x = point->x;
     double y = point->y;
     
     cairo_matrix_transform_point (scaled_path->scale, &x, &y);
-    _cairo_path_fixed_close_path (scaled_path->path);
-    _cairo_path_fixed_move_to (scaled_path->path,
+    status = _cairo_path_fixed_close_path (scaled_path->path);
+    if (status)
+	return CAIRO_CG_PATH_ERROR;
+
+    status = _cairo_path_fixed_move_to (scaled_path->path,
 			       _cairo_fixed_from_double (x),
 			       _cairo_fixed_from_double (y));
-
+    if (status)
+	return CAIRO_CG_PATH_ERROR;
+    
     return noErr;
 }
 
@@ -479,15 +488,18 @@ static OSStatus
 _line_to (const Float32Point *point,
 	  void *callback_data)
 {
+    cairo_status_t status;
     cairo_atsui_scaled_path_t *scaled_path = callback_data;
     double x = point->x;
     double y = point->y;
     
     cairo_matrix_transform_point (scaled_path->scale, &x, &y);
 
-    _cairo_path_fixed_line_to (scaled_path->path,
+    status = _cairo_path_fixed_line_to (scaled_path->path,
 			       _cairo_fixed_from_double (x),
 			       _cairo_fixed_from_double (y));
+    if (status)
+	return CAIRO_CG_PATH_ERROR;
 
     return noErr;
 }
@@ -498,6 +510,7 @@ _curve_to (const Float32Point *point1,
 	   const Float32Point *point3,
 	   void *callback_data)
 {
+    cairo_status_t status;
     cairo_atsui_scaled_path_t *scaled_path = callback_data;
     double x1 = point1->x;
     double y1 = point1->y;
@@ -510,13 +523,15 @@ _curve_to (const Float32Point *point1,
     cairo_matrix_transform_point (scaled_path->scale, &x2, &y2);
     cairo_matrix_transform_point (scaled_path->scale, &x3, &y3);
 
-    _cairo_path_fixed_curve_to (scaled_path->path,
+    status = _cairo_path_fixed_curve_to (scaled_path->path,
 				_cairo_fixed_from_double (x1),
 				_cairo_fixed_from_double (y1),
 				_cairo_fixed_from_double (x2),
 				_cairo_fixed_from_double (y2),
 				_cairo_fixed_from_double (x3),
 				_cairo_fixed_from_double (y3));
+    if (status)
+	return CAIRO_CG_PATH_ERROR;
 
     return noErr;
 }
@@ -525,9 +540,12 @@ static OSStatus
 _close_path (void *callback_data)
 
 {
+    cairo_status_t status;
     cairo_atsui_scaled_path_t *scaled_path = callback_data;
 
-    _cairo_path_fixed_close_path (scaled_path->path);
+    status = _cairo_path_fixed_close_path (scaled_path->path);
+    if (status)
+	return CAIRO_CG_PATH_ERROR;
 
     return noErr;
 }
commit c4d4ceb1c38b6985957d6532f2696bb9d32402ee
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 19 22:45:15 2007 +0100

    [cairo-xlib] Check source for XRender support.
    
    Do not rely on the assumption that if the destination has render support
    then the source has it as well - breaks when the boilerplate disables
    render support for a surface.
    
    Similarly do not set the XRender attributes on the source surface
    unless it actually has a xrender_format.
    (cherry picked from commit 3211d810d31a6607c8d78a50f577a8ca8eb705e6)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 399417c..05d4dca 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1263,10 +1263,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t	      *dst,
 	return DO_XCOPYAREA;
     }
 
-    if (!dst->buggy_repeat)
-	return DO_RENDER;
-
-    if (is_integer_translation &&
+    if (dst->buggy_repeat &&
+	is_integer_translation &&
 	src_attr->extend == CAIRO_EXTEND_REPEAT &&
 	(src->width != 1 || src->height != 1))
     {
@@ -1280,6 +1278,9 @@ _recategorize_composite_operation (cairo_xlib_surface_t	      *dst,
 	return DO_UNSUPPORTED;
     }
 
+    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
+	return DO_UNSUPPORTED;
+
     return DO_RENDER;
 }
 
@@ -1384,13 +1385,13 @@ _cairo_xlib_surface_composite (cairo_operator_t		op,
 	goto BAIL;
     }
 
-    status = _cairo_xlib_surface_set_attributes (src, &src_attr);
-    if (status)
-	goto BAIL;
-
     switch (operation)
     {
     case DO_RENDER:
+	status = _cairo_xlib_surface_set_attributes (src, &src_attr);
+	if (status)
+	    goto BAIL;
+
 	_cairo_xlib_surface_ensure_dst_picture (dst);
 	if (mask) {
 	    status = _cairo_xlib_surface_set_attributes (mask, &mask_attr);
commit 17d9f4f6d1d773622711f2ccc534dde32d9469c6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Oct 19 15:02:03 2007 -0400

    [cairo-xlib] Release glyph surfaces if we made them to be generated
    
    The reasoning is that right now, applications render glyphs to images,
    upload it to the X server, and keep a local copy in the cache.  The X
    server works hard to reuse glyph renderings, by hashing glyph images and
    reusing them.  So we are wasting memory in cairo apps that don't use the
    glyph surface after uploading to the server, which is the case if you
    don't use the glyph in an image surface.  The patch does not release the
    glyph surface if it already existed in the cache, so, worst case
    scenario is that we render the glyph twice, if you first use it with
    xlib, then with image surface.  That effect should be negligible.
    (cherry picked from commit 76e3b3cdc3dda986d420637cfc2445aca481a863)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 4fe62ed..399417c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2557,15 +2557,34 @@ _native_byte_order_lsb (void)
 
 static cairo_status_t
 _cairo_xlib_surface_add_glyph (Display *dpy,
-			       cairo_scaled_font_t  *scaled_font,
-			       cairo_scaled_glyph_t *scaled_glyph)
+			       cairo_scaled_font_t   *scaled_font,
+			       cairo_scaled_glyph_t **pscaled_glyph)
 {
     XGlyphInfo glyph_info;
     unsigned long glyph_index;
     unsigned char *data;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xlib_surface_font_private_t *font_private;
+    cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph;
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
+    cairo_bool_t already_had_glyph_surface;
+
+    if (!glyph_surface) {
+
+	status = _cairo_scaled_glyph_lookup (scaled_font,
+					     _cairo_scaled_glyph_index (scaled_glyph),
+					     CAIRO_SCALED_GLYPH_INFO_METRICS |
+					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
+					     pscaled_glyph);
+	if (status != CAIRO_STATUS_SUCCESS)
+	    return status;
+
+	scaled_glyph = *pscaled_glyph;
+	glyph_surface = scaled_glyph->surface;
+	already_had_glyph_surface = FALSE;
+    } else {
+	already_had_glyph_surface = TRUE;
+    }
 
     if (scaled_font->surface_private == NULL) {
 	status = _cairo_xlib_surface_font_init (dpy, scaled_font,
@@ -2575,6 +2594,31 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     }
     font_private = scaled_font->surface_private;
 
+    /* If the glyph surface has zero height or width, we create
+     * a clear 1x1 surface, to avoid various X server bugs.
+     */
+    if ((glyph_surface->width == 0) || (glyph_surface->height == 0)) {
+	cairo_t *cr;
+	cairo_surface_t *tmp_surface;
+
+	tmp_surface = cairo_image_surface_create (font_private->format, 1, 1);
+	cr = cairo_create (tmp_surface);
+	cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+	cairo_paint (cr);
+
+	status = cairo_status (cr);
+
+	cairo_destroy (cr);
+
+	tmp_surface->device_transform = glyph_surface->base.device_transform;
+	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
+
+	glyph_surface = (cairo_image_surface_t *) tmp_surface;
+
+	if (status)
+	    goto BAIL;
+    }
+
     /* If the glyph format does not match the font format, then we
      * create a temporary surface for the glyph image with the font's
      * format.
@@ -2582,14 +2626,16 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     if (glyph_surface->format != font_private->format) {
 	cairo_t *cr;
 	cairo_surface_t *tmp_surface;
-	double x_offset, y_offset;
 
 	tmp_surface = cairo_image_surface_create (font_private->format,
 						  glyph_surface->width,
 						  glyph_surface->height);
+	tmp_surface->device_transform = glyph_surface->base.device_transform;
+	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
+
 	cr = cairo_create (tmp_surface);
-	cairo_surface_get_device_offset (&glyph_surface->base, &x_offset, &y_offset);
-	cairo_set_source_surface (cr, &glyph_surface->base, x_offset, y_offset);
+
+	cairo_set_source_surface (cr, &glyph_surface->base, 0, 0);
 	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 	cairo_paint (cr);
 
@@ -2597,9 +2643,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 
 	cairo_destroy (cr);
 
-	tmp_surface->device_transform = glyph_surface->base.device_transform;
-	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
-
 	glyph_surface = (cairo_image_surface_t *) tmp_surface;
 
 	if (status)
@@ -2728,6 +2771,15 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     if (glyph_surface != scaled_glyph->surface)
 	cairo_surface_destroy (&glyph_surface->base);
 
+    /* if the scaled glyph didn't already have a surface attached
+     * to it, release the created surface now that we have it
+     * uploaded to the X server.  If the surface has already been
+     * there (eg. because image backend requested it), leave it in
+     * the cache
+     */
+    if (!already_had_glyph_surface)
+	_cairo_scaled_glyph_set_surface (scaled_glyph, scaled_font, NULL);
+
     return status;
 }
 
@@ -2913,7 +2965,6 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 
 	status = _cairo_scaled_glyph_lookup (scaled_font,
 					     glyphs[i].index,
-					     CAIRO_SCALED_GLYPH_INFO_SURFACE |
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
 					     &scaled_glyph);
 	if (status != CAIRO_STATUS_SUCCESS)
@@ -2924,14 +2975,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 
 	/* Glyph skipping:
 	 *
-	 * We skip any initial size-zero glyphs to avoid an X server bug (present
-	 * in at least Xorg 7.1 without EXA) which stops rendering glyphs after
-	 * the first zero-size glyph.  However, we don't skip all size-zero
-	 * glyphs, since that will force a new element at every space.  We
-	 * skip initial size-zero glyphs and hope that it's enough.  Since
-	 * Xft never exposed that bug, this assumption should be correct.
-	 *
-	 * We also skip any glyphs that have troublesome coordinates.  We want
+	 * We skip any glyphs that have troublesome coordinates.  We want
 	 * to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
 	 * a signed 16bit integer, otherwise it will overflow in the render
 	 * protocol.
@@ -2945,8 +2989,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	 * Anyway, we will allow positions in the range -1024..15359.  That
 	 * will buy us a few more years before this stops working.
 	 */
-	if ((!num_out_glyphs && !(scaled_glyph->surface->width && scaled_glyph->surface->height)) ||
-	    (((this_x+1024)|(this_y+1024))&~0x3fffu)) {
+	if (((this_x+1024)|(this_y+1024))&~0x3fffu) {
 	    glyphs[i].index = GLYPH_INDEX_SKIP;
 	    continue;
 	}
@@ -3002,7 +3045,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	if (scaled_glyph->surface_private == NULL) {
 	    status = _cairo_xlib_surface_add_glyph (dst->dpy,
 		                                    scaled_font,
-						    scaled_glyph);
+						    &scaled_glyph);
 	    if (status)
 		return status;
 	    scaled_glyph->surface_private = (void *) 1;
commit fcd180259f1bcd8a7c665c38d46e28af4cb8b190
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 18 20:07:12 2007 +0100

    [cairo-xlib-surface] Match content to xrender_format using the channel masks.
    
    _xrender_format_to_content() was using the channel offset to determine
    whether the format supported a content type.
    For example, the XRenderPictFormat for the A8 format looks like:
        direct.alpha = 0; direct.alphaMask = 0xff;
        direct.red   = 0; direct.redMask   = 0x00;
        direct.green = 0; direct.greenMask = 0x00;
        direct.blue  = 0; direct.blueMask  = 0x00;
    which _xrender_format_to_content() matched as CAIRO_CONTENT_COLOR.
    
    Switch to using the channel masks for deducing content type.
    (cherry picked from commit 8ae778273799ee9f6d3c13e9c41730daeda2c743)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 3e77165..4fe62ed 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -195,10 +195,10 @@ _xrender_format_to_content (XRenderPictFormat *xrender_format)
     if (xrender_format == NULL)
 	return CAIRO_CONTENT_COLOR;
 
-    xrender_format_has_alpha = (xrender_format->direct.alpha != 0);
-    xrender_format_has_color = (xrender_format->direct.red   != 0 ||
-				xrender_format->direct.green != 0 ||
-				xrender_format->direct.blue  != 0);
+    xrender_format_has_alpha = (xrender_format->direct.alphaMask != 0);
+    xrender_format_has_color = (xrender_format->direct.redMask   != 0 ||
+				xrender_format->direct.greenMask != 0 ||
+				xrender_format->direct.blueMask  != 0);
 
     if (xrender_format_has_alpha)
 	if (xrender_format_has_color)
commit a6d120360d70199cf676ec019db03d9b85de8a64
Author: Chris Heath <chris at heathens.co.nz>
Date:   Mon Oct 15 17:31:50 2007 -0400

    [autogen.sh] Tolerate tput failure (#12757)
    (cherry picked from commit 189feaf352f59b0a049202552024578715ef8cc7)

diff --git a/autogen.sh b/autogen.sh
index 73455ef..4253a91 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -49,8 +49,8 @@ esac
 
 
 # some terminal codes ...
-boldface="`tput bold 2>/dev/null`"
-normal="`tput sgr0 2>/dev/null`"
+boldface="`tput bold 2>/dev/null || true`"
+normal="`tput sgr0 2>/dev/null || true`"
 printbold() {
     echo $ECHO_N "$boldface"
     echo "$@"
commit 95b5c7a5735f64ff6ead73f34fb8f66156152e92
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Oct 2 10:54:44 2007 -0700

    [win32] return a nil surface, not NULL
    
    Missed an error return
    (cherry picked from commit c99d33b10e84883ade1402c3c1d1efdb4b46f66e)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 5c9d7d8..f1a8703 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1762,7 +1762,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
     HBITMAP saved_dc_bitmap;
 
     if (format != CAIRO_FORMAT_RGB24)
-	return NULL;
+	return NIL_SURFACE;
 /* XXX handle these eventually
 	format != CAIRO_FORMAT_A8 ||
 	format != CAIRO_FORMAT_A1)
commit c594864c7ec76ad8044fa694ed8a36ee3562dcd1
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Oct 2 10:48:59 2007 -0700

    [win32] report error correctly if CreateCompatibleBitmap fails
    
    These errors were being dropped on the floor, leading to
    rendering errors in out of video memory conditions.
    (cherry picked from commit 4dbf495515d6de933de7f567b935c5fdceed5f6f)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index ed5e352..5c9d7d8 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1775,8 +1775,25 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
 	screen_dc = NULL;
     }
 
-    ddb = CreateCompatibleBitmap (hdc, width, height);
     ddb_dc = CreateCompatibleDC (hdc);
+    if (ddb_dc == NULL) {
+	_cairo_win32_print_gdi_error("CreateCompatibleDC");
+	new_surf = NIL_SURFACE;
+	goto FINISH;
+    }
+
+    ddb = CreateCompatibleBitmap (hdc, width, height);
+    if (ddb == NULL) {
+	DeleteDC (ddb_dc);
+
+	/* Note that if an app actually does hit this out of memory
+	 * condition, it's going to have lots of other issues, as
+	 * video memory is probably exhausted.
+	 */
+	_cairo_win32_print_gdi_error("CreateCompatibleBitmap");
+	new_surf = NIL_SURFACE;
+	goto FINISH;
+    }
 
     saved_dc_bitmap = SelectObject (ddb_dc, ddb);
 
@@ -1789,6 +1806,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
     new_surf->saved_dc_bitmap = saved_dc_bitmap;
     new_surf->is_dib = FALSE;
 
+FINISH:
     if (screen_dc)
 	ReleaseDC (NULL, screen_dc);
 
commit 92121b446aca37f3ca7b5ccab257ffb77368fd0b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 15:54:58 2007 -0400

    [ChangeLog.mk] Fix changelog generation rules
    
    Previously it was trying to get logs of 1.2.0..1.4 while I really meant
    was 1.2.0..1.4.0.  It was a simple typo.
    (cherry picked from commit b12ed375cf7ad02a30324616e121a1e9ab8998cb)

diff --git a/ChangeLog.mk b/ChangeLog.mk
index 1566824..1158fb2 100644
--- a/ChangeLog.mk
+++ b/ChangeLog.mk
@@ -66,7 +66,7 @@ $(srcdir)/ChangeLog.cache-% $(srcdir)/ChangeLog.pre-%:
 		to=$$version; \
 		test "x$$version" = x && version=$(CURR_CHANGELOG_VERSION); \
 		from=$(PREV_CHANGELOG_VERSION); \
-		test "x$$to" = x || version=$$version.0; \
+		test "x$$to" = x || to=$$to.0; \
 		test "x$$from" = xinitial || from=$$from.0; \
 		spec=$$from..$$to; \
 	  fi; \
commit a1dc1516d863b60efce363b24e52f9cd9e239b4a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 16:04:49 2007 +0100

    [cairo-scaled-font] Acquire mutex around _cairo_scaled_font_glyph_path().
    
    All calls that manipulate the scaled_font->cache must hold its mutex.
    (cherry picked from commit 6e93941a7605a3958269de195dc16f255dda7bfd)

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 901fa58..21a6395 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1622,9 +1622,11 @@ _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs);
 
+    CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
 					    path);
+    CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
     if (transformed_glyphs != stack_transformed_glyphs)
       free (transformed_glyphs);
commit c90519378a20da197aaf7d88d88801b5fedb17eb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 4 09:08:46 2007 +0100

    [cairo-path] Check for an empty path in cairo_append_path().
    
    As we now generate empty paths, we must be able to handle empty paths
    in the user facing API. cairo_append_path() has an explicit check, and
    raises an error, for a NULL path->data, so we need to check the
    path->num_data first for empty paths.
    (cherry picked from commit ef5f460eb1f86a73e016c1150723ae1e70b3b037)

diff --git a/src/cairo.c b/src/cairo.c
index 6859e45..c6ea8c5 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -3405,6 +3405,9 @@ cairo_append_path (cairo_t		*cr,
 	return;
     }
 
+    if (path->num_data == 0)
+	return;
+
     if (path->data == NULL) {
 	_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
 	return;
diff --git a/test/copy-path.c b/test/copy-path.c
index 256f461..362bb34 100644
--- a/test/copy-path.c
+++ b/test/copy-path.c
@@ -141,7 +141,13 @@ draw (cairo_t *cr, int width, int height)
 	cairo_path_destroy (path);
 	return CAIRO_TEST_FAILURE;
     }
+    cairo_append_path (cr, path);
     cairo_path_destroy (path);
+    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
+	cairo_test_log ("Error: cairo_append_path failed with a copy of an empty path, returned status of %s\n",
+			cairo_status_to_string (cairo_status (cr)));
+	return CAIRO_TEST_FAILURE;
+    }
 
     /* We draw in the default black, so paint white first. */
     cairo_save (cr);
@@ -224,6 +230,15 @@ main (void)
     path.num_data = 0;
     path.status = CAIRO_STATUS_SUCCESS;
     cairo_append_path (cr, &path);
+    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+	return 1;
+    cairo_destroy (cr);
+
+    cr = cairo_create (surface);
+    path.data = NULL;
+    path.num_data = 1;
+    path.status = CAIRO_STATUS_SUCCESS;
+    cairo_append_path (cr, &path);
     if (cairo_status (cr) != CAIRO_STATUS_NULL_POINTER)
 	return 1;
     cairo_destroy (cr);
commit 721e17cc3a0227f5763bcbc2f6be33e968ea9365
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 3 23:25:10 2007 +0100

    [malloc] Take advantage of calloc() argument checking.
    
    calloc() will check its arguments for integer overflows so it is safer
    not to pre-multiply them.
    (cherry picked from commit 66664596559c55913fb0b9c8784fe8ab862c217b)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index d8bb64a..914dc0b 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -841,7 +841,7 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
 	    width_rgba = width;
 	    stride = bitmap->pitch;
 	    stride_rgba = (width_rgba * 4 + 3) & ~3;
-	    data_rgba = calloc (1, stride_rgba * height);
+	    data_rgba = calloc (stride_rgba, height);
 	    if (data_rgba == NULL) {
 		if (own_buffer)
 		    free (bitmap->buffer);
@@ -1042,7 +1042,7 @@ _render_glyph_outline (FT_Face                    face,
 	bitmap.pitch = stride;
 	bitmap.width = width * hmul;
 	bitmap.rows = height * vmul;
-	bitmap.buffer = calloc (1, stride * bitmap.rows);
+	bitmap.buffer = calloc (stride, bitmap.rows);
 
 	if (bitmap.buffer == NULL) {
 	    _cairo_error (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index de91fc7..15d6025 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -1215,7 +1215,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t  op,
 	int		      stride;
 
 	stride = (width + 3) & -4;
-	data = calloc (stride * height, 1);
+	data = calloc (stride, height);
 	if (!data)
 	{
 	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index ad41a4c..27287fa 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -988,7 +988,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
     }
 
     /* The image must be initially transparent */
-    mask_data = calloc (1, mask_stride * height);
+    mask_data = calloc (mask_stride, height);
     if (mask_data == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto CLEANUP_SOURCE;
commit ddfda4cd77472a346c917382748f88f14b0c983a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 3 23:19:10 2007 +0100

    [malloc] Check for integer overflow when realloc'ing.
    
    Perform similar sanity checks to Vlad's _cairo_malloc_ab() but on the
    arguments to realloc instead.
    (cherry picked from commit e49bcde27f88e21d5b8037a0089a226096f6514b)

diff --git a/src/cairo-array.c b/src/cairo-array.c
index ff8cce4..3525c78 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -138,8 +138,8 @@ _cairo_array_grow_by (cairo_array_t *array, int additional)
     }
 
     array->size = new_size;
-    new_elements = realloc (*array->elements,
-			    array->size * array->element_size);
+    new_elements = _cairo_realloc_ab (*array->elements,
+			              array->size, array->element_size);
 
     if (new_elements == NULL) {
 	array->size = old_size;
diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index 370d258..36a59fd 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -93,7 +93,11 @@ _lzw_buf_grow (lzw_buf_t *buf)
     if (buf->status)
 	return buf->status;
 
-    new_data = realloc (buf->data, new_size);
+    new_data = NULL;
+    /* check for integer overflow */
+    if (new_size / 2 == buf->data_size)
+	new_data = realloc (buf->data, new_size);
+
     if (new_data == NULL) {
 	free (buf->data);
 	buf->data_size = 0;
diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h
index ad22851..f8094f9 100644
--- a/src/cairo-malloc-private.h
+++ b/src/cairo-malloc-private.h
@@ -59,7 +59,7 @@
  * @n: number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@size memory using _cairo_malloc(), taking care to not
+ * Allocates @n*@size memory using _cairo_malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves much like
  * calloc(), except that the returned memory is not set to zero.
  * The memory should be freed using free().
@@ -76,12 +76,34 @@
    _cairo_malloc((unsigned) (a) * (unsigned) (size)))
 
 /**
+ * _cairo_realloc_ab:
+ * @ptr: original pointer to block of memory to be resized
+ * @n: number of elements to allocate
+ * @size: size of each element
+ *
+ * Reallocates @ptr a block of @n*@size memory using realloc(), taking
+ * care to not overflow when doing the multiplication.  The memory
+ * should be freed using free().
+ *
+ * @size should be a constant so that the compiler can optimize
+ * out a constant division.
+ *
+ * Return value: A pointer to the newly allocated memory, or %NULL in
+ * case of realloc() failure or overflow (whereupon the original block
+ * of memory * is left untouched).
+ */
+
+#define _cairo_realloc_ab(ptr, a, size) \
+  ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   realloc(ptr, (unsigned) (a) * (unsigned) (size)))
+
+/**
  * _cairo_malloc_abc:
- * @a: first factor of number of elements to allocate
+ * @n: first factor of number of elements to allocate
  * @b: second factor of number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@b*@size memory using _cairo_malloc(), taking care to not
+ * Allocates @n*@b*@size memory using _cairo_malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
@@ -103,7 +125,7 @@
  * @size: size of each element
  * @k: additional size to allocate
  *
- * Allocates @a*@ksize+ at k memory using _cairo_malloc(), taking care to not
+ * Allocates @n*@ksize+ at k memory using _cairo_malloc(), taking care to not
  * overflow when doing the arithmetic.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index d9f7ed2..6502a94 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1076,7 +1076,8 @@ _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t	*stroker,
 	/* Common case is one rectangle of exactly 4 segments. */
 	if (new_size == 0)
 	    new_size = 4;
-	new_segments = realloc (stroker->segments, new_size * sizeof (cairo_line_t));
+	new_segments = _cairo_realloc_ab (stroker->segments,
+					  new_size, sizeof (cairo_line_t));
 	if (new_segments == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
 	stroker->segments_size = new_size;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index ae62dfc..e8b6dd0 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -763,7 +763,9 @@ _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
 	if (new_stops)
 	    memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t));
     } else {
-	new_stops = realloc (pattern->stops, new_size * sizeof (pixman_gradient_stop_t));
+	new_stops = _cairo_realloc_ab (pattern->stops,
+				       new_size,
+				       sizeof (pixman_gradient_stop_t));
     }
 
     if (new_stops == NULL) {
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 9392322..a181925 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -138,7 +138,8 @@ _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
     int i;
 
     num_vertices = pen->num_vertices + num_points;
-    vertices = realloc (pen->vertices, num_vertices * sizeof (cairo_pen_vertex_t));
+    vertices = _cairo_realloc_ab (pen->vertices,
+				  num_vertices, sizeof (cairo_pen_vertex_t));
     if (vertices == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index 726884a..0aa88bc 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -97,7 +97,8 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
 	if (new_edges)
 	    memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
     } else {
-	new_edges = realloc (polygon->edges, new_size * sizeof (cairo_edge_t));
+	new_edges = _cairo_realloc_ab (polygon->edges,
+				       new_size, sizeof (cairo_edge_t));
     }
 
     if (new_edges == NULL) {
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index db748b3..c4540c5 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -113,7 +113,8 @@ _cairo_spline_grow (cairo_spline_t *spline)
 	if (new_points)
 	    memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
     } else {
-	new_points = realloc (spline->points, new_size * sizeof (cairo_point_t));
+	new_points = _cairo_realloc_ab (spline->points,
+					new_size, sizeof (cairo_point_t));
     }
 
     if (new_points == NULL) {
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 78e65ab..ac8b11d 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -264,7 +264,8 @@ _cairo_traps_grow (cairo_traps_t *traps)
 	if (new_traps)
 	    memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
     } else {
-	new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
+	new_traps = _cairo_realloc_ab (traps->traps,
+				       new_size, sizeof (cairo_trapezoid_t));
     }
 
     if (new_traps == NULL) {
commit 8c26eac21e1259dbd0e50923d296c627449b86b6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Oct 1 17:59:57 2007 +0100

    [cairo-path] Don't raise an error when attempting to create an empty path.
    
    Generate a real empty path structure instead of returning
    _cairo_path_nil, if we have been asked to create an empty path.
    
    (Also add a couple of missing _cairo_error()s and an appropriate test
    case.)
    
    Spotted by Fred Kiefer.
    (cherry picked from commit b4f86638cc4b87bfaf10568ae9beb89626e26613)

diff --git a/src/cairo-path.c b/src/cairo-path.c
index 0740ebc..b1ef44e 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -352,8 +352,10 @@ _cairo_path_create_in_error (cairo_status_t status)
 	return (cairo_path_t*) &_cairo_path_nil;
 
     path = malloc (sizeof (cairo_path_t));
-    if (path == NULL)
+    if (path == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_path_t*) &_cairo_path_nil;
+    }
 
     path->num_data = 0;
     path->data = NULL;
@@ -370,25 +372,34 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
     cairo_path_t *path;
 
     path = malloc (sizeof (cairo_path_t));
-    if (path == NULL)
+    if (path == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_path_t*) &_cairo_path_nil;
+    }
 
     path->num_data = _cairo_path_count (path, path_fixed,
 					_cairo_gstate_get_tolerance (gstate),
 					flatten);
-    if (path->num_data <= 0) {
+    if (path->num_data < 0) {
 	free (path);
 	return (cairo_path_t*) &_cairo_path_nil;
     }
 
-    path->data = _cairo_malloc_ab (path->num_data, sizeof (cairo_path_data_t));
-    if (path->data == NULL) {
-	free (path);
-	return (cairo_path_t*) &_cairo_path_nil;
-    }
+    if (path->num_data) {
+	path->data = _cairo_malloc_ab (path->num_data,
+	       	                       sizeof (cairo_path_data_t));
+	if (path->data == NULL) {
+	    free (path);
+	    _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_path_t*) &_cairo_path_nil;
+	}
 
-    path->status = _cairo_path_populate (path, path_fixed,
-			                 gstate, flatten);
+	path->status = _cairo_path_populate (path, path_fixed,
+					     gstate, flatten);
+    } else {
+	path->data = NULL;
+	path->status = CAIRO_STATUS_SUCCESS;
+    }
 
     return path;
 }
@@ -413,8 +424,9 @@ cairo_path_destroy (cairo_path_t *path)
     if (path == NULL || path == &_cairo_path_nil)
 	return;
 
-    free (path->data);
-    path->num_data = 0;
+    if (path->data)
+	free (path->data);
+
     free (path);
 }
 
diff --git a/test/copy-path.c b/test/copy-path.c
index 142bfa5..256f461 100644
--- a/test/copy-path.c
+++ b/test/copy-path.c
@@ -125,6 +125,23 @@ draw (cairo_t *cr, int width, int height)
     cairo_path_destroy (path);
 
     cairo_destroy (cr_error);
+    
+    /* first check that we can copy an empty path */
+    cairo_new_path (cr);
+    path = cairo_copy_path (cr);
+    if (path->status != CAIRO_STATUS_SUCCESS) {
+	cairo_test_log ("Error: cairo_copy_path returned status of %s\n",
+			cairo_status_to_string (path->status));
+	cairo_path_destroy (path);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (path->num_data != 0) {
+	cairo_test_log ("Error: cairo_copy_path did not copy an empty path, returned path contains %d elements\n",
+		        path->num_data);
+	cairo_path_destroy (path);
+	return CAIRO_TEST_FAILURE;
+    }
+    cairo_path_destroy (path);
 
     /* We draw in the default black, so paint white first. */
     cairo_save (cr);
commit f5be12a0c3896feae16cff293a9af435769e9e0c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Sep 29 07:55:48 2007 +0930

    CFF Subetting: Fix for #10849
    
    This fixes the problem Apple Preview has with viewing PDFs with CFF
    font subsets.
    (cherry picked from commit 042c382c094d1ea6f9a5a162d4d1d9ac83413233)

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 55e0f15..390b149 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1521,8 +1521,8 @@ static const font_write_t font_write_funcs[] = {
     cairo_cff_font_write_top_dict,
     cairo_cff_font_write_strings,
     cairo_cff_font_write_global_subrs,
-    cairo_cff_font_write_fdselect,
     cairo_cff_font_write_charset,
+    cairo_cff_font_write_fdselect,
     cairo_cff_font_write_charstrings,
     cairo_cff_font_write_cid_fontdict,
     cairo_cff_font_write_cid_private_dict_and_local_sub,
commit b1f2efa3bb7b3e2109e9b9b4ec7b89cb7ca8b7f1
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Sep 23 11:37:02 2007 +0930

    Truetype Subsetting: Avoid failing when fonts are missing optional tables
    
    Previously, the TrueType subsetting would fail if any of the "cvt",
    "fpgm", or "prep" tables were missing from the source font. However
    these tables are optional and not required in the subsetted font if
    they do not appear in the source font.
    
    The "name" table has been removed from the subsetted font as the
    Type42 specification does not require this table.
    (cherry picked from commit b20e08999e2f6e7a72ee75a7c3fd865bf0368794)

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 7f168a5..1efa4c8 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -46,10 +46,22 @@ struct subset_glyph {
     unsigned long location;
 };
 
-typedef struct _cairo_truetype_font {
+typedef struct _cairo_truetype_font cairo_truetype_font_t;
+
+typedef struct table table_t;
+struct table {
+    unsigned long tag;
+    cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
+    int pos; /* position in the font directory */
+};
+
+struct _cairo_truetype_font {
 
     cairo_scaled_font_subset_t *scaled_font_subset;
 
+    table_t truetype_tables[10];
+    int num_tables;
+
     struct {
 	char *base_font;
 	unsigned int num_glyphs;
@@ -70,7 +82,7 @@ typedef struct _cairo_truetype_font {
     int *parent_to_subset;
     cairo_status_t status;
 
-} cairo_truetype_font_t;
+};
 
 static int
 cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
@@ -712,35 +724,6 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
     return font->status;
 }
 
-typedef struct table table_t;
-struct table {
-    unsigned long tag;
-    cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
-    int pos; /* position in the font directory */
-};
-
-static const table_t truetype_tables[] = {
-    /* As we write out the glyf table we remap composite glyphs.
-     * Remapping composite glyphs will reference the sub glyphs the
-     * composite glyph is made up of.  That needs to be done first so
-     * we have all the glyphs in the subset before going further.
-     *
-     * The third column in this table is the order in which the
-     * directory entries will appear in the table directory.
-     * The table directory must be sorted in tag order. */
-    { TT_TAG_glyf, cairo_truetype_font_write_glyf_table,     3 },
-    { TT_TAG_cmap, cairo_truetype_font_write_cmap_table,     0 },
-    { TT_TAG_cvt,  cairo_truetype_font_write_generic_table,  1 },
-    { TT_TAG_fpgm, cairo_truetype_font_write_generic_table,  2 },
-    { TT_TAG_head, cairo_truetype_font_write_head_table,     4 },
-    { TT_TAG_hhea, cairo_truetype_font_write_hhea_table,     5 },
-    { TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table,     6 },
-    { TT_TAG_loca, cairo_truetype_font_write_loca_table,     7 },
-    { TT_TAG_maxp, cairo_truetype_font_write_maxp_table,     8 },
-    { TT_TAG_name, cairo_truetype_font_write_generic_table,  9 },
-    { TT_TAG_prep, cairo_truetype_font_write_generic_table, 10 },
-};
-
 static cairo_status_t
 cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
 {
@@ -748,20 +731,18 @@ cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
     unsigned char *table_buffer;
     size_t table_buffer_length;
     unsigned short search_range, entry_selector, range_shift;
-    int num_tables;
 
-    num_tables = ARRAY_LENGTH (truetype_tables);
     search_range = 1;
     entry_selector = 0;
-    while (search_range * 2 <= num_tables) {
+    while (search_range * 2 <= font->num_tables) {
 	search_range *= 2;
 	entry_selector++;
     }
     search_range *= 16;
-    range_shift = num_tables * 16 - search_range;
+    range_shift = font->num_tables * 16 - search_range;
 
     cairo_truetype_font_write_be32 (font, SFNT_VERSION);
-    cairo_truetype_font_write_be16 (font, num_tables);
+    cairo_truetype_font_write_be16 (font, font->num_tables);
     cairo_truetype_font_write_be16 (font, search_range);
     cairo_truetype_font_write_be16 (font, entry_selector);
     cairo_truetype_font_write_be16 (font, range_shift);
@@ -769,7 +750,7 @@ cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
     /* Allocate space for the table directory. Each directory entry
      * will be filled in by cairo_truetype_font_update_entry() after
      * the table is written. */
-    table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16;
+    table_buffer_length = font->num_tables * 16;
     status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length,
 						      &table_buffer);
     if (status)
@@ -824,7 +805,7 @@ cairo_truetype_font_generate (cairo_truetype_font_t  *font,
     cairo_status_t status;
     unsigned long start, end, next;
     uint32_t checksum, *checksum_location;
-    unsigned int i;
+    int i;
 
     if (cairo_truetype_font_write_offset_table (font))
 	goto fail;
@@ -833,14 +814,14 @@ cairo_truetype_font_generate (cairo_truetype_font_t  *font,
     end = start;
 
     end = 0;
-    for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
-	if (truetype_tables[i].write (font, truetype_tables[i].tag))
+    for (i = 0; i < font->num_tables; i++) {
+	if (font->truetype_tables[i].write (font, font->truetype_tables[i].tag))
 	    goto fail;
 
 	end = _cairo_array_num_elements (&font->output);
 	next = cairo_truetype_font_align_output (font);
-	cairo_truetype_font_update_entry (font, truetype_tables[i].pos, truetype_tables[i].tag,
-					start, end);
+	cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos,
+                                          font->truetype_tables[i].tag, start, end);
         status = cairo_truetype_font_check_boundary (font, next);
 	if (status) {
 	    font->status = status;
@@ -879,6 +860,91 @@ cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph)
     return font->parent_to_subset[glyph];
 }
 
+static void
+cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font,
+           unsigned long tag,
+           cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag),
+           int pos)
+{
+    font->truetype_tables[font->num_tables].tag = tag;
+    font->truetype_tables[font->num_tables].write = write;
+    font->truetype_tables[font->num_tables].pos = pos;
+    font->num_tables++;
+}
+
+/* cairo_truetype_font_create_truetype_table_list() builds the list of
+ * truetype tables to be embedded in the subsetted font. Each call to
+ * cairo_truetype_font_add_truetype_table() adds a table, the callback
+ * for generating the table, and the position in the table directory
+ * to the truetype_tables array.
+ *
+ * As we write out the glyf table we remap composite glyphs.
+ * Remapping composite glyphs will reference the sub glyphs the
+ * composite glyph is made up of. The "glyf" table callback needs to
+ * be called first so we have all the glyphs in the subset before
+ * going further.
+ *
+ * The order in which tables are added to the truetype_table array
+ * using cairo_truetype_font_add_truetype_table() specifies the order
+ * in which the callback functions will be called.
+ *
+ * The tables in the table directory must be listed in alphabetical
+ * order.  The "cvt", "fpgm", and "prep" are optional tables. They
+ * will only be embedded in the subset if they exist in the source
+ * font. The pos parameter of cairo_truetype_font_add_truetype_table()
+ * specifies the position of the table in the table directory.
+ */
+static void
+cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
+{
+    cairo_bool_t has_cvt = FALSE;
+    cairo_bool_t has_fpgm = FALSE;
+    cairo_bool_t has_prep = FALSE;
+    unsigned long size;
+    int pos;
+
+    size = 0;
+    if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
+                                      TT_TAG_cvt, 0, NULL,
+                                      &size) == CAIRO_STATUS_SUCCESS)
+        has_cvt = TRUE;
+
+    size = 0;
+    if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
+                                      TT_TAG_fpgm, 0, NULL,
+                                      &size) == CAIRO_STATUS_SUCCESS)
+        has_fpgm = TRUE;
+
+    size = 0;
+    if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
+                                      TT_TAG_prep, 0, NULL,
+                                      &size) == CAIRO_STATUS_SUCCESS)
+        has_prep = TRUE;
+
+    font->num_tables = 0;
+    pos = 1;
+    if (has_cvt)
+        pos++;
+    if (has_fpgm)
+        pos++;
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos);
+
+    pos = 0;
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++);
+    if (has_cvt)
+        cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt, cairo_truetype_font_write_generic_table, pos++);
+    if (has_fpgm)
+        cairo_truetype_font_add_truetype_table (font, TT_TAG_fpgm, cairo_truetype_font_write_generic_table, pos++);
+    pos++;
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_head, cairo_truetype_font_write_head_table, pos++);
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_hhea, cairo_truetype_font_write_hhea_table, pos++);
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, pos++);
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_loca, cairo_truetype_font_write_loca_table, pos++);
+    cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++);
+    if (has_prep)
+        cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos);
+}
+
 cairo_status_t
 _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 			     cairo_scaled_font_subset_t	*font_subset)
@@ -901,8 +967,9 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 	cairo_truetype_font_use_glyph (font, parent_glyph);
     }
 
+    cairo_truetype_font_create_truetype_table_list (font);
     status = cairo_truetype_font_generate (font, &data, &length,
-					 &string_offsets, &num_strings);
+                                           &string_offsets, &num_strings);
     if (status)
 	goto fail1;
 
commit e61f26a665925730c72fa08e14b491754661fbc0
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Sep 23 02:52:01 2007 +0100

    [type1-subset] only subset ft fonts
    
    If atsui and ft were both enabled, the code crashed trying to subset
    type-1 fonts; fixed by checking if fonts really are ft before using
    them as ft fonts. This is a temporary fix until we support subsetting
    across all font backends.
    (cherry picked from commit 8132b8b417c75388ce4c4671fffddaa44a5d1be0)

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 919b1d5..0716005 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1203,6 +1203,8 @@ _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
     PS_FontInfoRec font_info;
     cairo_bool_t is_type1 = FALSE;
 
+    if (!_cairo_scaled_font_is_ft (scaled_font))
+       return FALSE;
     unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
commit 2037316376e12155b8c372fd076123ecb5e365ff
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Sep 21 11:02:42 2007 -0700

    Avoid divide-by-zero when trying to allocate a 0-sized array
    
    Fix up the _cairo_malloc_* wrappers to avoid blindly dividing by zero;
    any attempt to allocate a zero-sized chunk of memory will result in
    NULL.
    (cherry picked from commit 6020f67f1a49cfe3844c4938d4af24c63c8424cc)

diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h
index f503b39..ad22851 100644
--- a/src/cairo-malloc-private.h
+++ b/src/cairo-malloc-private.h
@@ -40,11 +40,26 @@
 #include "cairo-wideint-private.h"
 
 /**
+ * _cairo_malloc:
+ * @size: size in bytes
+ *
+ * Allocate @size memory using malloc().
+ * The memory should be freed using free().
+ * malloc is skipped, if 0 bytes are requested, and %NULL will be returned.
+ *
+ * Return value: A pointer to the newly allocated memory, or %NULL in
+ * case of malloc() failure or size is 0.
+ */
+
+#define _cairo_malloc(size) \
+   ((size) ? malloc((unsigned) (size)) : NULL)
+
+/**
  * _cairo_malloc_ab:
  * @n: number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@size memory using malloc(), taking care to not
+ * Allocates @a*@size memory using _cairo_malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves much like
  * calloc(), except that the returned memory is not set to zero.
  * The memory should be freed using free().
@@ -57,8 +72,8 @@
  */
 
 #define _cairo_malloc_ab(a, size) \
-  ((unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
-   malloc((unsigned) (a) * (unsigned) (size)))
+  ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   _cairo_malloc((unsigned) (a) * (unsigned) (size)))
 
 /**
  * _cairo_malloc_abc:
@@ -66,7 +81,7 @@
  * @b: second factor of number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@b*@size memory using malloc(), taking care to not
+ * Allocates @a*@b*@size memory using _cairo_malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
@@ -78,9 +93,9 @@
  */
 
 #define _cairo_malloc_abc(a, b, size) \
-  ((unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
-   (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
-   malloc((unsigned) (a) * (unsigned) (b) * (unsigned) size))
+  ((b) && (unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
+   (size) && (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   _cairo_malloc((unsigned) (a) * (unsigned) (b) * (unsigned) (size)))
 
 /**
  * _cairo_malloc_ab_plus_c:
@@ -88,7 +103,7 @@
  * @size: size of each element
  * @k: additional size to allocate
  *
- * Allocates @a*@ksize+ at k memory using malloc(), taking care to not
+ * Allocates @a*@ksize+ at k memory using _cairo_malloc(), taking care to not
  * overflow when doing the arithmetic.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
@@ -97,8 +112,8 @@
  */
 
 #define _cairo_malloc_ab_plus_c(n, size, k) \
-  ((unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
+  ((size) && (unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
    (unsigned) (k) >= INT32_MAX - (unsigned) (n) * (unsigned) (size) ? NULL : \
-   malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
+   _cairo_malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
 
 #endif /* CAIRO_MALLOC_PRIVATE_H */
commit cca53adefca0823f1fb8ace278b8ca8ff43a829f
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Aug 29 16:30:49 2007 -0700

    Make NO_MUTEX really mean no mutexes
    (cherry picked from commit e3c16e15e39d98f96e2ce20e397d88214f5a821e)

diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h
index 59d581a..b9f0fb3 100644
--- a/src/cairo-mutex-type-private.h
+++ b/src/cairo-mutex-type-private.h
@@ -141,13 +141,13 @@ CAIRO_BEGIN_DECLS
 
 #if CAIRO_NO_MUTEX
 
-/* A poor man's mutex */
+/* No mutexes */
 
   typedef int cairo_mutex_t;
 
 # define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_LOCK(mutex) do { while (mutex) ; (mutex) = 1; } while (0)
-# define CAIRO_MUTEX_UNLOCK(mutex) (mutex) = 0
+# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
+# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
 # define CAIRO_MUTEX_NIL_INITIALIZER 0
 
 #elif HAVE_PTHREAD_H /*******************************************************/
commit 65e4841e6099881bda90c976b644611f31f7d62a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Sep 12 17:45:11 2007 -0400

    [cairo-ft-font] Ignore FT_Load_Glyph errors other than out-of-memory
    Same for FT_Render_Glyph.
    
    When the user asks us to render a glyph that is not available in the font,
    it's mostly an unavoidable kind of error for them, as in, they can't
    avoid such a call.  So it's not nice to put cairo_t in an error state and
    refuse any further drawying.
    
    Many PDF files are created using buggy software and cause such glpyh-not-found
    errors for CID 0 for example.
    
    Eventually we should propagate these kind of errors up and return it from
    the function call causing it, but that needs API change to add return value
    to all text functions, so for now we just ignore these errors.
    (cherry picked from commit 79d975f84bcc32e91db517d71a7312e2e1d653d4)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 69e35d2..d8bb64a 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1091,7 +1091,9 @@ _render_glyph_bitmap (FT_Face		      face,
      * we avoid the FT_LOAD_NO_RECURSE flag.
      */
     error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
-    if (error) {
+    /* XXX ignoring all other errors for now.  They are not fatal, typically
+     * just a glyph-not-found. */
+    if (error == FT_Err_Out_Of_Memory) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return CAIRO_STATUS_NO_MEMORY;
     }
@@ -1885,8 +1887,9 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
     error = FT_Load_Glyph (scaled_font->unscaled->face,
 			   _cairo_scaled_glyph_index(scaled_glyph),
 			   load_flags);
-
-    if (error) {
+    /* XXX ignoring all other errors for now.  They are not fatal, typically
+     * just a glyph-not-found. */
+    if (error == FT_Err_Out_Of_Memory) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto FAIL;
     }
@@ -2036,8 +2039,9 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
 	    error = FT_Load_Glyph (face,
 				   _cairo_scaled_glyph_index(scaled_glyph),
 				   load_flags | FT_LOAD_NO_BITMAP);
-
-	    if (error) {
+	    /* XXX ignoring all other errors for now.  They are not fatal, typically
+	     * just a glyph-not-found. */
+	    if (error == FT_Err_Out_Of_Memory) {
 		_cairo_ft_unscaled_font_unlock_face (unscaled);
 		_cairo_error (CAIRO_STATUS_NO_MEMORY);
 		return CAIRO_STATUS_NO_MEMORY;
commit 1f5d6f9dc70a0330ece30980ec1a9c18c0bec5c9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Sep 17 16:41:52 2007 -0400

    =?utf-8?q?[ChangeLog.mk]=20Make=20make=20rule=20depend=20on=20.git/HEAD,=20not=20.git
    
    =20That=20is=20exactly=20what=20we=20want.=20=20Kristian=20H=C3=B8gsberg=20suggested=20it.
    =20(cherry=20picked=20from=20commit=2021ab44f11d3d20eead5d988c7a6cf48eebff08c7)?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: 8bit

diff --git a/ChangeLog.mk b/ChangeLog.mk
index 99f5ed6..1566824 100644
--- a/ChangeLog.mk
+++ b/ChangeLog.mk
@@ -51,7 +51,7 @@ $(srcdir)/ChangeLog:
 
 DISTCLEANFILES += ChangeLog.cache-*
 
-ChangeLog.cache-*..: .git
+ChangeLog.cache-*..: .git/HEAD
 
 ChangeLog%: $(srcdir)/ChangeLog%
 
commit 00f1398d4ac82c410929af19e65ee9714c58ae20
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 5 08:07:41 2007 +0100

    [cairo-ft-font] Early detection of a zero sized bitmap.
    
    Under rare circumstances we may need to extract a surface that
    represents a bitmap with width==0 and rows==0. Detect this case at the
    start and simply return a zero-sized surface.
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=12284.
    (cherry picked from commit d62f8861689d8b9a9a837043fb78813f0407abd4)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 04441d0..69e35d2 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -736,6 +736,12 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
     width = bitmap->width;
     height = bitmap->rows;
 
+    if (width == 0 || height == 0) {
+	*surface = (cairo_image_surface_t *)
+	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
+	return (*surface)->base.status;
+    }
+
     switch (bitmap->pixel_mode) {
     case FT_PIXEL_MODE_MONO:
 	stride = (((width + 31) & ~31) >> 3);
commit b0485ed171d2544966da2e94ccb3d23761dfe804
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Sep 5 22:53:43 2007 +0930

    Create meta-surface source image with same content type as the
    meta-surface
    (cherry picked from commit 1e21220f0e2540e3befa66e4764f75589d0eef82)

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index e875e97..01da1e3 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -184,9 +184,9 @@ _cairo_meta_surface_acquire_source_image (void			 *abstract_surface,
     cairo_meta_surface_t *surface = abstract_surface;
     cairo_surface_t *image;
 
-    image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-					surface->width_pixels,
-					surface->height_pixels);
+    image = _cairo_image_surface_create_with_content (surface->content,
+						      surface->width_pixels,
+						      surface->height_pixels);
 
     status = _cairo_meta_surface_replay (&surface->base, image);
     if (status) {
commit 3dfd7ab1877342a9b3a1fe9f5a4b7735ec6bef70
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Sep 5 22:51:13 2007 +0930

    Eliminate unclipped CLEAR from meta-surface playback
    
    The optimization that avoids replaying commands prior to an unclipped
    CLEAR operation now starts playback from the first command after the
    CLEAR. This avoids the need to handle the unclipped CLEAR in the PDF
    surface.
    (cherry picked from commit 875e32178e5d990a09f3c41262d890888035f04f)

diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 30a64e7..e875e97 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -243,12 +243,6 @@ _cairo_meta_surface_paint (void			*abstract_surface,
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_paint_t *command;
 
-    /* An optimisation that takes care to not replay what was done
-     * before surface is cleared. We don't erase recorded commands
-     * since we may have earlier snapshots of this surface. */
-    if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
-	meta->replay_start_idx = meta->commands.num_elements;
-
     command = malloc (sizeof (cairo_command_paint_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
@@ -264,6 +258,12 @@ _cairo_meta_surface_paint (void			*abstract_surface,
     if (status)
 	goto CLEANUP_SOURCE;
 
+    /* An optimisation that takes care to not replay what was done
+     * before surface is cleared. We don't erase recorded commands
+     * since we may have earlier snapshots of this surface. */
+    if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
+	meta->replay_start_idx = meta->commands.num_elements;
+
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_SOURCE:
commit d0ad0e2fcc28301c8fd7a9b94aaf5b430e76c307
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Sep 5 00:26:56 2007 -0400

    [configure.in] Fix non-pkgconfig Xrender detection path (#4724)
    (cherry picked from commit b85032584b32af968dc8d8a0fcfc9f3e1d2770a0)

diff --git a/configure.in b/configure.in
index 834002c..a448115 100644
--- a/configure.in
+++ b/configure.in
@@ -261,9 +261,13 @@ CAIRO_BACKEND_ENABLE(xlib_xrender, Xlib Xrender, xlib-xrender, XLIB_XRENDER_SURF
     PKG_CHECK_MODULES(xlib_xrender, $xlib_xrender_REQUIRES, ,
 		      [AC_MSG_RESULT(no)
 		       xlib_xrender_REQUIRES=""
+		       old_CPPFLAGS=$CPPFLAGS
+		       CPPFLAGS="$CPPFLAGS $xlib_CFLAGS $xlib_NONPKGCONFIG_CFLAGS"
 		       AC_CHECK_HEADER(X11/extensions/Xrender.h,
 				       [xlib_xrender_NONPKGCONFIG_LIBS="-lXrender"],
-				       [use_xlib_xrender="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
+				       [use_xlib_xrender="no (requires Xrender http://freedesktop.org/Software/xlibs)"])
+		       CPPFLAGS=$old_CPPFLAGS
+		      ])
   fi
 ])
 
commit 51269b3894d1641e19a3791d4ed641e85dd1a073
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Aug 28 23:40:18 2007 +0930

    Fix PDF gradients bug
    
    The PDF surface was adding extra stops at the 0.0 and 1.0 offset when
    there was not already stops at these offsets. This has been replaced
    with code to move the coordinates of the linear gradient line in to
    the position of the first and last offset.
    (cherry picked from commit 3216275fd9a9cd8d51b1c3a8671393912d50d899)

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 815eae0..5e54b38 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1190,9 +1190,9 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
     for (i = 0; i < n_stops-1; i++) {
         if (is_alpha) {
             status = cairo_pdf_surface_emit_alpha_linear_function (surface,
-                                                             &stops[i],
-                                                             &stops[i+1],
-                                                             &stops[i].resource);
+                                                                   &stops[i],
+                                                                   &stops[i+1],
+                                                                   &stops[i].resource);
             if (status)
                 return status;
         } else {
@@ -1210,8 +1210,10 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 3\r\n"
-				 "   /Domain [ 0 1 ]\r\n",
-				 res.id);
+				 "   /Domain [ %f %f ]\r\n",
+				 res.id,
+                                 stops[0].offset,
+                                 stops[n_stops - 1].offset);
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Functions [ ");
@@ -1280,23 +1282,6 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
 	stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
     }
 
-    /* make sure first offset is 0.0 and last offset is 1.0. (Otherwise Acrobat
-     * Reader chokes.) */
-    if (stops[0].offset > COLOR_STOP_EPSILON) {
-	    memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
-	    stops = allstops;
-	    n_stops++;
-    }
-    stops[0].offset = 0.0;
-
-    if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
-	    memcpy (&stops[n_stops],
-		    &stops[n_stops - 1],
-		    sizeof (cairo_pdf_color_stop_t));
-	    n_stops++;
-    }
-    stops[n_stops-1].offset = 1.0;
-
     if (n_stops == 2) {
         /* no need for stitched function */
         status = cairo_pdf_surface_emit_rgb_linear_function (surface,
@@ -1424,6 +1409,8 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
     cairo_matrix_t pat_to_pdf;
     cairo_extend_t extend;
     cairo_status_t status;
+    cairo_gradient_pattern_t *gradient = &pattern->base;
+    double first_stop, last_stop;
 
     extend = cairo_pattern_get_extend (&pattern->base.base);
     status = _cairo_pdf_surface_pause_content_stream (surface);
@@ -1448,6 +1435,36 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
     x2 = _cairo_fixed_to_double (pattern->gradient.p2.x);
     y2 = _cairo_fixed_to_double (pattern->gradient.p2.y);
 
+    first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
+    last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
+
+    /* PDF requires the first and last stop to be the same as the line
+     * coordinates. If this is not a repeating pattern move the line
+     * coordinates to the location of first and last stop. */
+
+    if (pattern->base.base.extend == CAIRO_EXTEND_NONE ||
+	pattern->base.base.extend == CAIRO_EXTEND_PAD) {
+	double _x1, _y1, _x2, _y2;
+
+	_x1 = x1 + (x2 - x1)*first_stop;
+	_y1 = y1 + (y2 - y1)*first_stop;
+	_x2 = x1 + (x2 - x1)*last_stop;
+	_y2 = y1 + (y2 - y1)*last_stop;
+
+	x1 = _x1;
+	x2 = _x2;
+	y1 = _y1;
+	y2 = _y2;
+    }
+
+    if (gradient->n_stops == 2) {
+	/* If only two stops the Type 2 function is used by itself
+	 * without a Stitching function. Type 2 functions always have
+	 * the domain [0 1] */
+	first_stop = 0.0;
+	last_stop = 1.0;
+    }
+
     pattern_resource = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
                                  "%d 0 obj\r\n"
@@ -1458,12 +1475,14 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
                                  "      << /ShadingType 2\r\n"
                                  "         /ColorSpace /DeviceRGB\r\n"
                                  "         /Coords [ %f %f %f %f ]\r\n"
+                                 "         /Domain [ %f %f ]\r\n"
                                  "         /Function %d 0 R\r\n",
                                  pattern_resource.id,
                                  pat_to_pdf.xx, pat_to_pdf.yx,
                                  pat_to_pdf.xy, pat_to_pdf.yy,
                                  pat_to_pdf.x0, pat_to_pdf.y0,
                                  x1, y1, x2, y2,
+                                 first_stop, last_stop,
                                  color_function.id);
 
     if (extend == CAIRO_EXTEND_PAD) {
commit c20664b9a2e60d9503d6ae0f0df260c2f93b76f6
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Aug 29 12:52:00 2007 -0700

    [win32] call scaled_font_fini in create before returning NULL
    (cherry picked from commit bdc70d1fc2a31aa829571244c54f98210e97a2cf)

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 081a670..3a13ef3 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -286,16 +286,21 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
     status = _cairo_scaled_font_init (&f->base, font_face,
 				      font_matrix, ctm, options,
 				      &cairo_win32_scaled_font_backend);
+    if (status)
+	goto FAIL;
 
-    if (status == CAIRO_STATUS_SUCCESS)
-	status = _cairo_win32_scaled_font_set_metrics (f);
+    status = _cairo_win32_scaled_font_set_metrics (f);
 
     if (status) {
-	free (f);
-	return NULL;
+	_cairo_scaled_font_fini (&f->base);
+	goto FAIL;
     }
 
     return &f->base;
+
+ FAIL:
+    free (f);
+    return NULL;
 }
 
 static cairo_status_t
commit f2805ec50139ffc226d9a085e056bbb92f39accd
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Aug 29 12:18:16 2007 -0400

    [configure.in] Make PS backend require zlib too (#12210)
    
    The PS backend uses zlib these days.  Make it depend on zlib being available
    like PDF has been doing.
    (cherry picked from commit 114b07881e8b09f97394dd4fe8f2900ee9f4c348)

diff --git a/configure.in b/configure.in
index 775e9c5..834002c 100644
--- a/configure.in
+++ b/configure.in
@@ -522,7 +522,11 @@ fi
 
 dnl ===========================================================================
 
-CAIRO_BACKEND_ENABLE(ps, PostScript, ps, PS_SURFACE, auto, [use_ps=yes])
+CAIRO_BACKEND_ENABLE(ps, PostScript, ps, PS_SURFACE, auto, [
+    # The ps backend requires zlib.
+    use_ps=$have_libz
+    ps_NONPKGCONFIG_LIBS=-lz
+])
 
 dnl ===========================================================================
 
commit 832aafc52ab8d3876d1ed44e9b6c78cab264eff5
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Aug 28 16:47:24 2007 -0700

    Fix previous create_similar fallback patch
    
    We can't use composite, as some backends don't implement it.
    Use paint() instead.
    (cherry picked from commit 93aee43690c329f43be9e7b840851267ceb17956)

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 81dfaf5..ae62dfc 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1634,38 +1634,6 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 
 	status = _cairo_surface_clone_similar (dst, pattern->surface,
 					       x, y, width, height, out);
-
-	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-
-	    cairo_t *cr;
-
-	    *out = cairo_surface_create_similar (dst, dst->content,
-						 width, height);
-	    status = cairo_surface_status (*out);
-	    if (status) {
-		cairo_surface_destroy (*out);
-		*out = NULL;
-		return status;
-	    }
-
-	    (*out)->device_transform = pattern->surface->device_transform;
-	    (*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
-
-	    /* XXX Use _cairo_surface_composite directly */
-	    cr = cairo_create (*out);
-
-	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-	    cairo_set_source_surface (cr, pattern->surface, -x, -y);
-	    cairo_paint (cr);
-
-	    status = cairo_status (cr);
-	    cairo_destroy (cr);
-
-	    if (status) {
-		cairo_surface_destroy (*out);
-		*out = NULL;
-	    }
-	}
     }
 
     return status;
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 3593347..0d36257 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1262,8 +1262,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
 				       cairo_surface_t **clone_out)
 {
     cairo_status_t status;
-    cairo_pattern_union_t src_pattern;
     cairo_surface_t *new_surface = NULL;
+    cairo_t *cr;
 
     new_surface = _cairo_surface_create_similar_scratch (surface,
 							 cairo_surface_get_content (src),
@@ -1271,18 +1271,22 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
     if (new_surface->status)
 	return new_surface->status;
 
-    _cairo_pattern_init_for_surface (&src_pattern.surface, src);
+    /* We have to copy these here, so that the coordinate spaces are correct */
+    new_surface->device_transform = src->device_transform;
+    new_surface->device_transform_inverse = src->device_transform_inverse;
 
-    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
-				       &src_pattern.base,
-				       NULL,
-				       new_surface,
-				       src_x, src_y,
-				       0, 0,
-				       0, 0,
-				       width, height);
-
-    _cairo_pattern_fini (&src_pattern.base);
+    /* We can't use _cairo_composite directly, because backends that
+     * implement the "high-level" API may not have it implemented.
+     * (For example, SVG.)  We can fix this by either checking if the
+     * destination supports composite first, or we can make clone a
+     * required "high-level" operation.
+     */
+    cr = cairo_create (new_surface);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_surface (cr, src, -src_x, -src_y);
+    cairo_paint (cr);
+    status = cairo_status (cr);
+    cairo_destroy (cr);
 
     if (status == CAIRO_STATUS_SUCCESS)
 	*clone_out = new_surface;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 242faac..b6720c4 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1023,46 +1023,49 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
 			      int               height,
 			      cairo_surface_t **clone_out)
 {
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     cairo_image_surface_t *image;
     void *image_extra;
 
     if (surface->finished)
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
-    if (surface->backend->clone_similar == NULL)
-	return (cairo_int_status_t)
-	    _cairo_surface_fallback_clone_similar (surface, src,
-						   src_x, src_y,
-						   width, height,
-						   clone_out);
+    if (surface->backend->clone_similar) {
+	status = surface->backend->clone_similar (surface, src, src_x, src_y,
+						  width, height, clone_out);
 
-    status = surface->backend->clone_similar (surface, src, src_x, src_y,
-					      width, height, clone_out);
-    if (status == CAIRO_STATUS_SUCCESS && *clone_out != src)
-        (*clone_out)->device_transform = src->device_transform;
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	    /* If we failed, try again with an image surface */
+	    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
+	    if (status == CAIRO_STATUS_SUCCESS) {
+		status =
+		    surface->backend->clone_similar (surface, &image->base,
+						     src_x, src_y,
+						     width, height,
+						     clone_out);
 
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	return status;
+		_cairo_surface_release_source_image (src, image, image_extra);
+	    }
+	}
+    }
 
-    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
-    if (status != CAIRO_STATUS_SUCCESS)
+    /* If we're still unsupported, hit our fallback path to get a clone */
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	status =
+	    _cairo_surface_fallback_clone_similar (surface, src, src_x, src_y,
+						   width, height, clone_out);
+
+    /* We should never get UNSUPPORTED here, so if we have an error, bail. */
+    if (status)
 	return status;
 
-    status = surface->backend->clone_similar (surface, &image->base, src_x,
-					      src_y, width, height, clone_out);
-    if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) {
+    /* Update the clone's device_transform (which the underlying surface
+     * backend knows nothing about) */
+    if (*clone_out != src) {
         (*clone_out)->device_transform = src->device_transform;
         (*clone_out)->device_transform_inverse = src->device_transform_inverse;
-    }
-
-    /* If the above failed point, we could implement a full fallback
-     * using acquire_dest_image, but that's going to be very
-     * inefficient compared to a backend-specific implementation of
-     * clone_similar() with an image source. So we don't bother
-     */
+    }	
 
-    _cairo_surface_release_source_image (src, image, image_extra);
     return status;
 }
 
commit ec0593d89e24eaf70d5719f5293720127c6dcfac
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Aug 28 10:47:52 2007 -0700

    [win32] call free() and not scaled_font_destroy() if scaled init fails
    
    If scaled_font_destroy() is called, a deadlock can result; there's no
    reason to call destroy since the initialization failed (and, indeed,
    it might not be valid to do so anyway).
    (cherry picked from commit 6525d4debb6df67126b04609bb04d23d9c9bd7a6)

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 681dba7..081a670 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -291,7 +291,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
 	status = _cairo_win32_scaled_font_set_metrics (f);
 
     if (status) {
-	cairo_scaled_font_destroy (&f->base);
+	free (f);
 	return NULL;
     }
 
commit f202a77e1236157fc0ee5ebe14a9998fa46a032d
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Mon Aug 27 16:30:52 2007 -0700

    Implement fallback for clone_similar
    (cherry picked from commit 69dae7ee4ace8a92226140ce5ccb690e7f62e35c)

diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
index e0f83c4..b4ec5d1 100644
--- a/src/cairo-surface-fallback-private.h
+++ b/src/cairo-surface-fallback-private.h
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
@@ -116,4 +117,13 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t		op,
 					      cairo_trapezoid_t	       *traps,
 					      int			num_traps);
 
+cairo_private cairo_status_t
+_cairo_surface_fallback_clone_similar (cairo_surface_t  *surface,
+				       cairo_surface_t  *src,
+				       int               src_x,
+				       int               src_y,
+				       int               width,
+				       int               height,
+				       cairo_surface_t **clone_out);
+
 #endif
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index bf7ae99..3593347 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
@@ -1250,3 +1251,43 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t		op,
 
     return status;
 }
+
+cairo_status_t
+_cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
+				       cairo_surface_t	*src,
+				       int		 src_x,
+				       int		 src_y,
+				       int		 width,
+				       int		 height,
+				       cairo_surface_t **clone_out)
+{
+    cairo_status_t status;
+    cairo_pattern_union_t src_pattern;
+    cairo_surface_t *new_surface = NULL;
+
+    new_surface = _cairo_surface_create_similar_scratch (surface,
+							 cairo_surface_get_content (src),
+							 width, height);
+    if (new_surface->status)
+	return new_surface->status;
+
+    _cairo_pattern_init_for_surface (&src_pattern.surface, src);
+
+    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+				       &src_pattern.base,
+				       NULL,
+				       new_surface,
+				       src_x, src_y,
+				       0, 0,
+				       0, 0,
+				       width, height);
+
+    _cairo_pattern_fini (&src_pattern.base);
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	*clone_out = new_surface;
+    else
+	cairo_surface_destroy (new_surface);
+
+    return status;
+}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 447cb62..242faac 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1031,7 +1031,11 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
     if (surface->backend->clone_similar == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return (cairo_int_status_t)
+	    _cairo_surface_fallback_clone_similar (surface, src,
+						   src_x, src_y,
+						   width, height,
+						   clone_out);
 
     status = surface->backend->clone_similar (surface, src, src_x, src_y,
 					      width, height, clone_out);
commit b056bb3c1d344c9bb7d576e1558effa9dd6414a0
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Mon Aug 27 14:26:19 2007 -0700

    [win32] check correct surface for BitBlt support in get_subimage
    (cherry picked from commit f4a8633fce5262c09b323eef212fd6efe57d8f10)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 7f86eb8..ed5e352 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -476,7 +476,10 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
 
     status = CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
+    /* We are blitting -from- surface, so we need to check if it
+     * supports BitBlt.  I believe any surface can be used as a
+     * BitBlt destination. */
+    if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
 	BitBlt (local->dc,
 		0, 0,
 		width, height,
commit 95e61a5823ba95affc342c2d23e0c585ec7a22b7
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Aug 21 10:03:00 2007 -0700

    Ensure the Render extension is initialized before calling XESetCloseDisplay
    
    This avoids a potential crash from the Render extension being cleaned
    up during XCloseDisplay before the cairo CloseDisplay hook goes on to
    call into XRenderFreePicture.
    (cherry picked from commit 9f4e6436496fe561aa124bb2b89e1c6711684d98)

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index c7c3c43..b8f35cb 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -226,6 +226,7 @@ _cairo_xlib_display_get (Display *dpy)
     cairo_xlib_display_t *display;
     cairo_xlib_display_t **prev;
     XExtCodes *codes;
+    int major_unused, minor_unused;
 
     /* There is an apparent deadlock between this mutex and the
      * mutex for the display, but it's actually safe. For the
@@ -260,6 +261,14 @@ _cairo_xlib_display_get (Display *dpy)
     if (display == NULL)
 	goto UNLOCK;
 
+    /* Xlib calls out to the extension close_display hooks in LIFO
+     * order. So we have to ensure that all extensions that we depend
+     * on in our close_display hook are properly initialized before we
+     * add our hook. For now, that means Render, so we call into its
+     * QueryVersion function to ensure it gets initialized.
+     */
+    XRenderQueryVersion (dpy, &major_unused, &minor_unused);
+
     codes = XAddExtension (dpy);
     if (codes == NULL) {
 	free (display);
commit 820cca9c755b760e91efacfc189af2a428492e94
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 16 12:21:49 2007 +0100

    [cairo-ft-font] Decrement lock count on error.
    
    As noted in http://bugs.freedesktop.org/show_bug.cgi?id=12026 the error
    path of _cairo_ft_unscaled_font_lock_face() failed to reset the
    unscaled->lock_count before releasing the mutex and returning NULL.
    (cherry picked from commit bc635da45a32eb9b7aff6fa5f7f560ebf99092a8)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 4dc61ee..04441d0 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -552,6 +552,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
 		     unscaled->id,
 		     &face) != FT_Err_Ok)
     {
+	unscaled->lock_count--;
 	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return NULL;
commit 2f6957b44003eb98f3431ef0648bc04df1ccfb23
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Aug 10 20:10:29 2007 +0930

    PDF: Fix regression in pdf_surface_set_size()
    (cherry picked from commit 8881265cca73790a49068b3bab5362cb73f8deb6)

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index cf5af87..815eae0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -446,6 +446,7 @@ cairo_pdf_surface_set_size (cairo_surface_t	*surface,
 
     pdf_surface->width = width_in_points;
     pdf_surface->height = height_in_points;
+    cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points);
 }
 
 static void
commit 7538abbe672b3e6d990de34db8055ceb17511c07
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Aug 6 11:06:47 2007 -0700

    Ensure that a copied pattern gets its own user_data array
    
    This fixes the bug reported here:
    
    	Segfault with cairo_pattern_set_user_data
    	https://bugs.freedesktop.org/show_bug.cgi?id=11855
    (cherry picked from commit 13cae8b5e6d3fc93c4eb1853b91ba356b572b551)

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 6ead4b2..81dfaf5 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -185,7 +185,9 @@ _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
     } break;
     }
 
+    /* The reference count and user_data array are unique to the copy. */
     pattern->ref_count = 1;
+    _cairo_user_data_array_init (&pattern->user_data);
 
     return CAIRO_STATUS_SUCCESS;
 }
commit aae69c34b5f2f2f2349657473c32fbb274861b80
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 5 00:50:23 2007 +0930

    PDF: Fix gradients regression
    (cherry picked from commit 72c1f5d802c32f97ae5c0cbf899dc3a12fc28222)

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index dc5cda5..cf5af87 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1270,10 +1270,10 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
     n_stops = pattern->n_stops;
 
     for (i = 0; i < n_stops; i++) {
-	stops[i].color[0] = pattern->stops[i].color.red / 65535.0;
-	stops[i].color[1] = pattern->stops[i].color.green / 65535.0;
-	stops[i].color[2] = pattern->stops[i].color.blue / 65535.0;
-	stops[i].color[3] = pattern->stops[i].color.alpha / 65535.0;
+	stops[i].color[0] = pattern->stops[i].color.red;
+	stops[i].color[1] = pattern->stops[i].color.green;
+	stops[i].color[2] = pattern->stops[i].color.blue;
+	stops[i].color[3] = pattern->stops[i].color.alpha;
         if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
             emit_alpha = TRUE;
 	stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
commit a76f8653d6877134a1d3acbb0fcb4f68ebfbcb8f
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Thu Aug 2 21:25:46 2007 +0930

    CFF Subsetting: fix integer encoding bug
    
    Bug report at https://bugzilla.mozilla.org/show_bug.cgi?id=368668
    (cherry picked from commit f52aa4c13e91339e575ca2c52c9e3a1f4d95b106)

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 2adc709..55e0f15 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -158,7 +158,7 @@ encode_integer (unsigned char *p, int i)
         i = -i - 108;
         *p++ = (i >> 8)+ 251;
         *p++ = i & 0xff;
-    } else if (i >= -1131 && i <= -108) {
+    } else if (i >= -32768 && i <= 32767) {
         *p++ = 28;
         *p++ = (i >> 8)  & 0xff;
         *p++ = i & 0xff;
commit 553d8a9319cdb2f6d9378b5fb304f0e4c2e81f25
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 11 17:54:55 2007 +0100

    [Makefile.am] Add missing headers and reference images.
    
    Andrew Jorgensen spotted that make dist was missing a few headers needed
    for compilation and running make distcheck had spurious failures. Add
    the missing files to the distribution and a silly one-liner to check for
    missing reference images.
    (cherry picked from commit e5b01e67975578797b4f7875a9ba02121ff935b5)
    
    [With some edits after cherry-picking to elide files that don't exist
    in the 1.4 branch.]

diff --git a/src/Makefile.am b/src/Makefile.am
index 0378ca4..f8d21b7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -191,6 +191,7 @@ libcairo_la_SOURCES =				\
 	cairo-hull.c				\
 	cairo-image-surface.c			\
 	cairo-lzw.c				\
+	cairo-malloc-private.h			\
 	cairo-matrix.c				\
 	cairo-mutex.c				\
 	cairo-mutex-list-private.h		\
diff --git a/test/Makefile.am b/test/Makefile.am
index 4d9f5f5..14d3717 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -346,6 +346,7 @@ REFERENCE_IMAGES = \
 	push-group-rgb24-ref.png	\
 	push-group-svg-argb32-ref.png	\
 	radial-gradient-ref.png	\
+	radial-gradient-svg-ref.png	\
 	random-intersections-ps-argb32-ref.png	\
 	random-intersections-ref.png	\
 	rectangle-rounding-error-ref.png	\
@@ -617,4 +618,10 @@ check-ref-dups:
 	@sha1sum *-ref.png > ref.hash
 	@join ref.hash ref.hash | grep -v -E '( .*-ref.png).*\1' | cut -d' ' -f 1-2 | sort -u
 
-.PHONY: check-valgrind test recheck retest html rehtml check-ref-dups
+# Not exactly the best script in the world...
+check-ref-missing:
+	@for i in *-ref.png; do\
+	    echo ${REFERENCE_IMAGES} | grep -sq $$i || echo $$i; \
+	done
+
+.PHONY: check-valgrind test recheck retest html rehtml check-ref-dups check-ref-missing
commit 33b1e9ad8bd560e8a0119b2fc0b38bc4d9b03f8f
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Nov 21 10:43:21 2007 -0800

    Add missing definition of INT32_MAX
    
    Some win32 builds were broken without this.

diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h
index 491fc89..3eeb6c3 100644
--- a/pixman/src/pixman.h
+++ b/pixman/src/pixman.h
@@ -89,10 +89,21 @@ SOFTWARE.
   typedef unsigned __int32 uint32_t;
   typedef __int64 int64_t;
   typedef unsigned __int64 uint64_t;
-
+# ifndef INT16_MIN
+#  define INT16_MIN	(-32767-1)
+# endif
+# ifndef INT16_MAX
+#  define INT16_MAX	(32767)
+# endif
 # ifndef UINT16_MAX
 #  define UINT16_MAX	(65535)
 # endif
+# ifndef INT32_MIN
+#  define INT32_MIN	(-2147483647-1)
+# endif
+# ifndef INT32_MAX
+#  define INT32_MAX	(2147483647)
+# endif
 # ifndef UINT32_MAX
 #  define UINT32_MAX	(0xffffffffU)
 # endif


More information about the cairo-commit mailing list