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

Carl Worth cworth at kemper.freedesktop.org
Wed Nov 21 07:46:41 PST 2007


Rebased ref, commits from common ancestor:
commit 28f58ac4a2d39487cf232912a5960de24324c1e9
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 b7d80d1b86799aaad581d5d2239543566bd46184
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 e798a858b408750cbdfe566c5e371a0b4e280465
Author: Richard Hult <richard at imendio.com>
Date:   Mon Nov 5 10:05:07 2007 +0000

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

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 68bcae4..211cf66 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -221,7 +221,7 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
 
             extents.ascent = metrics.ascent;
             extents.descent = -metrics.descent;
-            extents.height = metrics.capHeight;
+            extents.height = extents.ascent + extents.descent + metrics.leading;
             extents.max_x_advance = metrics.maxAdvanceWidth;
 
             /* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
commit 4b2d2340e6f3bd32ae0f10331084f48759a7ed68
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 cd58243079623fbe072f84e4a603e29e2b47ab21
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 969baba266d070987874f95b2c5769612c7937b9
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 43326e758b8286671a7606b97d622eb52cbe3a7f
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 e14f0e957e0c99bb499ae6fe7a5e6ac9da613f26
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 f28f2c439e60e532712c2adb58eb731fe2eecd58
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 a8e203d02bf57c73087f4d6a940b2548d7e7c8f0
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Oct 20 23:41:46 2007 +0100

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 6df7d87..004b0bf 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -111,6 +111,7 @@ _cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
 					   const cairo_font_options_t *options,
 					   cairo_scaled_font_t **font)
 {
+    cairo_status_t status;
     cairo_atsui_font_face_t *font_face = abstract_face;
     OSStatus err;
     ATSUAttributeTag styleTags[] = { kATSUFontTag };
@@ -119,11 +120,22 @@ _cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
     ATSUStyle style;
 
     err = ATSUCreateStyle (&style);
+    if (err != noErr)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
     err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
                             styleTags, styleSizes, styleValues);
+    if (err != noErr) {
+        ATSUDisposeStyle (style);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-    return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
+    status = _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
 					    font_matrix, ctm, options, font);
+    if (status)
+        ATSUDisposeStyle (style);
+
+    return status;
 }
 
 static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
@@ -294,6 +306,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 			     const cairo_font_options_t *options,
 			     cairo_scaled_font_t **font_out)
 {
+    cairo_status_t status;
     ATSUStyle style;
     ATSUFontID fontID;
     OSStatus err;
@@ -302,6 +315,9 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
     const char *full_name;
 
     err = ATSUCreateStyle(&style);
+    if (err != noErr) {
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     switch (toy_face->weight) {
     case CAIRO_FONT_WEIGHT_BOLD:
@@ -375,6 +391,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 				       kFontNoPlatformCode,
 				       kFontRomanScript,
 				       kFontNoLanguageCode, &fontID);
+	    if (err != noErr) {
+		ATSUDisposeStyle (style);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
 	}
     }
 
@@ -387,10 +407,18 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
 
 	err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
 				styleTags, styleSizes, styleValues);
+	if (err != noErr) {
+	    ATSUDisposeStyle (style);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
     }
 
-    return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
+    status = _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
 					    font_matrix, ctm, options, font_out);
+    if (status)
+	ATSUDisposeStyle (style);
+
+    return status;
 }
 
 static void
@@ -601,6 +629,10 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
 				 lineProc,
 				 curveProc,
 				 closePathProc, (void *)&scaled_path, &err);
+    if (err != noErr) {
+	_cairo_path_fixed_destroy (scaled_path.path);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
 				  scaled_path.path);
@@ -664,6 +696,10 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
     err = ATSUGlyphGetScreenMetrics (scaled_font->style,
 				     1, &theGlyph, 0, false,
 				     false, &metricsH);    
+    if (err != noErr) {
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
     left = metricsH.sideBearing.x - 1.0;
     width = metricsH.deviceAdvance.x 
 	- metricsH.sideBearing.x 
@@ -809,27 +845,44 @@ _cairo_atsui_font_text_to_glyphs (void		*abstract_font,
 
     status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
     if (status)
-	return status;
+	goto BAIL3;
 
     err = ATSUCreateTextLayout(&textLayout);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL3;
+    }
 
     err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     /* Set the style for all of the text */
     err = ATSUSetRunStyle(textLayout,
 			  font->style, kATSUFromTextBeginning, kATSUToTextEnd);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
 							0,
 							kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 							(void *)&layoutRecords,
 							&glyphCount);
+    if (err != noErr) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto BAIL2;
+    }
 
     *num_glyphs = glyphCount - 1;
     *glyphs =
 	(cairo_glyph_t *) _cairo_malloc_ab(*num_glyphs, sizeof (cairo_glyph_t));
     if (*glyphs == NULL) {
-	return CAIRO_STATUS_NO_MEMORY;
+	status = CAIRO_STATUS_NO_MEMORY);
+	goto BAIL1;
     }
 
     _cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1);
@@ -847,14 +900,17 @@ _cairo_atsui_font_text_to_glyphs (void		*abstract_font,
 	(*glyphs)[i].y = y;
     }
 
-    free (utf16);
-
+  BAIL1:
+    /* TODO ignored return value. Is there anything we should do? */
     ATSUDirectReleaseLayoutDataArrayPtr(NULL,
 					kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 					(void *) &layoutRecords);
+  BAIL2:
     ATSUDisposeTextLayout(textLayout);
+  BAIL3:
+    free (utf16);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 ATSUStyle
commit 20427fc6121df15a1268652b313925c6d14a1c03
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 836e651c63f87acf7f489531ddefed71af1a2596
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 73124e86eca3afffca5406db43a99b32c49dae65
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 d5f463d656352bb5f12d6d83d0bc0f42922c4f91
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 8e3382908c2af5d4e092f48141b6f99462886025
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 bd5fe1b71d1d4d2675cfc27d008a8cca2779f2b3
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 a9a5cf8c76d251eb74306714bfbf7f1c3977ec61
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 9fdaeb6173c0a35acb23bf3e376c8db85e82a5fa
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 d8b8c022093a9e4054a5473085c9a5355695042f
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 246c1e50d4a7a816614179b24a7fd8ebf3f67c88
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 a40fafee77a6526d2a5d9becec66025f4a49d047
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 12d9264ddccb74ad228d7c8abb26faf3dc9ae4f2
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 273dde4a70fe0b17268f468b57ef62fa03abb5e8
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 16911b576ac5d1eccd22a28129bace471f28c912
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 5c2a7c2295b1a29b8cf63e1a73609ab87355b40d
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 1fd7173ab42b84c4f741810f2e0be2e3436cb84e
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 887895c92ffc725c39d2c625c2e56a16dd605f8c
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 4010e04b7988ce92276f3bd86415b51f6c198f48
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 68c6603a0ad8235e90374eecf3e6fd1579c944d7
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 46a4170f8ac9d5e9b485bc9b87e6f48375af2043
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 8781e2a5ffeaed31409859be7a28fd8c9e3414aa
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 c2b13f300dd806a4ed75021fd24392ed45f6e405
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 8180f6af64027873be0e47ba4d98c8cebc64761b
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 76553fe56f7e00d8d699118068d1357e15c16651
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 44e5e25e17051fb8052204682da5332ed5f27010
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Aug 28 23:40:18 2007 +0930

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

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

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

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

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

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

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

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

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

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

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

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


More information about the cairo-commit mailing list