[cairo-commit] Branch '1.4' - 57 commits - autogen.sh ChangeLog.mk configure.in NEWS 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 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
Mon Nov 26 22:33:26 PST 2007


Rebased ref, commits from common ancestor:
commit 442fa9a106b01f17699397dcc95298071a50fd6d
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Nov 26 22:31:32 2007 -0800

    Increment version to 1.4.12 and 13:6:11

diff --git a/configure.in b/configure.in
index 515b06e..2cda71e 100644
--- a/configure.in
+++ b/configure.in
@@ -5,7 +5,7 @@ dnl An odd micro number indicates in-progress development, (eg. from git/cvs)
 dnl An even micro number indicates a released version.
 m4_define(cairo_version_major, 1)
 m4_define(cairo_version_minor, 4)
-m4_define(cairo_version_micro, 11)
+m4_define(cairo_version_micro, 12)
 
 AC_INIT([cairo],
       cairo_version_major.cairo_version_minor.cairo_version_micro,
@@ -26,7 +26,7 @@ LT_CURRENT=13
 
 # Increment any time the source changes; set to
 # 0 if you increment CURRENT
-LT_REVISION=5
+LT_REVISION=6
 
 # Increment if any interfaces have been added; set to 0
 # if any interfaces have been removed. removal has
commit b28c7a90fce099cc6e8879ba05358f6389948975
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Nov 26 21:52:41 2007 -0800

    NEWS: Add notes for cairo 1.4.12

diff --git a/NEWS b/NEWS
index 9761028..2771e31 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,58 @@
+Release 1.4.12 (2007-11-26 Carl Worth <cworth at cworth.org>)
+==========================================================
+This is the sixth update in cairo's stable 1.4 series. It comes five
+months after the 1.4.10 release. This fix includes various bug fixes
+originally developed during the 1.5.x development and backported to
+1.4.
+
+Some of the most significant bug fixes prevent crashes:
+
+  * Avoid overflow when allocating large buffers (Vladimir Vukicevic)
+
+  * Fix crash with cairo_pattern_set_user_data (Carl Worth)
+
+  * Fix broken locking in cairo-ft error path (Chris Wilson)
+
+  * Avoid crash when cleaning up after Render extension (Carl Worth)
+
+  * Avoid crash for zero-sized bitmap glyph (Chris Wilson)
+
+  * Avoid crash with type-1 fonts and ft and atsui enabled (Brian Ewins)
+
+  * Fix many error-handling cases in the Quartz/ATSUI code (Brian Ewins)
+
+  * Eliminate cairo_stroke crash with scaling near zero (Carl Worth)
+
+Other fixes address rendering problems:
+
+  * Fix PDF linear gradients without stops at 0.0 and 1.0 (Adrian Johnson)
+
+  * Fix PDF CFF subsetting to work with Apple Preview (Adrian Johnson)
+
+  * Report proper errors on out-of-memory on win32 (Vladimir Vukicevic)
+
+  * Fix EXTEND_NONE gradients for cairo-quartz (Brian Ewins)
+
+  * Fix odd-number-of-dashes dashing for cairo-quartz (Brian Ewins)
+
+  * Fix erroneous results from cairo_stroke_extents (Carl Worth)
+
+  * Force non-AA text when bitmap strikes are available (Keith Packard)
+
+  * Fix cairo-atsui font metrics (Richard Hult)
+
+And some avoid raising cairo errors for innocent problems:
+
+  * Avoid drawing shutdown for glyph-not-found in font (Behdad Esfahbod)
+
+  * Don't raise an error for creating an empty path (Chris Wilson)
+
+At least one optimization managed to sneak in:
+
+  * Free glyph surfaces after uploading to X server cache (Behdad Esfahbod)
+
+And there are a few very minor fixes, (such as build fixes).
+
 Release 1.4.10 (2007-06-27 Carl Worth <cworth at cworth.org>)
 ==========================================================
 This is the fifth update in cairo's stable 1.4 series. It comes
commit 617d3f5738a8e9e6fccbbaa9a314f04383fbfc39
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 bc67e2a37b480e038e8215ae9093561f91090c76
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 476f888f4e38c63b535a06be77c49c2f4bdad010
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 589700e..6d8586a 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -224,7 +224,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 5c2ad5f69db5c685a3d5d9feeefb911df560bca3
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 e9de14eb4d841071c15e8aea7bc5d463ceb59622
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 19e29dfb80ee06b4a4a187ba40e2e0c6ecf0dab2
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 efcaee8f838177c1d1766e48aaa5dbf8cb9cf1d8
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 b7baef143316566fee1478bfeb109141c805e79f
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 7c70113149a25e2b0278a5e7ca9bbc330dc66e8a
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 0ec9e1b4fa06ea456fe596f423aad12be5ec5e1a
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 47bb6d8..5cff47e 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -553,9 +553,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;
@@ -566,7 +567,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;
 
@@ -576,14 +576,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;
@@ -636,14 +636,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 {
@@ -724,9 +724,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 a83e5462533f54d0c0105300b1e8687d120b8686
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 fd6a880..47bb6d8 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -425,10 +425,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,
@@ -445,7 +446,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);
@@ -453,18 +454,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 */
@@ -473,13 +474,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);
@@ -697,8 +699,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);
commit 0951d2a9ab22f7fe7839629a8a02057536c75c45
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 7e577a6..fd6a880 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -336,22 +336,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.
@@ -362,14 +363,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();
@@ -382,19 +382,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();
@@ -407,7 +406,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,
@@ -417,12 +416,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 */
@@ -677,8 +676,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 044de7fa7aa0da19ead348094697b2227e882417
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 21ed34d..7e577a6 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1288,15 +1288,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 5a3aa313d4a96944bd9feaea77b8457d7e4e9499
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 c264933..21ed34d 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 977ba306f90618a20fda16b16229c664bad15112
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 d151e00..c264933 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 4fdc3a69fdb17acf6a394d12351b19cd61e17516
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..d151e00 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -899,13 +899,20 @@ _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) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -933,8 +940,10 @@ _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
     *image_rect = surface->extents;
 
     status = _cairo_quartz_get_image (surface, image_out, &data);
-    if (status)
-	return status;
+    if (status) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
 
     *image_extra = data;
 
commit 6e4ff01d0ba40576943c76da638fe0026baab62b
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 ca132774c463f75b11b297c5b2b034ee669115ac
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 f27164c89910430385d21fc8904cedd884f21894
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 e971114..589700e 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -178,30 +178,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)
 {
@@ -268,7 +273,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);
@@ -295,7 +305,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 c00bf48648e27b4bed66edb5054cc6a8545bb2f4
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..e971114 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,25 @@ _cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
     ATSUStyle style;
 
     err = ATSUCreateStyle (&style);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
     err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
                             styleTags, styleSizes, styleValues);
+    if (err != noErr) {
+        ATSUDisposeStyle (style);
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return 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 +309,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 +318,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
     const char *full_name;
 
     err = ATSUCreateStyle(&style);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
 
     switch (toy_face->weight) {
     case CAIRO_FONT_WEIGHT_BOLD:
@@ -375,6 +395,11 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 				       kFontNoPlatformCode,
 				       kFontRomanScript,
 				       kFontNoLanguageCode, &fontID);
+	    if (err != noErr) {
+		ATSUDisposeStyle (style);
+		_cairo_error (CAIRO_STATUS_NO_MEMORY);
+		return CAIRO_STATUS_NO_MEMORY;
+	    }
 	}
     }
 
@@ -387,10 +412,19 @@ _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);
+	    _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return 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 +635,11 @@ _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);
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
 
     _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
 				  scaled_path.path);
@@ -664,6 +703,11 @@ _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) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
     left = metricsH.sideBearing.x - 1.0;
     width = metricsH.deviceAdvance.x 
 	- metricsH.sideBearing.x 
@@ -809,27 +853,49 @@ _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) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto BAIL3;
+    }
 
     err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto BAIL2;
+    }
 
     /* Set the style for all of the text */
     err = ATSUSetRunStyle(textLayout,
 			  font->style, kATSUFromTextBeginning, kATSUToTextEnd);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto BAIL2;
+    }
 
     err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
 							0,
 							kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 							(void *)&layoutRecords,
 							&glyphCount);
+    if (err != noErr) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = 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;
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto BAIL1;
     }
 
     _cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1);
@@ -847,14 +913,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 23b6c2fe9d8223f6b389dff49f99b5ae86706032
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 b7af909c8247642d2ec4dd0b96f20348be6e971a
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 a81ff21d53caa436732a479c2b91c4f3dfe35c93
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 c1464e04c4ae41cb8b353c5a0d18bd5e23ceef39
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 2e76f8b617dfad13e16a8bad70db9ff2f8e43db4
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 198dc3573f2a80accd1ba0c188ea5378f5f99bc5
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 bf67f28746044b6d5a712921c617ba52d31d33e3
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 0368f0d2081b58feea0489e0d29ad413dca6a007
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 03906e1d81b1adace7e5a4668fb449a487812d70
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 886bd8ee9b594478522ebf315f5bc809d837509f
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 3454ef0984299d19e79ceb705a84c4a706704e29
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 a5b74da68bcebaecaa4cbb252bc15b6bec32f847
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 96d0c44ac859727315fc31cadeafdf5bb1b770b8
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 fb62103c7bff66761780ecae6c501ceab3f64c38
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 9457131f8bf9ffe2a4a9178c049d02876f719671
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 4e2a11e0f10702abd5c5144410530e10d1e20a5d
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 d672c26396f6bde7a771beb5d35b3b786c4574b4
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 d5bdb91809bd69e6ed3068d1dc79aac669780e0b
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 1ea1fadf7ec53fcd27b8ed8acd655d913e72e091
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 57bc62a61e6f2dd36c5680d3f486791a968f33ac
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 709292419564ad14025b8b718324d79dd1b7255a
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 9b0a093547aa4b51381baeafd7fcc3029fb140d2
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 fce1a3fdd412128bad9efa75f3565d73e9355e99
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 11d83334ceb063d4b771f6ea47002985d844e244
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 c92dae41445303a4f109dc8a1f69e54b6ca958b7
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 95c49fc..862e14a 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 66add99fb643b1d23642f3115e410c7570702dbb
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 003dc9edabcf181884c3c2cf00c8f81ea9996f4b
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 e544c75f6acf64449d63c2e6bbff70556899317d
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 23278efcdb8ef9307fadccf876819b747d999958
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 1432c9232f5cf6906240fef07968b108bd0a3ef9
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 ce3744f79678f6949af736e40d0d4462da007908
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 c8aff910c417e09d774780ca91877e8b9e409b71
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 578e38eaa794130de1e57b80b60a9bf2e964e9c5
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 849f402b85a2ee7750b8eb767d6722a2489a8b74
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 dc5cda5..95c49fc 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 afda1179721b96e7786260e613a66ffea783ab9b
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;
 }


More information about the cairo-commit mailing list