b=374462, update cairo to 1.4.2, r=stuart
authorvladimir@pobox.com
Tue, 03 Apr 2007 18:09:15 -0700
changeset 314 479c58f245af4776693efde91b398f99f06bf95a
parent 313 7f2795494f0c01b4b2a518ca2d4cfb4bcf8a4983
child 315 caf13058cc2ef5f1a5fa4ab045517b31cccb883a
push idunknown
push userunknown
push dateunknown
reviewersstuart
bugs374462
milestone1.9a4pre
b=374462, update cairo to 1.4.2, r=stuart
configure.in
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface-private.h
gfx/cairo/cairo/src/cairo-atsui-font.c
gfx/cairo/cairo/src/cairo-bentley-ottmann.c
gfx/cairo/cairo/src/cairo-cff-subset.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-color.c
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-directfb.h
gfx/cairo/cairo/src/cairo-features.h.in
gfx/cairo/cairo/src/cairo-font.c
gfx/cairo/cairo/src/cairo-ft-font.c
gfx/cairo/cairo/src/cairo-glitz-surface.c
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-nquartz-surface.c
gfx/cairo/cairo/src/cairo-nquartz.h
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-os2.h
gfx/cairo/cairo/src/cairo-output-stream.c
gfx/cairo/cairo/src/cairo-paginated-surface.c
gfx/cairo/cairo/src/cairo-path-fill.c
gfx/cairo/cairo/src/cairo-path-fixed-private.h
gfx/cairo/cairo/src/cairo-path-fixed.c
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-path.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-polygon.c
gfx/cairo/cairo/src/cairo-private.h
gfx/cairo/cairo/src/cairo-ps-surface.c
gfx/cairo/cairo/src/cairo-quartz-private.h
gfx/cairo/cairo/src/cairo-quartz-surface.c
gfx/cairo/cairo/src/cairo-quartz.h
gfx/cairo/cairo/src/cairo-rename.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-skiplist-private.h
gfx/cairo/cairo/src/cairo-skiplist.c
gfx/cairo/cairo/src/cairo-slope.c
gfx/cairo/cairo/src/cairo-spline.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset-private.h
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xlib-private.h
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/test-fallback-surface.c
gfx/cairo/cairo/src/test-fallback-surface.h
gfx/cairo/cairo/src/test-meta-surface.c
gfx/cairo/cairo/src/test-meta-surface.h
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/cairo/src/test-paginated-surface.h
gfx/cairo/libpixman/src/fbcompose.c
gfx/cairo/libpixman/src/fbmmx.c
gfx/cairo/libpixman/src/fbpict.c
gfx/cairo/libpixman/src/fbtrap.c
gfx/cairo/libpixman/src/icimage.c
gfx/cairo/libpixman/src/icimage.h
gfx/cairo/libpixman/src/icint.h
gfx/cairo/libpixman/src/pixman-remap.h
gfx/cairo/libpixman/src/pixman.h
gfx/cairo/libpixman/src/slim_internal.h
gfx/src/thebes/nsThebesDeviceContext.cpp
gfx/thebes/public/gfxASurface.h
gfx/thebes/public/gfxQuartzSurface.h
gfx/thebes/src/gfxASurface.cpp
gfx/thebes/src/gfxMatrix.cpp
gfx/thebes/src/gfxQuartzPDFSurface.cpp
gfx/thebes/src/gfxQuartzSurface.cpp
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsDeviceContextSpecX.mm
widget/src/cocoa/nsNativeThemeCocoa.mm
--- a/configure.in
+++ b/configure.in
@@ -7243,17 +7243,16 @@ if test "$MOZ_SVG" -o "$MOZ_ENABLE_CANVA
            PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
            PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
            FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
            MOZ_ENABLE_CAIRO_FT=1
            CAIRO_FT_CFLAGS="$FT2_CFLAGS"
        fi
        if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
            QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
-           NQUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_NQUARTZ_SURFACE 1"
            ATSUI_FONT_FEATURE="#define CAIRO_HAS_ATSUI_FONT 1"
        fi
        if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
            WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
            WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
            PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
        fi
        if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,15 +2,25 @@ Snapshots of cairo and glitz for mozilla
 
 We only include the relevant parts of each release (generally, src/*.[ch]),
 as we have Makefile.in's that integrate into the Mozilla build system.  For
 documentation and similar, please see the official tarballs at
 http://www.cairographics.org/.
 
 VERSIONS:
 
-  cairo (1.3.12 tagged snapshot)
+  cairo (1.4.2)
   glitz 0.5.2 (cvs - 2006-01-10)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
+==== Patches ====
+
+All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined).
+
+Some specific things:
+
+max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
+
+fbcompose-bandaid.patch: Disable "optimized" code in non-MMX case due to bugs
+
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -124,21 +124,16 @@ endif
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 CSRCS   += cairo-os2-surface.c
 EXPORTS += cairo-os2.h cairo-os2-private.h
 endif
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 CSRCS   += cairo-quartz-surface.c cairo-atsui-font.c
 EXPORTS += cairo-quartz.h cairo-atsui.h
-
-ifdef MOZ_ENABLE_CAIRO_GFX
-CSRCS   += cairo-nquartz-surface.c
-EXPORTS += cairo-nquartz.h
-endif
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 CPPSRCS += cairo-beos-surface.cpp
 EXPORTS += cairo-beos.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -1,9 +1,9 @@
-/* $Id: cairo-analysis-surface-private.h,v 1.4 2007/04/03 18:59:47 vladimir%pobox.com Exp $
+/* $Id: cairo-analysis-surface-private.h,v 1.5 2007/04/04 01:09:15 vladimir%pobox.com Exp $
  *
  * Copyright © 2005 Keith Packard
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
--- a/gfx/cairo/cairo/src/cairo-atsui-font.c
+++ b/gfx/cairo/cairo/src/cairo-atsui-font.c
@@ -77,16 +77,19 @@ static cairo_status_t _cairo_atsui_font_
 						       cairo_scaled_font_t **font_out);
 
 struct _cairo_atsui_font {
     cairo_scaled_font_t base;
 
     ATSUStyle style;
     ATSUStyle unscaled_style;
     ATSUFontID fontID;
+
+    Fixed size;
+    CGAffineTransform font_matrix;
 };
 
 struct _cairo_atsui_font_face {
   cairo_font_face_t base;
   ATSUFontID font_id;
 };
 
 struct _cairo_atsui_scaled_path {
@@ -141,88 +144,37 @@ cairo_atsui_font_face_create_for_atsu_fo
 
   font_face->font_id = font_id;
 
     _cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend);
 
     return &font_face->base;
 }
 
-static CGContextRef
-CGBitmapContextCreateWithCairoImageSurface (const cairo_image_surface_t * surface)
-{
-    CGContextRef contextRef;
-    CGColorSpaceRef colorSpace;
-    int bits_per_comp, alpha;
-
-    /* Create a CGBitmapContext for the dest surface for drawing into */
-    if (surface->depth == 1) {
-	colorSpace = CGColorSpaceCreateDeviceGray ();
-	bits_per_comp = 1;
-	alpha = kCGImageAlphaNone;
-    } else if (surface->depth == 8) {
-	colorSpace = CGColorSpaceCreateDeviceGray ();
-	bits_per_comp = 8;
-	alpha = kCGImageAlphaNone;
-    } else if (surface->depth == 24) {
-	colorSpace = CGColorSpaceCreateDeviceRGB ();
-	bits_per_comp = 8;
-	alpha = kCGImageAlphaNoneSkipFirst | CG_BITMAP_BYTE_ORDER_FLAG;
-    } else if (surface->depth == 32) {
-	colorSpace = CGColorSpaceCreateDeviceRGB ();
-	bits_per_comp = 8;
-	alpha = kCGImageAlphaPremultipliedFirst | CG_BITMAP_BYTE_ORDER_FLAG;
-    } else {
-	/* not reached */
-	return NULL;
-    }
-    
-    contextRef = CGBitmapContextCreate (surface->data,
-					surface->width,
-					surface->height,
-					bits_per_comp,
-					surface->stride,
-					colorSpace,
-					alpha);
-    CGColorSpaceRelease (colorSpace);
-
-    return contextRef;
-}
-
 static CGAffineTransform
 CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
 {
     return CGAffineTransformMake(scale->xx, scale->yx,
                                  scale->xy, scale->yy,
                                  0, 0);
 }
 
-static CGAffineTransform
-CGAffineTransformMakeWithCairoScaleFactors(const cairo_matrix_t *scale)
-{
-    double xscale = 1.0;
-    double yscale = 1.0;
-    _cairo_matrix_compute_scale_factors(scale, &xscale, &yscale, 1);
-    return CGAffineTransformMake(xscale, 0,
-                                 0, yscale,
-                                 0, 0);
-}
-
 static ATSUStyle
-CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
+CreateSizedCopyOfStyle(ATSUStyle inStyle, 
+		       const Fixed *theSize, 
+		       const CGAffineTransform *theTransform)
 {
     ATSUStyle style;
     OSStatus err;
-
-    /* Set the style's size */
-    Fixed theSize = FloatToFixed(1.0);
-    CGAffineTransform theTransform = CGAffineTransformMakeWithCairoScaleFactors(scale);
-    const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, kATSUFontMatrixTag };
-    const ByteCount theFontStyleSizes[] = { sizeof(Fixed), sizeof(CGAffineTransform) };
-    ATSUAttributeValuePtr theFontStyleValues[] = { &theSize, &theTransform };
+    const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, 
+						  kATSUFontMatrixTag };
+    const ByteCount theFontStyleSizes[] = { sizeof(Fixed), 
+					    sizeof(CGAffineTransform) };
+    ATSUAttributeValuePtr theFontStyleValues[] = { (Fixed *)theSize, 
+						   (CGAffineTransform *)theTransform };
 
     err = ATSUCreateAndCopyStyle(inStyle, &style);
 
     err = ATSUSetAttributes(style,
                             sizeof(theFontStyleTags) /
                             sizeof(ATSUAttributeTag), theFontStyleTags,
                             theFontStyleSizes, theFontStyleValues);
 
@@ -268,25 +220,34 @@ static cairo_status_t
 				 const cairo_matrix_t *font_matrix,
 				 const cairo_matrix_t *ctm,
 				 const cairo_font_options_t *options,
 				 cairo_scaled_font_t **font_out)
 {
     cairo_atsui_font_t *font = NULL;
     OSStatus err;
     cairo_status_t status;
+    double xscale = 1.0;
+    double yscale = 1.0;
 
     font = malloc(sizeof(cairo_atsui_font_t));
     if (font == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
     _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
 			    &cairo_atsui_scaled_font_backend);
 
-    font->style = CreateSizedCopyOfStyle(style, &font->base.scale);
+    _cairo_matrix_compute_scale_factors (&font->base.scale, 
+					 &xscale, &yscale, 1);
+    font->font_matrix = CGAffineTransformMake (1., 0.,
+					       0., yscale/xscale,
+					       0., 0.);
+    font->size = FloatToFixed (xscale);
+
+    font->style = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix);
 
     {
 	Fixed theSize = FloatToFixed(1.0);
 	const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
 	const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
 	ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
 
 	err = ATSUSetAttributes(style,
@@ -475,40 +436,55 @@ static
 OSStatus _close_path_for_metrics(void *callback_data)
 {
     CGMutablePathRef path = callback_data;
 
     CGPathCloseSubpath (path);
     return noErr;
 }
 
+static GlyphID 
+_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
+    unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
+    if (index > 0xffff) 
+	return kATSDeletedGlyphcode;
+    return index;
+}
+
 static cairo_status_t
 _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
 				      cairo_scaled_glyph_t *scaled_glyph)
 {
-    cairo_text_extents_t extents;
+    cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
     OSStatus err, callback_err;
     ATSGlyphScreenMetrics metricsH;
     static ATSCubicMoveToUPP moveProc = NULL;
     static ATSCubicLineToUPP lineProc = NULL;
     static ATSCubicCurveToUPP curveProc = NULL;
     static ATSCubicClosePathUPP closePathProc = NULL;
     CGMutablePathRef path;
-    GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
+    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
     double xscale, yscale;
     CGRect rect;
 
+    if (theGlyph == kATSDeletedGlyphcode) {
+	_cairo_scaled_glyph_set_metrics (scaled_glyph,
+					 &scaled_font->base,
+					 &extents);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     /* We calculate the advance from the screen metrics. We
      * could probably take this from the glyph path.
      */
     err = ATSUGlyphGetScreenMetrics (scaled_font->style,
 				     1, &theGlyph, 0, false,
 				     false, &metricsH);
     if (err != noErr)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return CAIRO_STATUS_NO_MEMORY;
 
     /* Scale down to font units.*/
     _cairo_matrix_compute_scale_factors (&scaled_font->base.scale,
 					 &xscale, &yscale, 1);
     xscale = 1.0/xscale;
     yscale = 1.0/yscale;
 
     extents.x_advance = metricsH.deviceAdvance.x * xscale;
@@ -527,21 +503,18 @@ static cairo_status_t
      * Its only meaningful if err != noErr, and we don't currently
      * use it for anything.
      */
     err = ATSUGlyphGetCubicPaths (scaled_font->style, theGlyph,
 				  moveProc, lineProc, curveProc, closePathProc,
 				  (void *)path, &callback_err);
 
     if (err != noErr) {
-	/* This could potentially happen for bitmap fonts, where
-	 * no paths are available.
-	 */
 	CGPathRelease (path);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return CAIRO_STATUS_NO_MEMORY;
     }
 
     rect = CGPathGetBoundingBox (path);
 
     extents.x_bearing = rect.origin.x * xscale;
     extents.y_bearing = rect.origin.y * yscale;
     extents.width = rect.size.width * xscale;
     extents.height = rect.size.height * yscale;
@@ -631,46 +604,55 @@ static OSStatus
 static cairo_status_t
 _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
 					  cairo_scaled_glyph_t *scaled_glyph)
 {
     static ATSCubicMoveToUPP moveProc = NULL;
     static ATSCubicLineToUPP lineProc = NULL;
     static ATSCubicCurveToUPP curveProc = NULL;
     static ATSCubicClosePathUPP closePathProc = NULL;
+    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
     OSStatus err;
     cairo_atsui_scaled_path_t scaled_path;
     cairo_matrix_t *font_to_device = &scaled_font->base.scale;
     cairo_matrix_t unscaled_font_to_device;
     double xscale;
     double yscale;
     
+    scaled_path.path = _cairo_path_fixed_create ();
+    if (!scaled_path.path)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    if (theGlyph == kATSDeletedGlyphcode) {
+	_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
+				      scaled_path.path);
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     /* extract the rotation/shear component of the scale matrix. */
     _cairo_matrix_compute_scale_factors (font_to_device, &xscale, &yscale, 1);
     cairo_matrix_init (&unscaled_font_to_device, 
 		      font_to_device->xx, 
 		      font_to_device->yx, 
 		      font_to_device->xy, 
 		      font_to_device->yy, 0., 0.);
     cairo_matrix_scale (&unscaled_font_to_device, 1.0/xscale, 1.0/yscale);
 
     scaled_path.scale = &unscaled_font_to_device;
-    scaled_path.path = _cairo_path_fixed_create ();
-    if (!scaled_path.path)
-	return CAIRO_STATUS_NO_MEMORY;
 
     if (moveProc == NULL) {
         moveProc = NewATSCubicMoveToUPP(_move_to);
         lineProc = NewATSCubicLineToUPP(_line_to);
         curveProc = NewATSCubicCurveToUPP(_curve_to);
         closePathProc = NewATSCubicClosePathUPP(_close_path);
     }
 
     err = ATSUGlyphGetCubicPaths(scaled_font->style,
-				 _cairo_scaled_glyph_index (scaled_glyph),
+				 theGlyph,
 				 moveProc,
 				 lineProc,
 				 curveProc,
 				 closePathProc, (void *)&scaled_path, &err);
 
     _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
 				  scaled_path.path);
 
@@ -686,24 +668,34 @@ static cairo_status_t
     cairo_image_surface_t *surface;
     cairo_format_t format;
 
     ATSFontRef atsFont;
     CGFontRef cgFont;
     cairo_scaled_font_t base = scaled_font->base;
     cairo_font_extents_t extents = base.extents;
 
-    GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
+    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
     ATSGlyphScreenMetrics metricsH;
     double left, bottom, width, height;
     double xscale, yscale;
     CGRect bbox;
     CGAffineTransform transform;
 
 
+    if (theGlyph == kATSDeletedGlyphcode) {
+	surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
+	if (!surface)
+	    return CAIRO_STATUS_NO_MEMORY;
+	_cairo_scaled_glyph_set_surface (scaled_glyph,
+					 &base,
+					 surface);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     /* Compute a box to contain the glyph mask. The vertical
      * sizes come from the font extents; extra pixels are 
      * added to account for fractional sizes.
      */
     height = extents.ascent + extents.descent + 2.0;
     bottom = -extents.descent - 1.0;
 
     /* Horizontal sizes come from the glyph typographic metrics.
@@ -749,20 +741,33 @@ static cairo_status_t
     /* XXX should we select format based on antialiasing flags, as ft does? */
     format = CAIRO_FORMAT_A8;
 
     /* create the glyph mask surface */
     surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
     if (!surface)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    drawingContext = CGBitmapContextCreateWithCairoImageSurface (surface);
+    /* Create a CGBitmapContext for the dest surface for drawing into */
+    {
+	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray ();
+    
+	drawingContext = CGBitmapContextCreate (surface->data,
+						surface->width,
+						surface->height,
+						8,
+						surface->stride,
+						colorSpace,
+						kCGImageAlphaNone);
+	CGColorSpaceRelease (colorSpace);
+    }
+
     if (!drawingContext) {
 	cairo_surface_destroy ((cairo_surface_t *)surface);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return CAIRO_STATUS_NO_MEMORY;
     }
     
     atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
     cgFont = CGFontCreateWithPlatformFont (&atsFont);
 
     CGContextSetFont (drawingContext, cgFont);
 
     if (base.options.antialias ==  CAIRO_ANTIALIAS_NONE) {
@@ -834,16 +839,19 @@ static cairo_int_status_t
     uint16_t *utf16;
     int n16;
     OSStatus err;
     ATSUTextLayout textLayout;
     ATSLayoutRecord *layoutRecords;
     cairo_atsui_font_t *font = abstract_font;
     ItemCount glyphCount;
     int i;
+    CGPoint point;
+    double xscale, yscale;
+    CGAffineTransform device_to_user_scale;
 
     status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
     if (status)
 	return status;
 
     err = ATSUCreateTextLayout(&textLayout);
 
     err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
@@ -860,202 +868,85 @@ static cairo_int_status_t
 
     *num_glyphs = glyphCount - 1;
     *glyphs =
 	(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
     if (*glyphs == NULL) {
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
+    _cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1);
+    device_to_user_scale = 
+	CGAffineTransformInvert (CGAffineTransformMake (xscale, 0,
+							0, yscale,
+							0, 0));
     for (i = 0; i < *num_glyphs; i++) {
 	(*glyphs)[i].index = layoutRecords[i].glyphID;
-	(*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos);
+	/* ATSLayoutRecord.realPos is in device units, convert to user units */
+	point = CGPointMake (FixedToFloat (layoutRecords[i].realPos), 0);
+	point = CGPointApplyAffineTransform (point, device_to_user_scale);
+
+	(*glyphs)[i].x = x + point.x;
 	(*glyphs)[i].y = y;
     }
 
     free (utf16);
 
     ATSUDirectReleaseLayoutDataArrayPtr(NULL,
 					kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
 					(void *) &layoutRecords);
     ATSUDisposeTextLayout(textLayout);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_int_status_t
-_cairo_atsui_font_old_show_glyphs (void		       *abstract_font,
-				   cairo_operator_t    	op,
-				   cairo_pattern_t     *pattern,
-				   cairo_surface_t     *generic_surface,
-				   int                 	source_x,
-				   int                 	source_y,
-				   int			dest_x,
-				   int			dest_y,
-				   unsigned int		width,
-				   unsigned int		height,
-				   cairo_glyph_t       *glyphs,
-				   int                 	num_glyphs)
-{
-    cairo_atsui_font_t *font = abstract_font;
-    CGContextRef drawingContext;
-    cairo_image_surface_t *destImageSurface;
-    int i;
-    void *extra = NULL;
-    cairo_bool_t can_draw_directly;
-    cairo_rectangle_int16_t rect;
-    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
-
-    ATSFontRef atsFont;
-    CGFontRef cgFont;
-    CGAffineTransform textTransform;
-
-    if (!_cairo_surface_is_quartz (generic_surface))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Check if we can draw directly to the destination surface */
-    can_draw_directly = _cairo_pattern_is_opaque_solid (pattern) &&
-	op == CAIRO_OPERATOR_OVER;
-
-    if (!can_draw_directly) {
-	rect.x = dest_x;
-	rect.y = dest_y;
-	rect.width = width;
-	rect.height = height;
-
-	_cairo_surface_acquire_dest_image(generic_surface,
-					  &rect,
-					  &destImageSurface,
-					  &rect,
-					  &extra);
-
-	drawingContext = CGBitmapContextCreateWithCairoImageSurface (destImageSurface);
-	if (!drawingContext) 
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	CGContextTranslateCTM(drawingContext, 0, destImageSurface->height);
-	CGContextScaleCTM(drawingContext, 1.0f, -1.0f);
-    } else {
-	drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
-	CGContextSaveGState (drawingContext);
-    }
-
-    atsFont = FMGetATSFontRefFromFont(font->fontID);
-    cgFont = CGFontCreateWithPlatformFont(&atsFont);
-
-    CGContextSetFont(drawingContext, cgFont);
-
-    if (font->base.options.antialias ==  CAIRO_ANTIALIAS_NONE) {
-	CGContextSetShouldAntialias (drawingContext, false);
-    }
-
-    textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
-    textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
-
-    CGContextSetFontSize(drawingContext, 1.0);
-    CGContextSetTextMatrix(drawingContext, textTransform);
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
-	_cairo_pattern_is_opaque_solid(pattern))
-    {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
-	CGContextSetRGBFillColor(drawingContext,
-				 solid->color.red,
-				 solid->color.green,
-				 solid->color.blue, 1.0f);
-    } else {
-	CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
-    }
-
-    if (surface->clip_region) {
-	pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
-	int num_boxes = pixman_region_num_rects (surface->clip_region);
-	CGRect stack_rects[10];
-	CGRect *rects;
-	int i;
-	
-	/* XXX: Return-value of malloc needs to be checked for
-	 * NULL. Can someone fix this who is more familiar with
-	 * the cleanup needed in this function?
-	 */
-	if (num_boxes > 10)
-	    rects = malloc (sizeof (CGRect) * num_boxes);
-	else
-	    rects = stack_rects;
-	
-	for (i = 0; i < num_boxes; i++) {
-	    rects[i].origin.x = boxes[i].x1;
-	    rects[i].origin.y = boxes[i].y1;
-	    rects[i].size.width = boxes[i].x2 - boxes[i].x1;
-	    rects[i].size.height = boxes[i].y2 - boxes[i].y1;
-	}
-	
-	CGContextClipToRects (drawingContext, rects, num_boxes);
-	
-	if (rects != stack_rects)
-	    free(rects);
-    }
-
-    /* TODO - bold and italic text
-     *
-     * We could draw the text using ATSUI and get bold, italics
-     * etc. for free, but ATSUI does a lot of text layout work
-     * that we don't really need...
-     */
-
-    for (i = 0; i < num_glyphs; i++) {
-        CGGlyph theGlyph = glyphs[i].index;
-
-	/* round glyph locations to the nearest pixel */
-	/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
-        CGContextShowGlyphsAtPoint(drawingContext,
-				   _cairo_lround (glyphs[i].x),
-				   _cairo_lround (glyphs[i].y),
-                                   &theGlyph, 1);
-    }
-
-    if (!can_draw_directly) {
-	CGContextRelease(drawingContext);
-
-	_cairo_surface_release_dest_image(generic_surface,
-					  &rect,
-					  destImageSurface,
-					  &rect,
-					  extra);
-    } else {
-      CGContextRestoreGState (drawingContext);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_bool_t
-_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont)
-{
-    return (sfont->backend == &cairo_atsui_scaled_font_backend);
-}
-
 ATSUStyle
 _cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont)
 {
     cairo_atsui_font_t *afont = (cairo_atsui_font_t *) sfont;
 
     return afont->style;
 }
 
 ATSUFontID
 _cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont)
 {
     cairo_atsui_font_t *afont = (cairo_atsui_font_t *) sfont;
 
     return afont->fontID;
 }
 
+static cairo_int_status_t
+_cairo_atsui_load_truetype_table (void	           *abstract_font,
+				  unsigned long     tag,
+				  long              offset,
+				  unsigned char    *buffer,
+				  unsigned long    *length)
+{
+    cairo_atsui_font_t *scaled_font = abstract_font;
+    ATSFontRef atsFont;
+    OSStatus err;
+	
+    atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
+    err = ATSFontGetTable ( atsFont, tag,
+			    (ByteOffset) offset,
+			    (ByteCount) *length,
+			    buffer,
+			    length);
+    if (err != noErr) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
     CAIRO_FONT_TYPE_ATSUI,
     _cairo_atsui_font_create_toy,
     _cairo_atsui_font_fini,
     _cairo_atsui_font_scaled_glyph_init,
     _cairo_atsui_font_text_to_glyphs,
     NULL, /* ucs4_to_index */
-    _cairo_atsui_font_old_show_glyphs,
+    NULL, /* show_glyphs */
+    _cairo_atsui_load_truetype_table,
+    NULL, /* map_glyphs_to_unicode */
 };
 
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -116,27 +116,27 @@ typedef struct _cairo_bo_event {
     cairo_bo_edge_t *e2;
     cairo_bo_point32_t point;
     skip_elt_t elt;
 } cairo_bo_event_t;
 
 #define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
 
 typedef struct _cairo_bo_event_queue {
-    skip_list_t intersection_queue;
+    cairo_skip_list_t intersection_queue;
 
     cairo_bo_event_t *startstop_events;
     cairo_bo_event_t **sorted_startstop_event_ptrs;
     unsigned next_startstop_event_index;
     unsigned num_startstop_events;
 } cairo_bo_event_queue_t;
 
-/* This structure extends skip_list_t, which must come first. */
+/* This structure extends cairo_skip_list_t, which must come first. */
 typedef struct _cairo_bo_sweep_line {
-    skip_list_t active_edges;
+    cairo_skip_list_t active_edges;
     cairo_bo_edge_t *head;
     cairo_bo_edge_t *tail;
     int32_t current_y;
 } cairo_bo_sweep_line_t;
 
 static inline int
 _cairo_bo_point32_compare (cairo_bo_point32_t const *a,
 			   cairo_bo_point32_t const *b)
@@ -692,26 +692,26 @@ static void
     event->point = point;
 }
 
 static void
 _cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
 			      cairo_bo_event_t	     *event)
 {
     /* Don't insert if there's already an equivalent intersection event in the queue. */
-    skip_list_insert (&queue->intersection_queue, event,
+    _cairo_skip_list_insert (&queue->intersection_queue, event,
 		      event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
 }
 
 static void
 _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
 			      cairo_bo_event_t	     *event)
 {
     if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
-	skip_list_delete_given ( &queue->intersection_queue, &event->elt );
+	_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
 }
 
 static cairo_bo_event_t *
 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
 {
     skip_elt_t *elt = event_queue->intersection_queue.chains[0];
     cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
     cairo_bo_event_t *startstop;
@@ -735,17 +735,17 @@ static cairo_status_t
 			    int				 num_edges)
 {
     int i;
     cairo_bo_event_t *events, **sorted_event_ptrs;
     unsigned num_events = 2*num_edges;
 
     memset (event_queue, 0, sizeof(*event_queue));
 
-    skip_list_init (&event_queue->intersection_queue,
+    _cairo_skip_list_init (&event_queue->intersection_queue,
 		    cairo_bo_event_compare_abstract,
 		    sizeof (cairo_bo_event_t));
     if (0 == num_edges)
 	return CAIRO_STATUS_SUCCESS;
 
     /* The skip_elt_t field of a cairo_bo_event_t isn't used for start
      * or stop events, so this allocation is safe.  XXX: make the
      * event type a union so it doesn't always contain the skip
@@ -784,17 +784,17 @@ static cairo_status_t
 	   sizeof(cairo_bo_event_t *),
 	   cairo_bo_event_compare_pointers);
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
 {
-    skip_list_fini (&event_queue->intersection_queue);
+    _cairo_skip_list_fini (&event_queue->intersection_queue);
     if (event_queue->startstop_events)
 	free (event_queue->startstop_events);
     if (event_queue->sorted_startstop_event_ptrs)
 	free (event_queue->sorted_startstop_event_ptrs);
 }
 
 static void
 _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t	*event_queue,
@@ -829,39 +829,39 @@ static void
 			  intersection);
 
     _cairo_bo_event_queue_insert (event_queue, &event);
 }
 
 static void
 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
 {
-    skip_list_init (&sweep_line->active_edges,
+    _cairo_skip_list_init (&sweep_line->active_edges,
 		    _sweep_line_elt_compare,
 		    sizeof (sweep_line_elt_t));
     sweep_line->head = NULL;
     sweep_line->tail = NULL;
     sweep_line->current_y = 0;
 }
 
 static void
 _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
 {
-    skip_list_fini (&sweep_line->active_edges);
+    _cairo_skip_list_fini (&sweep_line->active_edges);
 }
 
 static void
 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t		*edge)
 {
     skip_elt_t *next_elt;
     sweep_line_elt_t *sweep_line_elt;
     cairo_bo_edge_t **prev_of_next, **next_of_prev;
 
-    sweep_line_elt = skip_list_insert (&sweep_line->active_edges, &edge,
+    sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
 				       1 /* unique inserts*/);
 
     next_elt = sweep_line_elt->elt.next[0];
     if (next_elt)
 	prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev);
     else
 	prev_of_next = &sweep_line->tail;
 
@@ -879,17 +879,17 @@ static void
 }
 
 static void
 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t	*edge)
 {
     cairo_bo_edge_t **left_next, **right_prev;
 
-    skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
+    _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
 
     left_next = &sweep_line->head;
     if (edge->prev)
 	left_next = &edge->prev->next;
 
     right_prev = &sweep_line->tail;
     if (edge->next)
 	right_prev = &edge->next->prev;
@@ -970,17 +970,17 @@ static void
     printf ("\n");
 }
 
 static void
 _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue)
 {
     skip_elt_t *elt;
     /* XXX: fixme to print the start/stop array too. */
-    skip_list_t *queue = &event_queue->intersection_queue;
+    cairo_skip_list_t *queue = &event_queue->intersection_queue;
     cairo_bo_event_t *event;
 
     printf ("Event queue:\n");
 
     for (elt = queue->chains[0];
 	 elt;
 	 elt = elt->next[0])
     {
@@ -1762,17 +1762,17 @@ run_test (const char		*test_name,
 }
 
 #define MAX_RANDOM 300
 
 int
 main (void)
 {
     char random_name[] = "random-XX";
-    static cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
+    cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
     unsigned int i, num_random;
     test_t *test;
 
     for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) {
 	test = &tests[i];
 	run_test (test->name, test->edges, test->num_edges);
     }
 
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -26,16 +26,17 @@
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Adrian Johnson.
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
+ *      Eugeniy Meshcheryakov <eugen@debian.org>
  */
 
 #include "cairoint.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 
 /* CFF Dict Operators. If the high byte is 0 the command is encoded
  * with a single byte. */
@@ -76,16 +77,23 @@ typedef struct _cff_dict_operator {
     cairo_hash_entry_t base;
 
     unsigned short operator;
     unsigned char *operand;
     int            operand_length;
     int            operand_offset;
 } cff_dict_operator_t;
 
+typedef struct _cff_charset {
+    cairo_bool_t         is_builtin;
+    const uint16_t      *sids;
+    const unsigned char *data;
+    int                  length;
+} cff_charset_t;
+
 typedef struct _cairo_cff_font {
 
     cairo_scaled_font_subset_t *scaled_font_subset;
     const cairo_scaled_font_backend_t *backend;
 
     /* Font Data */
     unsigned char       *data;
     unsigned long        data_length;
@@ -95,58 +103,33 @@ typedef struct _cairo_cff_font {
     char                *font_name;
     cairo_hash_table_t  *top_dict;
     cairo_hash_table_t  *private_dict;
     cairo_array_t        strings_index;
     cairo_array_t        charstrings_index;
     cairo_array_t        global_sub_index;
     cairo_array_t        local_sub_index;
     int                  num_glyphs;
+    cff_charset_t        charset;
+    int                  charset_offset;
 
     /* Subsetted Font Data */
     char                *subset_font_name;
     cairo_array_t        charstrings_subset_index;
     cairo_array_t        strings_subset_index;
+    cairo_array_t        charset_subset;
     cairo_array_t        output;
 
     /* Subset Metrics */
     int                 *widths;
     int                  x_min, y_min, x_max, y_max;
     int                  ascent, descent;
 
 } cairo_cff_font_t;
 
-#ifdef WORDS_BIGENDIAN
-
-#define cpu_to_be16(v) (v)
-#define be16_to_cpu(v) (v)
-#define cpu_to_be32(v) (v)
-
-#else
-
-static inline uint16_t
-cpu_to_be16(uint16_t v)
-{
-    return (v << 8) | (v >> 8);
-}
-
-static inline uint16_t
-be16_to_cpu(uint16_t v)
-{
-    return cpu_to_be16 (v);
-}
-
-static inline uint32_t
-cpu_to_be32(uint32_t v)
-{
-    return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
-}
-
-#endif
-
 /* Encoded integer using maximum sized encoding. This is required for
  * operands that are later modified after encoding. */
 static unsigned char *
 encode_integer_max (unsigned char *p, int i)
 {
     *p++ = 29;
     *p++ = i >> 24;
     *p++ = (i >> 16) & 0xff;
@@ -500,30 +483,16 @@ cff_dict_read (cairo_hash_table_t *dict,
     }
 
 fail:
     _cairo_array_fini (&operands);
 
     return status;
 }
 
-static void
-cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
-{
-    cff_dict_operator_t key, *op;
-
-    _cairo_dict_init_key (&key, operator);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
-    {
-        free (op->operand);
-        _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
-    }
-}
-
 static unsigned char *
 cff_dict_get_operands (cairo_hash_table_t *dict,
                        unsigned short      operator,
                        int                *size)
 {
     cff_dict_operator_t key, *op;
 
     _cairo_dict_init_key (&key, operator);
@@ -737,22 +706,29 @@ cairo_cff_font_read_top_dict (cairo_cff_
         goto fail;
     font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
 
     operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
     operand = decode_integer (operand, &size);
     decode_integer (operand, &offset);
     cairo_cff_font_read_private_dict (font, font->data + offset, size);
 
-    cff_dict_remove (font->top_dict, CHARSET_OP);
+    operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size);
+    if (!operand)
+      font->charset_offset = 0;
+    else {
+      decode_integer (operand, &offset);
+      font->charset_offset = offset;
+    }
 
     /* Use maximum sized encoding to reserve space for later modification. */
     end_buf = encode_integer_max (buf, 0);
     cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
     cff_dict_set_operands (font->top_dict, ENCODING_OP, buf, end_buf - buf);
+    cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
     /* Private has two operands - size and offset */
     end_buf = encode_integer_max (end_buf, 0);
     cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
 
 fail:
     cff_index_fini (&index);
 
     return status;
@@ -765,25 +741,159 @@ cairo_cff_font_read_strings (cairo_cff_f
 }
 
 static cairo_int_status_t
 cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
 {
     return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
 }
 
+static cairo_int_status_t
+cff_charset_read_data (cff_charset_t *charset, const unsigned char *data,
+	const unsigned char *data_end, int num_glyphs)
+{
+    const unsigned char *p = data;
+
+    num_glyphs -= 1; /* do not count .notdef */
+
+    if (p + 1 > data_end)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    switch (*p++) {
+    case 0:
+	if (p + num_glyphs*2 > data_end)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	charset->is_builtin = FALSE;
+	charset->data = data;
+	charset->length = num_glyphs * 2 + 1;
+	break;
+    case 1:
+	while (num_glyphs > 0) {
+	    if (p + 3 > data_end)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	    num_glyphs -= p[2] + 1;
+	    p += 3;
+	}
+	if (num_glyphs < 0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	charset->is_builtin = FALSE;
+	charset->data = data;
+	charset->length = p - data;
+	break;
+    case 2:
+	while (num_glyphs > 0) {
+	    if (p + 4 > data_end)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	    num_glyphs -= be16_to_cpu(*(uint16_t *)(p + 2)) + 1;
+	    p += 4;
+	}
+	if (num_glyphs < 0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	charset->is_builtin = FALSE;
+	charset->data = data;
+	charset->length = p - data;
+	break;
+    default:
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static const uint16_t ISOAdobe_charset[] = {
+    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+    45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+    59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+    73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+    87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+    101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+    123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+    134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+    145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+    156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+    167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+    178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+    189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+    200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
+    211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+    222, 223, 224, 225, 226, 227, 228,
+};
+
+static const uint16_t Expert_charset[] = {
+    1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13,
+    14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+    248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+    258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
+    267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+    278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+    289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+    300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
+    311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163,
+    319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169,
+    327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
+    338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+    349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
+    360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
+    371, 372, 373, 374, 375, 376, 377, 378,
+};
+
+static const uint16_t ExpertSubset_charset[] = {
+    1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240,
+    241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
+    251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
+    263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
+    300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321,
+    322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
+    330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
+    341, 342, 343, 344, 345, 346,
+};
+
+static cairo_int_status_t
+cairo_cff_font_read_charset (cairo_cff_font_t *font)
+{
+    switch (font->charset_offset) {
+    case 0:
+	/* ISOAdobe charset */
+	font->charset.is_builtin = TRUE;
+        font->charset.sids = ISOAdobe_charset;
+        font->charset.length = sizeof (ISOAdobe_charset);
+	return CAIRO_STATUS_SUCCESS;
+    case 1:
+	/* Expert charset */
+	font->charset.is_builtin = TRUE;
+        font->charset.sids = Expert_charset;
+        font->charset.length = sizeof (Expert_charset);
+	return CAIRO_STATUS_SUCCESS;
+    case 2:
+	/* ExpertSubset charset */;
+	font->charset.is_builtin = TRUE;
+        font->charset.sids = ExpertSubset_charset;
+        font->charset.length = sizeof (ExpertSubset_charset);
+	return CAIRO_STATUS_SUCCESS;
+    default:
+	break;
+    }
+    return cff_charset_read_data (&font->charset, font->data + (unsigned)font->charset_offset,
+	    font->data_end, font->num_glyphs);
+}
+
 typedef cairo_int_status_t
 (*font_read_t) (cairo_cff_font_t *font);
 
 static const font_read_t font_read_funcs[] = {
     cairo_cff_font_read_header,
     cairo_cff_font_read_name,
     cairo_cff_font_read_top_dict,
     cairo_cff_font_read_strings,
     cairo_cff_font_read_global_subroutines,
+    /* non-contiguous */
+    cairo_cff_font_read_charset,
 };
 
 static cairo_int_status_t
 cairo_cff_font_read_font (cairo_cff_font_t *font)
 {
     cairo_int_status_t status;
     unsigned int i;
 
@@ -893,28 +1003,106 @@ cairo_cff_font_subset_charstrings (cairo
                                    element->length);
         if (status)
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static uint16_t
+cff_sid_from_gid (const cff_charset_t *charset, int gid)
+{
+    const uint16_t *sids;
+    const unsigned char *p;
+    int prev_glyph;
+
+    if (charset->is_builtin) {
+        if (gid - 1 < charset->length / 2)
+	    return charset->sids[gid - 1];
+    }
+    else {
+	/* no need to check sizes here, this was done during reading */
+	switch (charset->data[0]) {
+	case 0:
+	    sids = (const uint16_t *)(charset->data + 1);
+	    return be16_to_cpu(sids[gid - 1]);
+	case 1:
+	    prev_glyph = 1;
+	    for (p = charset->data + 1; p < charset->data + charset->length; p += 3) {
+		if (gid <= prev_glyph + p[2]) {
+		    uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
+		    return sid + gid - prev_glyph;
+		}
+		prev_glyph += p[2] + 1;
+	    }
+	    break;
+	case 2:
+	    prev_glyph = 1;
+	    for (p = charset->data + 1; p < charset->data + charset->length; p += 4) {
+		uint16_t nLeft = be16_to_cpu(*(const uint16_t *)(p + 2));
+		if (gid <= prev_glyph + nLeft) {
+		    uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
+		    return sid + gid - prev_glyph;
+		}
+		prev_glyph += nLeft + 1;
+	    }
+	    break;
+	default:
+	    break;
+	}
+    }
+    return 0;
+}
+
+static cairo_status_t
+cairo_cff_font_subset_charset (cairo_cff_font_t  *font)
+{
+    unsigned int i;
+
+    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+	int gid = font->scaled_font_subset->glyphs[i];
+	uint16_t original_sid = cff_sid_from_gid(&font->charset, gid);
+	uint16_t new_sid;
+	cff_index_element_t *element;
+	cairo_status_t status;
+
+	if (original_sid >= NUM_STD_STRINGS) {
+	    element = _cairo_array_index (&font->strings_index, original_sid - NUM_STD_STRINGS);
+	    new_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+	    status = cff_index_append (&font->strings_subset_index, element->data, element->length);
+	    if (status)
+		return status;
+	}
+	else
+	    new_sid = original_sid;
+
+	status = _cairo_array_append(&font->charset_subset, &new_sid);
+	if (status)
+	    return status;
+    }
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_status_t
 cairo_cff_font_subset_font (cairo_cff_font_t  *font)
 {
     cairo_status_t status;
 
     /* TODO: subset subroutines */
 
     status = cairo_cff_font_subset_strings (font);
     if (status)
         return status;
 
     status = cairo_cff_font_subset_charstrings (font);
+    if (status)
+	return status;
+
+    status = cairo_cff_font_subset_charset (font);
 
     return status;
 }
 
 /* Set the operand of the specified operator in the (already written)
  * top dict to point to the current position in the output
  * array. Operands updated with this function must have previously
  * been encoded with the 5-byte (max) integer encoding. */
@@ -1034,16 +1222,37 @@ cairo_cff_font_write_encoding (cairo_cff
     buf[2] = 0; /* First code in range */
     /* Codes left in range excluding first */
     buf[3] = font->scaled_font_subset->num_glyphs - 1;
 
     return _cairo_array_append_multiple (&font->output, buf, 4);
 }
 
 static cairo_status_t
+cairo_cff_font_write_charset (cairo_cff_font_t  *font)
+{
+    unsigned char format = 0;
+    unsigned int i;
+    cairo_status_t status;
+
+    cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
+    status = _cairo_array_append (&font->output, &format);
+    if (status)
+	return status;
+
+    for (i = 0; i < (unsigned)_cairo_array_num_elements(&font->charset_subset); i++) {
+	uint16_t sid = cpu_to_be16(*(uint16_t *)_cairo_array_index(&font->charset_subset, i));
+	status = _cairo_array_append_multiple (&font->output, &sid, sizeof(sid));
+	if (status)
+	    return status;
+    }
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 cairo_cff_font_write_charstrings (cairo_cff_font_t  *font)
 {
     cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
 
     return cff_index_write (&font->charstrings_subset_index, &font->output);
 }
 
 static cairo_status_t
@@ -1093,16 +1302,17 @@ typedef cairo_status_t
 
 static const font_write_t font_write_funcs[] = {
     cairo_cff_font_write_header,
     cairo_cff_font_write_name,
     cairo_cff_font_write_top_dict,
     cairo_cff_font_write_strings,
     cairo_cff_font_write_global_subrs,
     cairo_cff_font_write_encoding,
+    cairo_cff_font_write_charset,
     cairo_cff_font_write_charstrings,
     cairo_cff_font_write_private_dict_and_local_sub,
 };
 
 static cairo_status_t
 cairo_cff_font_write_subset (cairo_cff_font_t *font)
 {
     cairo_int_status_t status;
@@ -1340,16 +1550,17 @@ static cairo_int_status_t
     cff_dict_init (&font->top_dict);
     cff_dict_init (&font->private_dict);
     cff_index_init (&font->strings_index);
     cff_index_init (&font->charstrings_index);
     cff_index_init (&font->global_sub_index);
     cff_index_init (&font->local_sub_index);
     cff_index_init (&font->charstrings_subset_index);
     cff_index_init (&font->strings_subset_index);
+    _cairo_array_init (&font->charset_subset, sizeof(uint16_t));
 
     free (name);
     *font_return = font;
 
     return CAIRO_STATUS_SUCCESS;
 
 fail7:
     free (font->data);
@@ -1378,16 +1589,17 @@ cairo_cff_font_destroy (cairo_cff_font_t
     cff_dict_fini (font->top_dict);
     cff_dict_fini (font->private_dict);
     cff_index_fini (&font->strings_index);
     cff_index_fini (&font->charstrings_index);
     cff_index_fini (&font->global_sub_index);
     cff_index_fini (&font->local_sub_index);
     cff_index_fini (&font->charstrings_subset_index);
     cff_index_fini (&font->strings_subset_index);
+    _cairo_array_fini (&font->charset_subset);
     free (font);
 }
 
 cairo_status_t
 _cairo_cff_subset_init (cairo_cff_subset_t          *cff_subset,
                         const char		    *subset_name,
                         cairo_scaled_font_subset_t  *font_subset)
 {
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -43,17 +43,20 @@ static cairo_clip_path_t *
 _cairo_clip_path_reference (cairo_clip_path_t *clip_path);
 
 static void
 _cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
 
 void
 _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
 {
-    clip->mode = _cairo_surface_get_clip_mode (target);
+    if (target)
+	clip->mode = _cairo_surface_get_clip_mode (target);
+    else
+	clip->mode = CAIRO_CLIP_MODE_MASK;
 
     clip->surface = NULL;
     clip->surface_rect.x = 0;
     clip->surface_rect.y = 0;
     clip->surface_rect.width = 0;
     clip->surface_rect.height = 0;
 
     clip->serial = 0;
--- a/gfx/cairo/cairo/src/cairo-color.c
+++ b/gfx/cairo/cairo/src/cairo-color.c
@@ -90,31 +90,32 @@ void
 }
 
 /* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
  * The conversion is designed to divide the input range into 65536
  * equally-sized regions. This is achieved by multiplying by 65536 and
  * then special-casing the result of an input value of 1.0 so that it
  * maps to 65535 instead of 65536.
  */
-static inline uint16_t _color_to_short (double d)
+uint16_t
+_cairo_color_double_to_short (double d)
 {
     uint32_t i;
     i = (uint32_t) (d * 65536);
     i -= (i >> 16);
     return i;
 }
 
 static void
 _cairo_color_compute_shorts (cairo_color_t *color)
 {
-    color->red_short   = _color_to_short (color->red   * color->alpha);
-    color->green_short = _color_to_short (color->green * color->alpha);
-    color->blue_short  = _color_to_short (color->blue  * color->alpha);
-    color->alpha_short = _color_to_short (color->alpha);
+    color->red_short   = _cairo_color_double_to_short (color->red   * color->alpha);
+    color->green_short = _cairo_color_double_to_short (color->green * color->alpha);
+    color->blue_short  = _cairo_color_double_to_short (color->blue  * color->alpha);
+    color->alpha_short = _cairo_color_double_to_short (color->alpha);
 }
 
 void
 _cairo_color_init_rgba (cairo_color_t *color,
 			double red, double green, double blue,
 			double alpha)
 {
     color->red   = red;
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -47,19 +47,19 @@
 #include <direct/memcpy.h>
 #include <direct/util.h>
 
 #include "cairo-directfb.h"
 #include "cairoint.h"
 
 
 /*
- * Rectangle works fine.
+ * Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
  */
-#define DFB_RECTANGLES 1
+#define DFB_RECTANGLES 0
 
 /*
  * Composite works fine.
  */
 #define DFB_COMPOSITE 1 
 
 /*
  * CompositeTrapezoids works (without antialiasing).
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -43,10 +43,13 @@
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
 cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
 
 CAIRO_END_DECLS
 
+#else  /*CAIRO_HAS_DIRECTFB_SURFACE*/
+# error Cairo was not compiled with support for the directfb backend
 #endif /*CAIRO_HAS_DIRECTFB_SURFACE*/
+
 #endif /*CAIRO_DIRECTFB_H*/
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -47,33 +47,31 @@
 # define CAIRO_END_DECLS
 #endif
 
 #ifndef cairo_public
 # define cairo_public
 #endif
 
 #define CAIRO_VERSION_MAJOR 1
-#define CAIRO_VERSION_MINOR 3
-#define CAIRO_VERSION_MICRO 12
+#define CAIRO_VERSION_MINOR 4
+#define CAIRO_VERSION_MICRO 2
 
-#define CAIRO_VERSION_STRING "1.3.12"
+#define CAIRO_VERSION_STRING "1.4.2"
 
 @PS_SURFACE_FEATURE@
 
 @PDF_SURFACE_FEATURE@
 
 @SVG_SURFACE_FEATURE@
 
 @XLIB_SURFACE_FEATURE@
 
 @QUARTZ_SURFACE_FEATURE@
 
-@NQUARTZ_SURFACE_FEATURE@
-
 @XCB_SURFACE_FEATURE@
 
 @WIN32_SURFACE_FEATURE@
 
 @OS2_SURFACE_FEATURE@
 
 @BEOS_SURFACE_FEATURE@
 
--- a/gfx/cairo/cairo/src/cairo-font.c
+++ b/gfx/cairo/cairo/src/cairo-font.c
@@ -1,8 +1,9 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
  * Copyright © 2005 Red Hat Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
@@ -60,67 +61,78 @@ void
 {
     font_face->status = CAIRO_STATUS_SUCCESS;
     font_face->ref_count = 1;
     font_face->backend = backend;
 
     _cairo_user_data_array_init (&font_face->user_data);
 }
 
+/* This mutex protects both cairo_toy_font_hash_table as well as
+   reference count manipulations for all cairo_font_face_t. */
+CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
+
 /**
  * cairo_font_face_reference:
- * @font_face: a #cairo_font_face_t, (may be NULL in which case this
+ * @font_face: a #cairo_font_face_t, (may be %NULL in which case this
  * function does nothing).
  *
  * Increases the reference count on @font_face by one. This prevents
  * @font_face from being destroyed until a matching call to
  * cairo_font_face_destroy() is made.
  *
+ * The number of references to a #cairo_font_face_t can be get using
+ * cairo_font_face_get_reference_count().
+ *
  * Return value: the referenced #cairo_font_face_t.
  **/
 cairo_font_face_t *
 cairo_font_face_reference (cairo_font_face_t *font_face)
 {
-    if (font_face == NULL)
-	return NULL;
+    if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
+	return font_face;
 
-    if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
-	return font_face;
+    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
 
     /* We would normally assert (font_face->ref_count >0) here but we
      * can't get away with that due to the zombie case as documented
      * in _cairo_ft_font_face_destroy. */
 
     font_face->ref_count++;
 
+    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
+
     return font_face;
 }
 slim_hidden_def (cairo_font_face_reference);
 
 /**
  * cairo_font_face_destroy:
  * @font_face: a #cairo_font_face_t
  *
  * Decreases the reference count on @font_face by one. If the result
  * is zero, then @font_face and all associated resources are freed.
  * See cairo_font_face_reference().
  **/
 void
 cairo_font_face_destroy (cairo_font_face_t *font_face)
 {
-    if (font_face == NULL)
+    if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
 	return;
 
-    if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
-	return;
+    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
 
     assert (font_face->ref_count > 0);
 
-    if (--(font_face->ref_count) > 0)
+    if (--(font_face->ref_count) > 0) {
+        CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 	return;
+    }
+
+    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 
     font_face->backend->destroy (font_face);
 
     /* We allow resurrection to deal with some memory management for the
      * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
      * need to effectively mutually reference each other
      */
     if (font_face->ref_count > 0)
@@ -129,32 +141,52 @@ cairo_font_face_destroy (cairo_font_face
     _cairo_user_data_array_fini (&font_face->user_data);
 
     free (font_face);
 }
 slim_hidden_def (cairo_font_face_destroy);
 
 /**
  * cairo_font_face_get_type:
- * @font_face: a #cairo_font_face_t
+ * @font_face: a font face
  *
  * This function returns the type of the backend used to create
  * a font face. See #cairo_font_type_t for available types.
  *
  * Return value: The type of @font_face.
  *
  * Since: 1.2
  **/
 cairo_font_type_t
 cairo_font_face_get_type (cairo_font_face_t *font_face)
 {
     return font_face->backend->type;
 }
 
 /**
+ * cairo_font_face_get_reference_count:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Returns the current reference count of @font_face.
+ *
+ * Return value: the current reference count of @font_face.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
+{
+    if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
+	return 0;
+
+    return font_face->ref_count;
+}
+
+/**
  * cairo_font_face_status:
  * @font_face: a #cairo_font_face_t
  *
  * Checks whether an error has previously occurred for this
  * font face
  *
  * Return value: %CAIRO_STATUS_SUCCESS or another error such as
  *   %CAIRO_STATUS_NO_MEMORY.
@@ -221,45 +253,45 @@ static int
 				 const void *key_b);
 
 /* We maintain a hash table from family/weight/slant =>
  * cairo_font_face_t for cairo_toy_font_t. The primary purpose of
  * this mapping is to provide unique cairo_font_face_t values so that
  * our cache and mapping from cairo_font_face_t => cairo_scaled_font_t
  * works. Once the corresponding cairo_font_face_t objects fall out of
  * downstream caches, we don't need them in this hash table anymore.
+ *
+ * Modifications to this hash table are protected by
+ * _cairo_font_face_mutex.
  */
-
 static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL;
 
-CAIRO_MUTEX_DECLARE (cairo_toy_font_face_hash_table_mutex);
-
 static cairo_hash_table_t *
 _cairo_toy_font_face_hash_table_lock (void)
 {
-    CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
+    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
 
     if (cairo_toy_font_face_hash_table == NULL)
     {
 	cairo_toy_font_face_hash_table =
 	    _cairo_hash_table_create (_cairo_toy_font_face_keys_equal);
 
 	if (cairo_toy_font_face_hash_table == NULL) {
-	    CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
+	    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 	    return NULL;
 	}
     }
 
     return cairo_toy_font_face_hash_table;
 }
 
 static void
 _cairo_toy_font_face_hash_table_unlock (void)
 {
-    CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
+    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 }
 
 /**
  * _cairo_toy_font_face_init_key:
  *
  * Initialize those portions of cairo_toy_font_face_t needed to use
  * it as a hash table key, including the hash code buried away in
  * font_face->base.hash_entry. No memory allocation is performed here
@@ -358,18 +390,21 @@ cairo_font_face_t *
 
     _cairo_toy_font_face_init_key (&key, family, slant, weight);
 
     /* Return existing font_face if it exists in the hash table. */
     if (_cairo_hash_table_lookup (hash_table,
 				  &key.base.hash_entry,
 				  (cairo_hash_entry_t **) &font_face))
     {
+	/* We increment the reference count here manually to avoid
+	   double-locking. */
+	font_face->base.ref_count++;
 	_cairo_toy_font_face_hash_table_unlock ();
-	return cairo_font_face_reference (&font_face->base);
+	return &font_face->base;
     }
 
     /* Otherwise create it and insert into hash table. */
     font_face = malloc (sizeof (cairo_toy_font_face_t));
     if (font_face == NULL)
 	goto UNWIND_HASH_TABLE_LOCK;
 
     status = _cairo_toy_font_face_init (font_face, family, slant, weight);
@@ -466,13 +501,16 @@ void
     free (unscaled_font);
 }
 
 void
 _cairo_font_reset_static_data (void)
 {
     _cairo_scaled_font_map_destroy ();
 
-    CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
+    /* We manually acquire the lock rather than calling
+     * cairo_toy_font_face_hash_table_lock simply to avoid
+     * creating the table only to destroy it again. */
+    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
     _cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
     cairo_toy_font_face_hash_table = NULL;
-    CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
+    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 }
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -57,19 +57,21 @@
 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
 
 /* This is the max number of FT_face objects we keep open at once
  */
 #define MAX_OPEN_FACES 10
 
+#ifndef MOZILLA_CAIRO_NOT_DEFINED
 /* This is the maximum font size we allow to be passed to FT_Set_Char_Size
  */
 #define MAX_FONT_SIZE 1000
+#endif /* !MOZILLA_CAIRO_NOT_DEFINED */
 
 /*
  * The simple 2x2 matrix is converted into separate scale and shape
  * factors so that hinting works right
  */
 
 typedef struct _cairo_ft_font_transform {
     double  x_scale, y_scale;
@@ -99,17 +101,18 @@ struct _cairo_ft_unscaled_font {
     cairo_bool_t have_scale;
     cairo_matrix_t current_scale;
     double x_scale;		/* Extracted X scale factor */
     double y_scale;             /* Extracted Y scale factor */
     cairo_bool_t have_shape;	/* true if the current scale has a non-scale component*/
     cairo_matrix_t current_shape;
     FT_Matrix Current_Shape;
 
-    int lock;		/* count of how many times this font has been locked */
+    cairo_mutex_t mutex;
+    int lock_count;
 
     cairo_ft_font_face_t *faces;	/* Linked list of faces for this font */
 };
 
 static int
 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
 				    const void *key_b);
 
@@ -148,17 +151,17 @@ static const cairo_unscaled_font_backend
 typedef struct _cairo_ft_unscaled_font_map {
     cairo_hash_table_t *hash_table;
     FT_Library ft_library;
     int num_open_faces;
 } cairo_ft_unscaled_font_map_t;
 
 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
 
-CAIRO_MUTEX_DECLARE(cairo_ft_unscaled_font_map_mutex);
+CAIRO_MUTEX_DECLARE(_cairo_ft_unscaled_font_map_mutex);
 
 static void
 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
 				  cairo_ft_unscaled_font_t *unscaled)
 {
     if (unscaled->face) {
 	FT_Done_Face (unscaled->face);
 	unscaled->face = NULL;
@@ -206,17 +209,17 @@ FAIL:
 }
 
 static void
 _cairo_ft_unscaled_font_map_destroy (void)
 {
     cairo_ft_unscaled_font_t *unscaled;
     cairo_ft_unscaled_font_map_t *font_map;
 
-    CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);
+    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
 
     if (cairo_ft_unscaled_font_map) {
 	font_map = cairo_ft_unscaled_font_map;
 
 	/* This is rather inefficient, but destroying the hash table
 	 * is something we only do during debugging, (during
 	 * cairo_debug_reset_static_data), when efficiency is not
 	 * relevant. */
@@ -239,41 +242,41 @@ static void
 
 	_cairo_hash_table_destroy (font_map->hash_table);
 
 	free (font_map);
 
 	cairo_ft_unscaled_font_map = NULL;
     }
 
-    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
+    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
 }
 
 static cairo_ft_unscaled_font_map_t *
 _cairo_ft_unscaled_font_map_lock (void)
 {
-    CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);
+    CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
 
     if (cairo_ft_unscaled_font_map == NULL)
     {
 	_cairo_ft_unscaled_font_map_create ();
 
 	if (cairo_ft_unscaled_font_map == NULL) {
-	    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
+	    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
 	    return NULL;
 	}
     }
 
     return cairo_ft_unscaled_font_map;
 }
 
 static void
 _cairo_ft_unscaled_font_map_unlock (void)
 {
-    CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
+    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
 }
 
 static void
 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
 				  char			   *filename,
 				  int			    id)
 {
     unsigned long hash;
@@ -332,17 +335,18 @@ static cairo_status_t
 	filename_copy = strdup (filename);
 	if (filename_copy == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
 
 	_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
     }
 
     unscaled->have_scale = FALSE;
-    unscaled->lock = 0;
+    CAIRO_MUTEX_INIT (&unscaled->mutex);
+    unscaled->lock_count = 0;
 
     unscaled->faces = NULL;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_bool_t
 _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
@@ -365,16 +369,18 @@ static void
 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
 {
     assert (unscaled->face == NULL);
 
     if (unscaled->filename) {
 	free (unscaled->filename);
 	unscaled->filename = NULL;
     }
+
+    CAIRO_MUTEX_FINI (&unscaled->mutex);
 }
 
 static int
 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
 				    const void *key_b)
 {
     const cairo_ft_unscaled_font_t *unscaled_a = key_a;
     const cairo_ft_unscaled_font_t *unscaled_b = key_b;
@@ -496,81 +502,86 @@ static void
     }
 }
 
 static cairo_bool_t
 _has_unlocked_face (void *entry)
 {
     cairo_ft_unscaled_font_t *unscaled = entry;
 
-    return (unscaled->lock == 0 && unscaled->face);
+    return (unscaled->lock_count == 0 && unscaled->face);
 }
 
 /* Ensures that an unscaled font has a face object. If we exceed
  * MAX_OPEN_FACES, try to close some.
  *
  * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
  * set the scale on the face, but just returns it at the last scale.
  */
 FT_Face
 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
 {
     cairo_ft_unscaled_font_map_t *font_map;
     FT_Face face = NULL;
 
-    if (unscaled->face) {
-	unscaled->lock++;
+    CAIRO_MUTEX_LOCK (unscaled->mutex);
+    unscaled->lock_count++;
+
+    if (unscaled->face)
 	return unscaled->face;
-    }
 
     /* If this unscaled font was created from an FT_Face then we just
      * returned it above. */
     assert (!unscaled->from_face);
 
     font_map = _cairo_ft_unscaled_font_map_lock ();
-    assert (font_map != NULL);
+    {
+	assert (font_map != NULL);
 
-    while (font_map->num_open_faces >= MAX_OPEN_FACES)
-    {
-	cairo_ft_unscaled_font_t *entry;
+	while (font_map->num_open_faces >= MAX_OPEN_FACES)
+	{
+	    cairo_ft_unscaled_font_t *entry;
 
-	entry = _cairo_hash_table_random_entry (font_map->hash_table,
-						_has_unlocked_face);
-	if (entry == NULL)
-	    break;
+	    entry = _cairo_hash_table_random_entry (font_map->hash_table,
+						    _has_unlocked_face);
+	    if (entry == NULL)
+		break;
 
-	_font_map_release_face_lock_held (font_map, entry);
+	    _font_map_release_face_lock_held (font_map, entry);
+	}
     }
+    _cairo_ft_unscaled_font_map_unlock ();
 
     if (FT_New_Face (font_map->ft_library,
 		     unscaled->filename,
 		     unscaled->id,
 		     &face) != FT_Err_Ok)
-	goto FAIL;
+    {
+	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
+	return NULL;
+    }
 
     unscaled->face = face;
-    unscaled->lock++;
 
     font_map->num_open_faces++;
 
- FAIL:
-    _cairo_ft_unscaled_font_map_unlock ();
-
     return face;
 }
 slim_hidden_def (cairo_ft_scaled_font_lock_face);
 
 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
  */
 void
 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
 {
-    assert (unscaled->lock > 0);
+    assert (unscaled->lock_count > 0);
 
-    unscaled->lock--;
+    unscaled->lock_count--;
+
+    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
 }
 slim_hidden_def (cairo_ft_scaled_font_unlock_face);
 
 static void
 _compute_transform (cairo_ft_font_transform_t *sf,
 		    cairo_matrix_t      *scale)
 {
     cairo_matrix_t normalized = *scale;
@@ -642,29 +653,36 @@ static void
     cairo_matrix_init (&unscaled->current_shape,
 		       sf.shape[0][0], sf.shape[0][1],
 		       sf.shape[1][0], sf.shape[1][1],
 		       0.0, 0.0);
 
     FT_Set_Transform(unscaled->face, &mat, NULL);
 
     if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
+#ifndef MOZILLA_CAIRO_NOT_DEFINED
         double x_scale = sf.x_scale;
         double y_scale = sf.y_scale;
         if (x_scale > MAX_FONT_SIZE) {
             x_scale = MAX_FONT_SIZE;
         }
         if (y_scale > MAX_FONT_SIZE) {
             y_scale = MAX_FONT_SIZE;
         }
 
 	error = FT_Set_Char_Size (unscaled->face,
+				  sf.x_scale * 64.0,
+				  sf.y_scale * 64.0,
+				  0, 0);
+#else
+	error = FT_Set_Char_Size (unscaled->face,
 				  x_scale * 64.0,
 				  y_scale * 64.0,
 				  0, 0);
+#endif /* MOZCAIRO */
 	assert (error == 0);
     } else {
 	double min_distance = DBL_MAX;
 	int i;
 	int best_i = 0;
 
 	for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
@@ -1496,16 +1514,18 @@ static cairo_scaled_font_t *
 	} else {
 	    fs_metrics.max_x_advance = 0;
 	    fs_metrics.max_y_advance = face->max_advance_height / scale;
 	}
     }
 
     _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
 
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+
     return &scaled_font->base;
 }
 
 cairo_bool_t
 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
 {
     return scaled_font->backend == &cairo_ft_scaled_font_backend;
 }
@@ -1775,20 +1795,23 @@ static cairo_int_status_t
     FT_Face face;
     FT_Error error;
     int load_flags = scaled_font->ft_options.load_flags;
     FT_Glyph_Metrics *metrics;
     double x_factor, y_factor;
     cairo_bool_t vertical_layout = FALSE;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-    face = cairo_ft_scaled_font_lock_face (abstract_font);
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
 	return CAIRO_STATUS_NO_MEMORY;
 
+    _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+				       &scaled_font->base.scale);
+
     /* Ignore global advance unconditionally */
     load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
 
     if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
 	(info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
 	load_flags |= FT_LOAD_NO_BITMAP;
 
     /*
@@ -1818,16 +1841,18 @@ static cairo_int_status_t
     if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
 	FT_GlyphSlot_Embolden (glyph);
 #endif
 
     if (vertical_layout)
 	_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
 
     if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
+
+	cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
 	/*
 	 * Compute font-space metrics
 	 */
 	metrics = &glyph->metrics;
 
 	if (unscaled->x_scale == 0)
 	    x_factor = 0;
 	else
@@ -1843,18 +1868,17 @@ static cairo_int_status_t
 	 *
 	 * Scale metrics back to glyph space from the scaled glyph space returned
 	 * by FreeType
 	 *
 	 * If we want hinted metrics but aren't asking for hinted glyphs from
 	 * FreeType, then we need to do the metric hinting ourselves.
 	 */
 
-	if ((scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) &&
-	    (load_flags & FT_LOAD_NO_HINTING))
+	if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
 	{
 	    FT_Pos x1, x2;
 	    FT_Pos y1, y2;
 	    FT_Pos advance;
 	    
 	    if (!vertical_layout) {
 		x1 = (metrics->horiBearingX) & -64;
 		x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
@@ -1891,24 +1915,30 @@ static cairo_int_status_t
 	 } else {
 	    fs_metrics.width  = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
 	    fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
 
 	    if (!vertical_layout) {
 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
 		
-		fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
+		if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
+		    fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
+		else
+		    fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
 		fs_metrics.y_advance = 0 * y_factor;
 	    } else {
 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
 		
 		fs_metrics.x_advance = 0 * x_factor;
-		fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
+		if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
+		    fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
+		else
+		    fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
 	    }
 	 }
 
 	_cairo_scaled_glyph_set_metrics (scaled_glyph,
 					 &scaled_font->base,
 					 &fs_metrics);
     }
 
@@ -1941,17 +1971,17 @@ static cairo_int_status_t
 	 * so reload it. This will probably never occur though
 	 */
 	if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
 	    error = FT_Load_Glyph (face,
 				   _cairo_scaled_glyph_index(scaled_glyph),
 				   load_flags | FT_LOAD_NO_BITMAP);
 
 	    if (error) {
-		cairo_ft_scaled_font_unlock_face (abstract_font);
+		_cairo_ft_unscaled_font_unlock_face (unscaled);
 		return CAIRO_STATUS_NO_MEMORY;
 	    }
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 	    /*
 	     * embolden glyphs if requested
 	     */
 	    if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
 		FT_GlyphSlot_Embolden (glyph);
@@ -1969,17 +1999,17 @@ static cairo_int_status_t
 	if (status)
 	    goto FAIL;
 
 	_cairo_scaled_glyph_set_path (scaled_glyph,
 				      &scaled_font->base,
 				      path);
     }
  FAIL:
-    cairo_ft_scaled_font_unlock_face (abstract_font);
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return status;
 }
 
 static unsigned long
 _cairo_ft_ucs4_to_index (void	    *abstract_font,
 			 uint32_t    ucs4)
 {
@@ -2021,25 +2051,58 @@ static cairo_int_status_t
         status = CAIRO_STATUS_SUCCESS;
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 #endif
 
     return status;
 }
 
+static void
+_cairo_ft_map_glyphs_to_unicode (void	                    *abstract_font,
+                                 cairo_scaled_font_subset_t *font_subset)
+{
+    cairo_ft_scaled_font_t *scaled_font = abstract_font;
+    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+    FT_Face face;
+    FT_UInt glyph;
+    unsigned long charcode;
+    unsigned int i;
+    int count;
+
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return;
+
+    count = font_subset->num_glyphs;
+    charcode = FT_Get_First_Char( face, &glyph);
+    while (glyph != 0 && count > 0)
+    {
+        for (i = 0; i < font_subset->num_glyphs; i++) {
+            if (font_subset->glyphs[i] == glyph) {
+                font_subset->to_unicode[i] = charcode;
+                count--;
+                break;
+            }
+        }
+        charcode = FT_Get_Next_Char(face, charcode, &glyph);
+    }
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+}
+
 const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
     NULL,			/* text_to_glyphs */
     _cairo_ft_ucs4_to_index,
     NULL, 			/* show_glyphs */
     _cairo_ft_load_truetype_table,
+    _cairo_ft_map_glyphs_to_unicode,
 };
 
 /* cairo_ft_font_face_t */
 
 static void
 _cairo_ft_font_face_destroy (void *abstract_face)
 {
     cairo_ft_font_face_t *font_face = abstract_face;
@@ -2387,23 +2450,24 @@ cairo_ft_font_face_create_for_ft_face (F
  * when you are done using it.  Since the #FT_Face object can be
  * shared between multiple #cairo_scaled_font_t objects, you must not
  * lock any other font objects until you unlock this one. A count is
  * kept of the number of times cairo_ft_font_lock_face() is
  * called. cairo_ft_font_unlock_face() must be called the same number
  * of times.
  *
  * You must be careful when using this function in a library or in a
- * threaded application, because other threads may lock faces that
- * share the same #FT_Face object. For this reason, you must call
- * cairo_ft_lock() before locking any face objects, and
- * cairo_ft_unlock() after you are done. (These functions are not yet
- * implemented, so this function cannot be currently safely used in a
- * threaded application.)
-
+ * threaded application, because freetype's design makes it unsafe to
+ * call freetype functions simultaneously from multiple threads, (even
+ * if using distinct FT_Face objects). Because of this, application
+ * code that acquires an FT_Face object with this call must add it's
+ * own locking to protect any use of that object, (and which also must
+ * protect any other calls into cairo as almost any cairo function
+ * might result in a call into the freetype library).
+ *
  * Return value: The #FT_Face object for @font, scaled appropriately,
  * or %NULL if @scaled_font is in an error state (see
  * cairo_scaled_font_status()) or there is insufficient memory.
  **/
 FT_Face
 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
@@ -2416,16 +2480,24 @@ cairo_ft_scaled_font_lock_face (cairo_sc
     if (face == NULL) {
 	_cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
 
     _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
 				       &scaled_font->base.scale);
 
+    /* NOTE: We deliberately release the unscaled font's mutex here,
+     * so that we are not holding a lock across two separate calls to
+     * cairo function, (which would give the application some
+     * opportunity for creating deadlock. This is obviously unsafe,
+     * but as documented, the user must add manual locking when using
+     * this function. */
+     CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
+
     return face;
 }
 
 /**
  * cairo_ft_scaled_font_unlock_face:
  * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
  *   object can be created by calling cairo_scaled_font_create() on a
  *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
@@ -2436,16 +2508,22 @@ cairo_ft_scaled_font_lock_face (cairo_sc
 void
 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
 
     if (scaled_font->base.status)
 	return;
 
+    /* NOTE: We released the unscaled font's mutex at the end of
+     * cairo_ft_scaled_font_lock_face, so we have to acquire it again
+     * as _cairo_ft_unscaled_font_unlock_face expects it to be held
+     * when we call into it. */
+    CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
+
     _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
 }
 
 /* We expose our unscaled font implementation internally for the the
  * PDF backend, which needs to keep track of the the different
  * fonts-on-disk used by a document, so it can embed them.
  */
 cairo_unscaled_font_t *
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -589,17 +589,17 @@ static cairo_int_status_t
 	cairo_gradient_pattern_t    *gradient =
 	    (cairo_gradient_pattern_t *) pattern;
 	char			    *data;
 	glitz_fixed16_16_t	    *params;
 	int			    n_params;
 	unsigned int		    *pixels;
 	unsigned int		    i, n_base_params;
 	glitz_buffer_t		    *buffer;
-	static glitz_pixel_format_t format = {
+	static const glitz_pixel_format_t format = {
 	    GLITZ_FOURCC_RGB,
 	    {
 		32,
 		0xff000000,
 		0x00ff0000,
 		0x0000ff00,
 		0x000000ff
 	    },
@@ -681,22 +681,22 @@ static cairo_int_status_t
 	    params[2] = grad->gradient.p2.x;
 	    params[3] = grad->gradient.p2.y;
 	    attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
 	}
 	else
 	{
 	    cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
 
-	    params[0] = grad->gradient.inner.x;
-	    params[1] = grad->gradient.inner.y;
-	    params[2] = grad->gradient.inner.radius;
-	    params[3] = grad->gradient.outer.x;
-	    params[4] = grad->gradient.outer.y;
-	    params[5] = grad->gradient.outer.radius;
+	    params[0] = grad->gradient.c1.x;
+	    params[1] = grad->gradient.c1.y;
+	    params[2] = grad->gradient.c1.radius;
+	    params[3] = grad->gradient.c2.x;
+	    params[4] = grad->gradient.c2.y;
+	    params[5] = grad->gradient.c2.radius;
 	    attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
 	}
 
 	switch (pattern->extend) {
 	case CAIRO_EXTEND_NONE:
 	    attr->fill = GLITZ_FILL_TRANSPARENT;
 	    break;
 	case CAIRO_EXTEND_REPEAT:
@@ -971,17 +971,17 @@ static cairo_int_status_t
 	glitz_color.green = color->green_short;
 	glitz_color.blue = color->blue_short;
 	glitz_color.alpha = color->alpha_short;
 
 	glitz_set_rectangles (dst->surface, &glitz_color,
 			      (glitz_rectangle_t *) rects, n_rects);
     } break;
     case CAIRO_OPERATOR_CLEAR: {
-	static glitz_color_t glitz_color = { 0, 0, 0, 0 };
+	static const glitz_color_t glitz_color = { 0, 0, 0, 0 };
 
 	glitz_set_rectangles (dst->surface, &glitz_color,
 			      (glitz_rectangle_t *) rects, n_rects);
     } break;
     case CAIRO_OPERATOR_SATURATE:
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     case CAIRO_OPERATOR_OVER:
     case CAIRO_OPERATOR_IN:
@@ -1090,17 +1090,17 @@ static cairo_int_status_t
     }
     alpha = 0xffff;
 
     if (status)
 	return status;
 
     if (op == CAIRO_OPERATOR_ADD || n_traps <= 1)
     {
-	static glitz_color_t	clear_black = { 0, 0, 0, 0 };
+	static const glitz_color_t	clear_black = { 0, 0, 0, 0 };
 	glitz_color_t		color;
 	glitz_geometry_format_t	format;
 	int			n_trap_added;
 	int			offset = 0;
 	int			data_size = 0;
 	int			size = 30 * n_traps; /* just a guess */
 
 	format.vertex.primitive = GLITZ_PRIMITIVE_QUADS;
@@ -1936,17 +1936,17 @@ static cairo_int_status_t
     glitz_float_t			stack_vertices[N_STACK_BUF * 16];
     glitz_float_t			*vertices;
     glitz_buffer_t			*buffer;
     cairo_int_status_t			status;
     int					x_offset, y_offset;
     int					i, cached_glyphs = 0;
     int					remaining_glyps = num_glyphs;
     glitz_float_t			x1, y1, x2, y2;
-    static glitz_vertex_format_t	format = {
+    static const glitz_vertex_format_t	format = {
 	GLITZ_PRIMITIVE_QUADS,
 	GLITZ_DATA_TYPE_FLOAT,
 	sizeof (glitz_float_t) * 4,
 	GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK,
 	{ 0 },
 	{
 	    GLITZ_DATA_TYPE_FLOAT,
 	    GLITZ_COORDINATE_SIZE_XY,
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -38,74 +38,34 @@
 #include <stdlib.h>
 
 #include "cairoint.h"
 
 #include "cairo-clip-private.h"
 #include "cairo-gstate-private.h"
 
 static cairo_status_t
-_cairo_gstate_init (cairo_gstate_t  *gstate,
-		    cairo_surface_t *target);
-
-static cairo_status_t
 _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
 
-static void
-_cairo_gstate_fini (cairo_gstate_t *gstate);
-
 static cairo_status_t
 _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
 
 static cairo_status_t
 _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
 
 static void
 _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
 
 static void
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
                                            cairo_glyph_t       *transformed_glyphs);
 
-/**
- * _cairo_gstate_create:
- * @target: a #cairo_surface_t, not NULL
- *
- * Create a new #cairo_gstate_t to draw to target with all graphics
- * state parameters set to defaults. gstate->next will be set to NULL
- * and may be used by the caller to chain #cairo_gstate_t objects
- * together.
- *
- * Return value: a new #cairo_gstate_t or NULL if there is
- * insufficient memory.
- **/
-cairo_gstate_t *
-_cairo_gstate_create (cairo_surface_t *target)
-{
-    cairo_status_t status;
-    cairo_gstate_t *gstate;
-
-    assert (target != NULL);
-
-    gstate = malloc (sizeof (cairo_gstate_t));
-    if (gstate == NULL)
-	return NULL;
-
-    status = _cairo_gstate_init (gstate, target);
-    if (status) {
-	free (gstate);
-	return NULL;
-    }
-
-    return gstate;
-}
-
-static cairo_status_t
+cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
 		    cairo_surface_t *target)
 {
     gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
 
     gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
     gstate->antialias = CAIRO_ANTIALIAS_DEFAULT;
 
@@ -184,17 +144,17 @@ static cairo_status_t
 
     gstate->source = cairo_pattern_reference (other->source);
 
     gstate->next = NULL;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+void
 _cairo_gstate_fini (cairo_gstate_t *gstate)
 {
     _cairo_stroke_style_fini (&gstate->stroke_style);
 
     cairo_font_face_destroy (gstate->font_face);
     gstate->font_face = NULL;
 
     cairo_scaled_font_destroy (gstate->scaled_font);
@@ -717,18 +677,18 @@ void
                                          double *x1, double *y1,
                                          double *x2, double *y2,
                                          cairo_bool_t *is_tight)
 {
     cairo_matrix_t matrix_inverse;
 
     cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse,
                            &gstate->target->device_transform_inverse);
-    cairo_matrix_transform_bounding_box (&matrix_inverse,
-					 x1, y1, x2, y2, is_tight);
+    _cairo_matrix_transform_bounding_box (&matrix_inverse,
+					  x1, y1, x2, y2, is_tight);
 }
 
 /* XXX: NYI
 cairo_status_t
 _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
 {
     cairo_status_t status;
 
@@ -950,16 +910,21 @@ cairo_status_t
 			 cairo_path_fixed_t *path,
 			 double		     x,
 			 double		     y,
 			 cairo_bool_t	    *inside_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_traps_t traps;
 
+    if (gstate->stroke_style.line_width <= 0.0) {
+	*inside_ret = FALSE;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     _cairo_gstate_user_to_backend (gstate, &x, &y);
 
     _cairo_traps_init (&traps);
 
     status = _cairo_path_fixed_stroke_to_traps (path,
 						&gstate->stroke_style,
 						&gstate->ctm,
 						&gstate->ctm_inverse,
@@ -1068,36 +1033,59 @@ static void
                                                double *x2, double *y2)
 {
     cairo_box_t extents;
 
     _cairo_traps_extents (traps, &extents);
 
     if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
         /* no traps, so we actually won't draw anything */
-        *x1 = *y1 = *x2 = *y2 = 0;
+	if (x1)
+	    *x1 = 0.0;
+	if (y1)
+	    *y1 = 0.0;
+	if (x2)
+	    *x2 = 0.0;
+	if (y2)
+	    *y2 = 0.0;
     } else {
-        *x1 = _cairo_fixed_to_double (extents.p1.x);
-        *y1 = _cairo_fixed_to_double (extents.p1.y);
-        *x2 = _cairo_fixed_to_double (extents.p2.x);
-        *y2 = _cairo_fixed_to_double (extents.p2.y);
+	if (x1)
+	    *x1 = _cairo_fixed_to_double (extents.p1.x);
+	if (y1)
+	    *y1 = _cairo_fixed_to_double (extents.p1.y);
+	if (x2)
+	    *x2 = _cairo_fixed_to_double (extents.p2.x);
+	if (y2)
+	    *y2 = _cairo_fixed_to_double (extents.p2.y);
 
         _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
     }
 }
 
 cairo_status_t
 _cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
 			      cairo_path_fixed_t *path,
                               double *x1, double *y1,
 			      double *x2, double *y2)
 {
     cairo_status_t status;
     cairo_traps_t traps;
 
+    if (gstate->stroke_style.line_width <= 0.0) {
+	if (x1)
+	    *x1 = 0.0;
+	if (y1)
+	    *y1 = 0.0;
+	if (x2)
+	    *x2 = 0.0;
+	if (y2)
+	    *y2 = 0.0;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     _cairo_traps_init (&traps);
 
     status = _cairo_path_fixed_stroke_to_traps (path,
 						&gstate->stroke_style,
 						&gstate->ctm,
 						&gstate->ctm_inverse,
 						gstate->tolerance,
 						&traps);
@@ -1160,21 +1148,25 @@ cairo_status_t
     
     status = _cairo_surface_get_extents (gstate->target, &extents);
     if (status)
         return status;
 
     status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
     if (status)
         return status;
-    
-    *x1 = extents.x;
-    *y1 = extents.y;
-    *x2 = extents.x + extents.width;
-    *y2 = extents.y + extents.height;
+
+    if (x1)
+	*x1 = extents.x;
+    if (y1)
+	*y1 = extents.y;
+    if (x2)
+	*x2 = extents.x + extents.width;
+    if (y2)
+	*y2 = extents.y + extents.height;
 
     _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_rectangle_list_t*
 _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
@@ -1266,16 +1258,31 @@ cairo_status_t
     if (status)
 	return status;
 
     *font_face = gstate->font_face;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+cairo_status_t
+_cairo_gstate_get_scaled_font (cairo_gstate_t       *gstate,
+			       cairo_scaled_font_t **scaled_font)
+{
+    cairo_status_t status;
+
+    status = _cairo_gstate_ensure_scaled_font (gstate);
+    if (status)
+	return status;
+
+    *scaled_font = gstate->scaled_font;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 /*
  * Like everything else in this file, fonts involve Too Many Coordinate Spaces;
  * it is easy to get confused about what's going on.
  *
  * The user's view
  * ---------------
  *
  * Users ask for things in user space. When cairo starts, a user space unit
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -1111,16 +1111,17 @@ cairo_image_surface_t *
     cairo_image_surface_t *clone;
     cairo_t *cr;
     double x, y;
 
     clone = (cairo_image_surface_t *)
 	cairo_image_surface_create (format,
 				    surface->width, surface->height);
 
+    /* Use _cairo_surface_composite directly */
     cr = cairo_create (&clone->base);
     cairo_surface_get_device_offset (&surface->base, &x, &y);
     cairo_set_source_surface (cr, &surface->base, x, y);
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
     cairo_paint (cr);
     cairo_destroy (cr);
 
     cairo_surface_set_device_offset (&clone->base, x, y);
--- a/gfx/cairo/cairo/src/cairo-matrix.c
+++ b/gfx/cairo/cairo/src/cairo-matrix.c
@@ -351,20 +351,20 @@ cairo_matrix_transform_point (const cair
     cairo_matrix_transform_distance (matrix, x, y);
 
     *x += matrix->x0;
     *y += matrix->y0;
 }
 slim_hidden_def(cairo_matrix_transform_point);
 
 void
-cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
-                                     double *x1, double *y1,
-                                     double *x2, double *y2,
-                                     cairo_bool_t *is_tight)
+_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
+				      double *x1, double *y1,
+				      double *x2, double *y2,
+				      cairo_bool_t *is_tight)
 {
     int i;
     double quad_x[4], quad_y[4];
     double min_x, max_x;
     double min_y, max_y;
 
     quad_x[0] = *x1;
     quad_y[0] = *y1;
@@ -412,17 +412,16 @@ cairo_matrix_transform_bounding_box (con
         */
         *is_tight =
             (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
              quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
             (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
              quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
     }
 }
-slim_hidden_def(cairo_matrix_transform_bounding_box);
 
 static void
 _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
 {
     matrix->xx *= scalar;
     matrix->yx *= scalar;
 
     matrix->xy *= scalar;
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-nquartz-surface.c
+++ /dev/null
@@ -1,1866 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright  2006 Mozilla Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Mozilla Corporation.
- *
- * Contributor(s):
- *	Vladimir Vukicevic <vladimir@mozilla.com>
- */
-
-#include <Carbon/Carbon.h>
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-#include <AGL/agl.h>
-#include <OpenGL/gl.h>
-#endif
-
-#include "cairoint.h"
-#include "cairo-private.h"
-#include "cairo-nquartz.h"
-
-#include "cairo-quartz-private.h"
-
-#undef NQUARTZ_DEBUG
-
-#ifdef NQUARTZ_DEBUG
-#define ND(_x)	fprintf _x
-#else
-#define ND(_x)	do {} while(0)
-#endif
-
-/* This method is private, but it exists.  Its params are are exposed
- * as args to the NS* method, but not as CG.
- */
-enum PrivateCGCompositeMode {
-    kPrivateCGCompositeClear		= 0,
-    kPrivateCGCompositeCopy		= 1,
-    kPrivateCGCompositeSourceOver	= 2,
-    kPrivateCGCompositeSourceIn		= 3,
-    kPrivateCGCompositeSourceOut	= 4,
-    kPrivateCGCompositeSourceAtop	= 5,
-    kPrivateCGCompositeDestinationOver	= 6,
-    kPrivateCGCompositeDestinationIn	= 7,
-    kPrivateCGCompositeDestinationOut	= 8,
-    kPrivateCGCompositeDestinationAtop	= 9,
-    kPrivateCGCompositeXOR		= 10,
-    kPrivateCGCompositePlusDarker	= 11, // (max (0, (1-d) + (1-s)))
-    kPrivateCGCompositePlusLighter	= 12, // (min (1, s + d))
-};
-typedef enum PrivateCGCompositeMode PrivateCGCompositeMode;
-CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
-CG_EXTERN void CGContextResetCTM (CGContextRef);
-CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform);
-CG_EXTERN void CGContextResetClip (CGContextRef);
-CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
-
-/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
- * has all the stuff we care about, just some of it isn't exported in the SDK.
- */ 
-#ifndef kCGBitmapByteOrder32Host
-#define USE_10_3_WORKAROUNDS
-#define kCGBitmapAlphaInfoMask 0x1F
-#define kCGBitmapByteOrderMask 0x7000
-#define kCGBitmapByteOrder32Host 0
-
-typedef uint32_t CGBitmapInfo;
-
-/* public in 10.4, present in 10.3.9 */
-CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
-CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
-#endif
-
-
-typedef struct cairo_nquartz_surface {
-    cairo_surface_t base;
-
-    void *imageData;
-
-    CGContextRef cgContext;
-    CGAffineTransform cgContextBaseCTM;
-
-    cairo_rectangle_int16_t extents;
-
-    /* These are stored while drawing operations are in place, set up
-     * by nquartz_setup_source() and nquartz_finish_source()
-     */
-    CGAffineTransform imageTransform;
-    CGImageRef sourceImage;
-    CGShadingRef sourceShading;
-    CGPatternRef sourcePattern;
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    AGLContext aglContext;
-#else
-    void *_unused;
-#endif
-} cairo_nquartz_surface_t;
-
-/**
- ** Utility functions
- **/
-
-void nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest);
-void nquartz_image_to_png (CGImageRef, char *dest);
-
-/*
- * Cairo path -> Quartz path conversion helpers
- */
-
-/* cairo path -> mutable path */
-static cairo_status_t
-_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
-{
-    CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
-		       _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
-{
-    CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
-			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
-{
-    CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
-			   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-			   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-			   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_close_path (void *closure)
-{
-    CGPathCloseSubpath ((CGMutablePathRef) closure);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* cairo path -> execute in context */
-static cairo_status_t
-_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
-{
-    //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    CGContextMoveToPoint ((CGContextRef) closure,
-			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
-{
-    //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    if (CGContextIsPathEmpty ((CGContextRef) closure))
-	CGContextMoveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    else
-	CGContextAddLineToPoint ((CGContextRef) closure,
-				 _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
-{
-    //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n",
-    //		   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-    //		   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-    //		   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
-
-    CGContextAddCurveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-			      _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-			      _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_close_path (void *closure)
-{
-    //ND((stderr, "closepath\n"));
-    CGContextClosePath ((CGContextRef) closure);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_nquartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
-					  CGMutablePathRef cgPath)
-{
-    return _cairo_path_fixed_interpret (path,
-					CAIRO_DIRECTION_FORWARD,
-					_cairo_path_to_quartz_path_move_to,
-					_cairo_path_to_quartz_path_line_to,
-					_cairo_path_to_quartz_path_curve_to,
-					_cairo_path_to_quartz_path_close_path,
-					cgPath);
-}
-
-static cairo_status_t
-_cairo_nquartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
-					     CGContextRef cgc)
-{
-    return _cairo_path_fixed_interpret (path,
-					CAIRO_DIRECTION_FORWARD,
-					_cairo_path_to_quartz_context_move_to,
-					_cairo_path_to_quartz_context_line_to,
-					_cairo_path_to_quartz_context_curve_to,
-					_cairo_path_to_quartz_context_close_path,
-					cgc);
-}
-
-/*
- * Misc helpers/callbacks
- */
-
-static PrivateCGCompositeMode
-_cairo_nquartz_cairo_operator_to_quartz (cairo_operator_t op)
-{
-    switch (op) {
-	case CAIRO_OPERATOR_CLEAR:
-	    return kPrivateCGCompositeClear;
-	case CAIRO_OPERATOR_SOURCE:
-	    return kPrivateCGCompositeCopy;
-	case CAIRO_OPERATOR_OVER:
-	    return kPrivateCGCompositeSourceOver;
-	case CAIRO_OPERATOR_IN:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeSourceIn;
-	case CAIRO_OPERATOR_OUT:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeSourceOut;
-	case CAIRO_OPERATOR_ATOP:
-	    return kPrivateCGCompositeSourceAtop;
-
-	case CAIRO_OPERATOR_DEST:
-	    /* XXX this is handled specially (noop)! */
-	    return kPrivateCGCompositeCopy;
-	case CAIRO_OPERATOR_DEST_OVER:
-	    return kPrivateCGCompositeDestinationOver;
-	case CAIRO_OPERATOR_DEST_IN:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeDestinationIn;
-	case CAIRO_OPERATOR_DEST_OUT:
-	    return kPrivateCGCompositeDestinationOut;
-	case CAIRO_OPERATOR_DEST_ATOP:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeDestinationAtop;
-
-	case CAIRO_OPERATOR_XOR:
-	    return kPrivateCGCompositeXOR; /* This will generate strange results */
-	case CAIRO_OPERATOR_ADD:
-	    return kPrivateCGCompositePlusLighter;
-	case CAIRO_OPERATOR_SATURATE:
-	    /* XXX This doesn't match image output for SATURATE; there's no equivalent */
-	    return kPrivateCGCompositePlusDarker;  /* ??? */
-    }
-
-
-    return kPrivateCGCompositeCopy;
-}
-
-static CGLineCap
-_cairo_nquartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap)
-{
-    switch (ccap) {
-	case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break;
-	case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break;
-	case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break;
-    }
-
-    return kCGLineCapButt;
-}
-
-static CGLineJoin
-_cairo_nquartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin)
-{
-    switch (cjoin) {
-	case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break;
-	case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break;
-	case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break;
-    }
-
-    return kCGLineJoinMiter;
-}
-
-static void
-_cairo_nquartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
-				       CGAffineTransform *dst)
-{
-    dst->a = src->xx;
-    dst->b = src->xy;
-    dst->c = src->yx;
-    dst->d = src->yy;
-    dst->tx = src->x0;
-    dst->ty = src->y0;
-}
-
-/**
- ** Source -> Quartz setup and finish functions
- **/
-
-static void
-ComputeGradientValue (void *info, const float *in, float *out)
-{
-    float fdist = *in; /* 0.0 .. 1.0 */
-    cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
-    cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
-    int i;
-
-    for (i = 0; i < grad->n_stops; i++) {
-	if (grad->stops[i].x > fdist_fix)
-	    break;
-    }
-
-    if (i == 0 || i == grad->n_stops) {
-	if (i == grad->n_stops)
-	    --i;
-	out[0] = grad->stops[i].color.red / 65535.;
-	out[1] = grad->stops[i].color.green / 65535.;
-	out[2] = grad->stops[i].color.blue / 65535.;
-	out[3] = grad->stops[i].color.alpha / 65535.;
-    } else {
-	float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
-	float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
-	float bp = (fdist - ax)/bx;
-	float ap = 1.0 - bp;
-
-	out[0] =
-	    (grad->stops[i-1].color.red / 65535.) * ap +
-	    (grad->stops[i].color.red / 65535.) * bp;
-	out[1] =
-	    (grad->stops[i-1].color.green / 65535.) * ap +
-	    (grad->stops[i].color.green / 65535.) * bp;
-	out[2] =
-	    (grad->stops[i-1].color.blue / 65535.) * ap +
-	    (grad->stops[i].color.blue / 65535.) * bp;
-	out[3] =
-	    (grad->stops[i-1].color.alpha / 65535.) * ap +
-	    (grad->stops[i].color.alpha / 65535.) * bp;
-    }
-}
-
-static CGFunctionRef
-CreateGradientFunction (cairo_gradient_pattern_t *gpat)
-{
-    static const float input_value_range[2] = { 0.f, 1.f };
-    static const float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f };
-    static const CGFunctionCallbacks callbacks = {
-	0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
-    };
-
-    return CGFunctionCreate (gpat,
-			     1,
-			     input_value_range,
-			     4,
-			     output_value_ranges,
-			     &callbacks);
-}
-
-static CGShadingRef
-_cairo_nquartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
-{
-    cairo_matrix_t mat;
-    double x0, y0;
-
-    if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
-	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
-	return NULL;
-
-    /* We can only do this if we have an identity pattern matrix;
-     * otherwise fall back through to the generic pattern case.
-     * XXXperf we could optimize this by creating a pattern with the shading;
-     * but we'd need to know the extents to do that.
-     * ... but we don't care; we can use the surface extents for it
-     * XXXtodo - implement gradients with non-identity pattern matrices
-     */
-    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;
-
-    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();
-
-	start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
-			     _cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
-	end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0,
-			   _cairo_fixed_to_double (lpat->gradient.p2.y) - y0);
-
-	cairo_pattern_reference (abspat);
-	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
-	shading = CGShadingCreateAxial (rgb,
-					start, end,
-					gradFunc,
-					true, true);
-	CGColorSpaceRelease(rgb);
-	CGFunctionRelease(gradFunc);
-
-	return shading;
-    }
-
-    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();
-
-	start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.inner.x) - x0,
-			     _cairo_fixed_to_double (rpat->gradient.inner.y) - y0);
-	end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.outer.x) - x0,
-			   _cairo_fixed_to_double (rpat->gradient.outer.y) - y0);
-
-	cairo_pattern_reference (abspat);
-	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
-	shading = CGShadingCreateRadial (rgb,
-					 start,
-					 _cairo_fixed_to_double (rpat->gradient.inner.radius),
-					 end,
-					 _cairo_fixed_to_double (rpat->gradient.outer.radius),
-					 gradFunc,
-					 true, true);
-	CGColorSpaceRelease(rgb);
-	CGFunctionRelease(gradFunc);
-
-	return shading;
-    }
-
-    /* Shouldn't be reached */
-    ASSERT_NOT_REACHED;
-    return NULL;
-}
-
-
-/* Generic cairo_pattern -> CGPattern function */
-static void
-SurfacePatternDrawFunc (void *info, CGContextRef context)
-{
-    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
-    cairo_surface_t *pat_surf = spat->surface;
-    cairo_rectangle_int16_t extents;
-    cairo_status_t status;
-
-    cairo_nquartz_surface_t *quartz_surf = NULL;
-
-    cairo_bool_t flip = FALSE;
-
-    CGImageRef img;
-
-    if (!cairo_surface_is_nquartz (pat_surf)) {
-	ND((stderr, "-- source is not nquartz surface\n"));
-	/* This sucks; we should really store a dummy nquartz surface
-	 * for passing in here
-	 * XXXtodo store a dummy nquartz surface somewhere for handing off to clone_similar
-	 * XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
-	 * just create the CGImage directly!
-	 */
-
-	cairo_surface_t *dummy = cairo_nquartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-
-	cairo_rectangle_int16_t rect;
-	_cairo_surface_get_extents (pat_surf, &rect);
-
-	cairo_surface_t *new_surf = NULL;
-
-	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
-				      rect.width, rect.height, &new_surf);
-
-	cairo_surface_destroy(dummy);
-
-	quartz_surf = (cairo_nquartz_surface_t *) new_surf;
-    } else {
-	ND((stderr, "-- source is nquartz surface\n"));
-	/* If it's a nquartz 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_nquartz_surface_t*) pat_surf;
-
-	/* XXXtodo WHY does this need to be flipped?  Writing this stuff
-	 * to disk shows that in both this path and the path above the source image
-	 * has an identical orientation, and the destination context at all times has a Y
-	 * flip.  So why do we need to flip in this case?
-	 */
-	flip = TRUE;
-    }
-
-    /* this is a 10.4 API, present in 10.3.9 */
-    CGContextFlush (quartz_surf->cgContext);
-    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
-
-    if (!img) {
-	// ... give up.
-	ND((stderr, "CGBitmapContextCreateImage failed\n"));
-	cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
-	return;
-    }
-
-    if (flip) {
-	CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
-	CGContextScaleCTM (context, 1, -1);
-    }
-
-    CGRect imageBounds;
-    imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
-    imageBounds.origin.x = 0;
-    imageBounds.origin.y = 0;
-
-    CGContextDrawImage (context, imageBounds, img);
-
-    CGImageRelease (img);
-
-    cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
-}
-
-/* Borrowed from cairo-meta-surface */
-static cairo_status_t
-_init_pattern_with_snapshot (cairo_pattern_t *pattern,
-			     const cairo_pattern_t *other)
-{
-    _cairo_pattern_init_copy (pattern, other);
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern =
-	    (cairo_surface_pattern_t *) pattern;
-	cairo_surface_t *surface = surface_pattern->surface;
-
-	surface_pattern->surface = _cairo_surface_snapshot (surface);
-
-	cairo_surface_destroy (surface);
-
-	if (surface_pattern->surface->status)
-	    return surface_pattern->surface->status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static CGPatternRef
-_cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_t *dest,
-							  cairo_pattern_t *abspat)
-{
-    cairo_surface_pattern_t *spat;
-    cairo_surface_t *pat_surf;
-    cairo_rectangle_int16_t extents;
-
-    CGRect pbounds;
-    CGAffineTransform ptransform, stransform;
-    CGPatternCallbacks cb = { 0,
-			      SurfacePatternDrawFunc,
-			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
-    CGPatternRef cgpat;
-    float rw, rh;
-
-    cairo_pattern_union_t *snap_pattern = NULL;
-    cairo_pattern_t *target_pattern = abspat;
-
-    /* SURFACE is the only type we'll handle here */
-    if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
-	return NULL;
-
-    spat = (cairo_surface_pattern_t *) abspat;
-    pat_surf = spat->surface;
-
-    _cairo_surface_get_extents (pat_surf, &extents);
-    pbounds.origin.x = 0;
-    pbounds.origin.y = 0;
-    pbounds.size.width = extents.width;
-    pbounds.size.height = extents.height;
-
-    cairo_matrix_t m = spat->base.matrix;
-    cairo_matrix_invert(&m);
-    _cairo_nquartz_cairo_matrix_to_quartz (&m, &stransform);
-
-    /* The pattern matrix is relative to the bottom left, again; the
-     * incoming cairo pattern matrix is relative to the upper left.
-     * So we take the pattern matrix and the original context matrix,
-     * which gives us the correct base translation/y flip.
-     */
-    ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM);
-
-#ifdef NQUARTZ_DEBUG
-    ND((stderr, "  pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height));
-    ND((stderr, "  pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d));
-    CGAffineTransform xform = CGContextGetCTM(dest->cgContext);
-    ND((stderr, "  context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
-#endif
-
-    // kjs seems to indicate this should work (setting to 0,0 to avoid
-    // tiling); however, the pattern CTM scaling ends up being NaN in
-    // the pattern draw function if either rw or rh are 0.
-    // XXXtodo get pattern drawing working with extend options
-    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
-#if 0
-    if (spat->base.extend == CAIRO_EXTEND_NONE) {
-	/* XXX wasteful; this will keep drawing the pattern in the
-	 * original location.  We need to set up the clip region
-	 * instead to do this right.
-	 */
-	rw = 0;
-	rh = 0;
-    } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
-	rw = extents.width;
-	rh = extents.height;
-    } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
-	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
-	 * and then tiling that
-	 */
-	rw = extents.width;
-	rh = extents.height;
-    } else {
-	/* CAIRO_EXTEND_PAD */
-	/* XXX broken. */
-	rw = 0;
-	rh = 0;
-    }
-#else
-    rw = extents.width;
-    rh = extents.height;
-#endif
-
-    /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
-       other block if it doesn't fafect performance */
-    if (1 /* context is for printing */) {
-	snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
-	target_pattern = (cairo_pattern_t*) snap_pattern;
-	_init_pattern_with_snapshot (snap_pattern, abspat);
-    } else {
-	cairo_pattern_reference (abspat);
-	target_pattern = abspat;
-    }
-
-    cgpat = CGPatternCreate (target_pattern,
-			     pbounds,
-			     ptransform,
-			     rw, rh,
-			     kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
-			     TRUE,
-			     &cb);
-    return cgpat;
-}
-
-typedef enum {
-    DO_SOLID,
-    DO_SHADING,
-    DO_PATTERN,
-    DO_UNSUPPORTED
-} cairo_nquartz_action_t;
-
-static cairo_nquartz_action_t
-_cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
-			     cairo_pattern_t *source)
-{
-    assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-
-	CGContextSetRGBStrokeColor (surface->cgContext,
-				    solid->color.red,
-				    solid->color.green,
-				    solid->color.blue,
-				    solid->color.alpha);
-	CGContextSetRGBFillColor (surface->cgContext,
-				  solid->color.red,
-				  solid->color.green,
-				  solid->color.blue,
-				  solid->color.alpha);
-
-	return DO_SOLID;
-    } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR ||
-	       source->type == CAIRO_PATTERN_TYPE_RADIAL)
-    {
-	CGShadingRef shading = _cairo_nquartz_cairo_gradient_pattern_to_quartz (source);
-	if (!shading)
-	    return DO_UNSUPPORTED;
-
-	surface->sourceShading = shading;
-
-	return DO_SHADING;
-    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	CGPatternRef pattern = _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
-	if (!pattern)
-	    return DO_UNSUPPORTED;
-
-	float patternAlpha = 1.0f;
-
-	// Save before we change the pattern, colorspace, etc. so that
-	// we can restore and make sure that quartz releases our
-	// pattern (which may be stack allocated)
-	CGContextSaveGState(surface->cgContext);
-
-	CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
-	CGContextSetFillColorSpace (surface->cgContext, patternSpace);
-	CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
-	CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
-	CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha);
-	CGColorSpaceRelease (patternSpace);
-
-	/* Quartz likes to munge the pattern phase (as yet unexplained
-	 * why); force it to 0,0 as we've already baked in the correct
-	 * pattern translation into the pattern matrix
-	 */
-	CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0));
-
-	surface->sourcePattern = pattern;
-
-	return DO_PATTERN;
-    } else {
-	return DO_UNSUPPORTED;
-    }
-
-    ASSERT_NOT_REACHED;
-}
-
-static void
-_cairo_nquartz_teardown_source (cairo_nquartz_surface_t *surface,
-				cairo_pattern_t *source)
-{
-    if (surface->sourceImage) {
-	// nothing to do; we don't use sourceImage yet
-    }
-
-    if (surface->sourceShading) {
-	CGShadingRelease(surface->sourceShading);
-	surface->sourceShading = NULL;
-    }
-
-    if (surface->sourcePattern) {
-	CGPatternRelease(surface->sourcePattern);
-	// To tear down the pattern and colorspace
-	CGContextRestoreGState(surface->cgContext);
-
-	surface->sourcePattern = NULL;
-    }
-}
-
-/**
- ** get source/dest image implementation
- **/
-
-static void
-ImageDataReleaseFunc(void *info, const void *data, size_t size)
-{
-    if (data != NULL) {
-	free((void *) data);
-    }
-}
-
-/* Read the image from the surface's front buffer */
-static cairo_int_status_t
-_cairo_nquartz_get_image (cairo_nquartz_surface_t *surface,
-			  cairo_image_surface_t **image_out,
-			  unsigned char **data_out)
-{
-    unsigned char *imageData;
-    cairo_image_surface_t *isurf;
-
-    /* If we weren't constructed with an AGL Context
-     * or a CCGBitmapContext, then we have no way
-     * of doing this
-     */
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext) {
-	AGLContext oldContext;
-	cairo_format_masks_t masks = { 32, 0xff << 24, 0xff << 16, 0xff << 8, 0xff << 0 };
-	unsigned int i;
-
-	oldContext = aglGetCurrentContext();
-	if (oldContext != surface->aglContext)
-	    aglSetCurrentContext(surface->aglContext);
-
-	imageData = (unsigned char *) malloc (surface->extents.width * surface->extents.height * 4);
-	if (!imageData)
-	    return CAIRO_STATUS_NO_MEMORY;
-
-	glReadBuffer (GL_FRONT);
-	glReadPixels (0, 0, surface->extents.width, surface->extents.height,
-		      GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
-		      imageData);
-
-	/* swap lines */
-	/* XXX find some fast code to do this */
-	unsigned int lineSize = surface->extents.width * 4;
-	unsigned char *tmpLine = malloc(lineSize);
-	for (i = 0; i < surface->extents.height / 2; i++) {
-	    unsigned char *l0 = imageData + lineSize * i;
-	    unsigned char *l1 = imageData + (lineSize * (surface->extents.height - i - 1));
-	    memcpy (tmpLine, l0, lineSize);
-	    memcpy (l0, l1, lineSize);
-	    memcpy (l1, tmpLine, lineSize);
-	}
-	free (tmpLine);
-
-	if (oldContext && oldContext != surface->aglContext)
-	    aglSetCurrentContext(oldContext);
-
-	isurf = (cairo_image_surface_t *)_cairo_image_surface_create_with_masks
-	    (imageData,
-	     &masks,
-	     surface->extents.width,
-	     surface->extents.height,
-	     surface->extents.width * 4);
-
-	if (data_out)
-	    *data_out = imageData;
-	else
-	    _cairo_image_surface_assume_ownership_of_data (isurf);
-#else
-    /* no AGL */
-    if (0) {
-#endif
-    } else if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) {
-	unsigned int stride;
-	unsigned int bitinfo;
-	unsigned int bpc, bpp;
-	CGColorSpaceRef colorspace;
-	unsigned int color_comps;
-
-	imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
-#ifdef USE_10_3_WORKAROUNDS
-	bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
-#else
-	bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
-#endif
-	stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
-	bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
-	bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
-
-	// let's hope they don't add YUV under us
-	colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
-	color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
-
-	// XXX TODO: We can handle all of these by converting to
-	// pixman masks, including non-native-endian masks
-	if (bpc != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (bpp != 32 && bpp != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (color_comps != 3 && color_comps != 1)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (bpp == 32 && color_comps == 3 &&
-	    (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
-	    (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_ARGB32,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 32 && color_comps == 3 &&
-		   (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
-		   (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_RGB24,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 8 && color_comps == 1)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_A8,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else {
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    *image_out = isurf;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/**
- ** Cairo surface backend implementations
- **/
-
-static cairo_status_t
-_cairo_nquartz_surface_finish (void *abstract_surface)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    ND((stderr, "_cairo_nquartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext)
-	aglSetCurrentContext(surface->aglContext);
-#endif
-
-    CGContextFlush (surface->cgContext);
-
-    /* Restore our saved gstate that we use to reset clipping */
-    CGContextRestoreGState (surface->cgContext);
-
-    CGContextRelease (surface->cgContext);
-
-    surface->cgContext = NULL;
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext)
-	glFlush();
-
-    surface->aglContext = NULL;
-#endif
-
-    if (surface->imageData) {
-	free (surface->imageData);
-	surface->imageData = NULL;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_acquire_source_image (void *abstract_surface,
-					     cairo_image_surface_t **image_out,
-					     void **image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    //ND((stderr, "%p _cairo_nquartz_surface_acquire_source_image\n", surface));
-
-    *image_extra = NULL;
-
-    return _cairo_nquartz_get_image (surface, image_out, NULL);
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_acquire_dest_image (void *abstract_surface,
-					   cairo_rectangle_int16_t *interest_rect,
-					   cairo_image_surface_t **image_out,
-					   cairo_rectangle_int16_t *image_rect,
-					   void **image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t status;
-    unsigned char *data;
-
-    ND((stderr, "%p _cairo_nquartz_surface_acquire_dest_image\n", surface));
-
-    *image_rect = surface->extents;
-
-    status = _cairo_nquartz_get_image (surface, image_out, &data);
-    if (status)
-	return status;
-
-    *image_extra = data;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_nquartz_surface_release_dest_image (void *abstract_surface,
-					   cairo_rectangle_int16_t *interest_rect,
-					   cairo_image_surface_t *image,
-					   cairo_rectangle_int16_t *image_rect,
-					   void *image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    unsigned char *imageData = (unsigned char *) image_extra;
-
-    //ND((stderr, "%p _cairo_nquartz_surface_release_dest_image\n", surface));
-
-    if (!CGBitmapContextGetData (surface->cgContext)) {
-	CGDataProviderRef dataProvider;
-	CGImageRef img;
-
-	dataProvider = CGDataProviderCreateWithData (NULL, imageData,
-						     surface->extents.width * surface->extents.height * 4,
-						     ImageDataReleaseFunc);
-
-	img = CGImageCreate (surface->extents.width, surface->extents.height,
-			     8, 32,
-			     surface->extents.width * 4,
-			     CGColorSpaceCreateDeviceRGB(),
-			     kCGImageAlphaPremultipliedFirst,
-			     dataProvider,
-			     NULL,
-			     false,
-			     kCGRenderingIntentDefault);
-
-	CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy);
-
-	CGContextDrawImage (surface->cgContext,
-			    CGRectMake (0, 0, surface->extents.width, surface->extents.height),
-			    img);
-
-	CGImageRelease (img);
-	CGDataProviderRelease (dataProvider);
-
-	ND((stderr, "Image for surface %p was recovered from a bitmap\n", surface));
-    }
-
-    cairo_surface_destroy ((cairo_surface_t *) image);
-}
-
-static cairo_surface_t *
-_cairo_nquartz_surface_create_similar (void *abstract_surface,
-				       cairo_content_t content,
-				       int width,
-				       int height)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    cairo_format_t format;
-
-    if (content == CAIRO_CONTENT_COLOR_ALPHA)
-	format = CAIRO_FORMAT_ARGB32;
-    else if (content == CAIRO_CONTENT_COLOR)
-	format = CAIRO_FORMAT_RGB24;
-    else if (content == CAIRO_CONTENT_ALPHA)
-	format = CAIRO_FORMAT_A8;
-    else
-	return NULL;
-
-    return cairo_nquartz_surface_create (format, width, height);
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_clone_similar (void *abstract_surface,
-				      cairo_surface_t *src,
-				      int              src_x,
-				      int              src_y,
-				      int              width,
-				      int              height,
-				      cairo_surface_t **clone_out)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_nquartz_surface_t *new_surface = NULL;
-    cairo_format_t new_format;
-
-    CGImageRef quartz_image = NULL;
-    cairo_surface_t *surface_to_release = NULL;
-
-    if (cairo_surface_is_nquartz (src)) {
-	cairo_nquartz_surface_t *qsurf = (cairo_nquartz_surface_t *) src;
-	quartz_image = CGBitmapContextCreateImage (qsurf->cgContext);
-	new_format = CAIRO_FORMAT_ARGB32;  /* XXX bogus; recover a real format from the image */
-    } else if (_cairo_surface_is_image (src)) {
-	cairo_image_surface_t *isurf = (cairo_image_surface_t *) src;
-	CGDataProviderRef dataProvider;
-	CGColorSpaceRef cgColorspace;
-	CGBitmapInfo bitinfo;
-	int bitsPerComponent, bitsPerPixel;
-
-	if (isurf->format == CAIRO_FORMAT_ARGB32) {
-	    cgColorspace = CGColorSpaceCreateDeviceRGB();
-	    bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 32;
-	} else if (isurf->format == CAIRO_FORMAT_RGB24) {
-	    cgColorspace = CGColorSpaceCreateDeviceRGB();
-	    bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 32;
-	} else if (isurf->format == CAIRO_FORMAT_A8) {
-	    cgColorspace = CGColorSpaceCreateDeviceGray();
-	    bitinfo = kCGImageAlphaNone;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 8;
-	} else {
-	    /* SUPPORT A1, maybe */
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-
-	new_format = isurf->format;
-
-	dataProvider = CGDataProviderCreateWithData (NULL,
-						     isurf->data,
-						     isurf->height * isurf->stride,
-						     NULL);
-
-	quartz_image = CGImageCreate (isurf->width, isurf->height,
-				      bitsPerComponent,
-				      bitsPerPixel,
-				      isurf->stride,
-				      cgColorspace,
-				      bitinfo,
-				      dataProvider,
-				      NULL,
-				      false,
-				      kCGRenderingIntentDefault);
-	CGDataProviderRelease (dataProvider);
-	CGColorSpaceRelease (cgColorspace);
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    if (!quartz_image)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    new_surface = (cairo_nquartz_surface_t *)
-	cairo_nquartz_surface_create (new_format,
-				      CGImageGetWidth (quartz_image),
-				      CGImageGetHeight (quartz_image));
-    if (!new_surface || new_surface->base.status)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    CGContextSetCompositeOperation (new_surface->cgContext,
-				    kPrivateCGCompositeCopy);
-
-    nquartz_image_to_png (quartz_image, NULL);
-
-    CGContextDrawImage (new_surface->cgContext,
-			CGRectMake (src_x, src_y, width, height),
-			quartz_image);
-    CGImageRelease (quartz_image);
-
-    *clone_out = (cairo_surface_t*) new_surface;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_get_extents (void *abstract_surface,
-				    cairo_rectangle_int16_t *extents)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    *extents = surface->extents;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_paint (void *abstract_surface,
-			      cairo_operator_t op,
-			      cairo_pattern_t *source)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_paint op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    CGRect bounds = CGContextGetClipBoundingBox (surface->cgContext);
-
-    action = _cairo_nquartz_setup_source (surface, source);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
-							  surface->extents.y,
-							  surface->extents.width,
-							  surface->extents.height));
-    } else if (action == DO_SHADING) {
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    ND((stderr, "-- paint\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_fill (void *abstract_surface,
-			     cairo_operator_t op,
-			     cairo_pattern_t *source,
-			     cairo_path_fixed_t *path,
-			     cairo_fill_rule_t fill_rule,
-			     double tolerance,
-			     cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_fill op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSaveGState (surface->cgContext);
-
-    CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_UNSUPPORTED) {
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    CGContextBeginPath (surface->cgContext);
-    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextFillPath (surface->cgContext);
-	else
-	    CGContextEOFillPath (surface->cgContext);
-    } else if (action == DO_SHADING) {
-
-	// we have to clip and then paint the shading; we can't fill
-	// with the shading
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextClip (surface->cgContext);
-	else
-	    CGContextEOClip (surface->cgContext);
-
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    ND((stderr, "-- fill\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_stroke (void *abstract_surface,
-			       cairo_operator_t op,
-			       cairo_pattern_t *source,
-			       cairo_path_fixed_t *path,
-			       cairo_stroke_style_t *style,
-			       cairo_matrix_t *ctm,
-			       cairo_matrix_t *ctm_inverse,
-			       double tolerance,
-			       cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSaveGState (surface->cgContext);
-
-    // Turning antialiasing off causes misrendering with
-    // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels)
-    //CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-    CGContextSetLineWidth (surface->cgContext, style->line_width);
-    CGContextSetLineCap (surface->cgContext, _cairo_nquartz_cairo_line_cap_to_quartz (style->line_cap));
-    CGContextSetLineJoin (surface->cgContext, _cairo_nquartz_cairo_line_join_to_quartz (style->line_join));
-    CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
-
-    if (style->dash && style->num_dashes) {
-#define STATIC_DASH 32
-	float sdash[STATIC_DASH];
-	float *fdash = sdash;
-	int k;
-	if (style->num_dashes > STATIC_DASH)
-	    fdash = malloc (sizeof(float)*style->num_dashes);
-
-	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 (fdash != sdash)
-	    free (fdash);
-    }
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_UNSUPPORTED) {
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    CGContextBeginPath (surface->cgContext);
-    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextStrokePath (surface->cgContext);
-    } else if (action == DO_SHADING) {
-	// we have to clip and then paint the shading; first we have to convert
-	// the stroke to a path that we can fill
-	CGContextReplacePathWithStrokedPath (surface->cgContext);
-	CGContextClip (surface->cgContext);
-
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    ND((stderr, "-- stroke\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_show_glyphs (void *abstract_surface,
-				    cairo_operator_t op,
-				    cairo_pattern_t *source,
-				    cairo_glyph_t *glyphs,
-				    int num_glyphs,
-				    cairo_scaled_font_t *scaled_font)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-    int i;
-
-    if (num_glyphs <= 0)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (!_cairo_scaled_font_is_atsui (scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    CGContextSaveGState (surface->cgContext);
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-    } else if (action == DO_SHADING) {
-	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
-    } else {
-	/* Unsupported */
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    double y_height = surface->extents.height;
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
-    ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
-    CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
-
-    CGContextSetFont (surface->cgContext, cgfref);
-    CGFontRelease (cgfref);
-
-    /* So this should include the size; I don't know if I need to extract the
-     * size from this and call CGContextSetFontSize.. will I get crappy hinting
-     * with this 1.0 size business?  Or will CG just multiply that size into the
-     * text matrix?
-     */
-    //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
-    CGAffineTransform cairoTextTransform, textTransform;
-    _cairo_nquartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
-
-    textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
-    textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
-    textTransform = CGAffineTransformConcat (cairoTextTransform, textTransform);
-
-    CGContextSetTextMatrix (surface->cgContext, textTransform);
-    CGContextSetFontSize (surface->cgContext, 1.0);
-
-    // XXXtodo/perf: stack storage for glyphs/sizes
-#define STATIC_BUF_SIZE 64
-    CGGlyph glyphs_static[STATIC_BUF_SIZE];
-    CGSize cg_advances_static[STATIC_BUF_SIZE];
-    CGGlyph *cg_glyphs = &glyphs_static[0];
-    CGSize *cg_advances = &cg_advances_static[0];
-
-    if (num_glyphs > STATIC_BUF_SIZE) {
-	cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
-	cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
-    }
-
-    float xprev = glyphs[0].x;
-    float yprev = glyphs[0].y;
-
-    cg_glyphs[0] = glyphs[0].index;
-    cg_advances[0].width = 0;
-    cg_advances[0].height = 0;
-
-    for (i = 1; i < num_glyphs; i++) {
-	cg_glyphs[i] = glyphs[i].index;
-        float xf = glyphs[i].x;
-        float yf = glyphs[i].y;
-	cg_advances[i-1].width = xf - xprev;
-	cg_advances[i-1].height = yf - yprev;
-	xprev = xf;
-	yprev = yf;
-    }
-
-#if 0
-    for (i = 0; i < num_glyphs; i++) {
-	ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height));
-    }
-#endif
-
-    CGContextShowGlyphsWithAdvances (surface->cgContext,
-				     cg_glyphs,
-				     cg_advances,
-				     num_glyphs);
-
-    if (cg_glyphs != &glyphs_static[0]) {
-	free (cg_glyphs);
-	free (cg_advances);
-    }
-
-    if (action == DO_SHADING)
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_mask (void *abstract_surface,
-			     cairo_operator_t op,
-			     cairo_pattern_t *source,
-			     cairo_pattern_t *mask)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-
-    ND((stderr, "%p _cairo_nquartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type));
-
-    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
-	/* This is easy; we just need to paint with the alpha. */
-	cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
-
-	CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha);
-    } else {
-	/* So, CGContextClipToMask is not present in 10.3.9, so we're
-	 * doomed; if we have imageData, we can do fallback, otherwise
-	 * just pretend success.
-	 */
-	if (surface->imageData)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    rv = _cairo_nquartz_surface_paint (surface, op, source);
-
-    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
-	CGContextSetAlpha (surface->cgContext, 1.0);
-    }
-
-    ND((stderr, "-- mask\n"));
-
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_intersect_clip_path (void *abstract_surface,
-					    cairo_path_fixed_t *path,
-					    cairo_fill_rule_t fill_rule,
-					    double tolerance,
-					    cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    ND((stderr, "%p _cairo_nquartz_surface_intersect_clip_path path: %p\n", surface, path));
-
-    if (path == NULL) {
-	/* If we're being asked to reset the clip, we can only do it
-	 * by restoring the gstate to our previous saved one, and
-	 * saving it again.
-	 *
-	 * Note that this assumes that ALL nquartz surface creation
-	 * functions will do a SaveGState first; we do this in create_internal.
-	 */
-	CGContextRestoreGState (surface->cgContext);
-	CGContextSaveGState (surface->cgContext);
-    } else {
-	CGContextBeginPath (surface->cgContext);
-	_cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextClip (surface->cgContext);
-	else
-	    CGContextEOClip (surface->cgContext);
-    }
-
-    ND((stderr, "-- intersect_clip_path\n"));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-// XXXtodo implement show_page; need to figure out how to handle begin/end
-
-static const struct _cairo_surface_backend cairo_nquartz_surface_backend = {
-    CAIRO_SURFACE_TYPE_NQUARTZ,
-    _cairo_nquartz_surface_create_similar,
-    _cairo_nquartz_surface_finish,
-    _cairo_nquartz_surface_acquire_source_image,
-    NULL, /* release_source_image */
-    _cairo_nquartz_surface_acquire_dest_image,
-    _cairo_nquartz_surface_release_dest_image,
-    _cairo_nquartz_surface_clone_similar,
-    NULL, /* composite */
-    NULL, /* fill_rectangles */
-    NULL, /* composite_trapezoids */
-    NULL, /* copy_page */
-    NULL, /* show_page */
-    NULL, /* set_clip_region */
-    _cairo_nquartz_surface_intersect_clip_path,
-    _cairo_nquartz_surface_get_extents,
-    NULL, /* old_show_glyphs */
-    NULL, /* get_font_options */
-    NULL, /* flush */
-    NULL, /* mark_dirty_rectangle */
-    NULL, /* scaled_font_fini */
-    NULL, /* scaled_glyph_fini */
-
-    _cairo_nquartz_surface_paint,
-    _cairo_nquartz_surface_mask,
-    _cairo_nquartz_surface_stroke,
-    _cairo_nquartz_surface_fill,
-    _cairo_nquartz_surface_show_glyphs,
-
-    NULL, /* snapshot */
-};
-
-cairo_bool_t
-cairo_surface_is_nquartz (cairo_surface_t *surf)
-{
-    return (surf->backend == &cairo_nquartz_surface_backend);
-}
-
-static cairo_nquartz_surface_t *
-_cairo_nquartz_surface_create_internal (CGContextRef cgContext,
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-					AGLContext aglContext,
-#else
-					void * unused,
-#endif
-					cairo_content_t content,
-					unsigned int width,
-					unsigned int height,
-					cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surface;
-
-    /* Init the base surface */
-    surface = malloc(sizeof(cairo_nquartz_surface_t));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
-
-    memset(surface, 0, sizeof(cairo_nquartz_surface_t));
-
-    _cairo_surface_init(&surface->base, &cairo_nquartz_surface_backend,
-			content);
-
-    /* Save our extents */
-    surface->extents.x = surface->extents.y = 0;
-    surface->extents.width = width;
-    surface->extents.height = height;
-
-    if (!y_grows_down) {
-	/* Then make the CGContext sane */
-	CGContextTranslateCTM (cgContext, 0.0, surface->extents.height);
-	CGContextScaleCTM (cgContext, 1.0, -1.0);
-    }
-
-    /* Save so we can always get back to a known-good CGContext -- this is
-     * required for proper behaviour of intersect_clip_path(NULL)
-     */
-    CGContextSaveGState (cgContext);
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    surface->aglContext = aglContext;
-#endif
-    surface->cgContext = cgContext;
-    surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
-
-    surface->imageData = NULL;
-
-    return surface;
-}
-					 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-cairo_surface_t *
-cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
-					      unsigned int width,
-					      unsigned int height,
-					      cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surf;
-    CGSize sz;
-
-    /* Make our CGContext from the AGL context */
-    sz.width = width;
-    sz.height = height;
-
-    CGContextRef cgc = CGGLContextCreate (aglContext, sz, NULL /* device RGB colorspace */);
-
-    surf = _cairo_nquartz_surface_create_internal (cgc, aglContext, CAIRO_CONTENT_COLOR_ALPHA,
-						   width, height, y_grows_down);
-    if (!surf) {
-	CGContextRelease (cgc);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    return (cairo_surface_t *) surf;
-}
-#endif
-
-cairo_surface_t *
-cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
-					     unsigned int width,
-					     unsigned int height,
-					     cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surf;
-
-    CGContextRetain (cgContext);
-
-    surf = _cairo_nquartz_surface_create_internal (cgContext, NULL, CAIRO_CONTENT_COLOR_ALPHA,
-						   width, height, y_grows_down);
-    if (!surf) {
-	CGContextRelease (cgContext);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    return (cairo_surface_t *) surf;
-}
-
-cairo_surface_t *
-cairo_nquartz_surface_create (cairo_format_t format,
-			      unsigned int width,
-			      unsigned int height)
-{
-    cairo_nquartz_surface_t *surf;
-    CGContextRef cgc;
-    CGColorSpaceRef cgColorspace;
-    CGBitmapInfo bitinfo;
-    void *imageData;
-    int stride;
-    int bitsPerComponent;
-
-    if (format == CAIRO_FORMAT_ARGB32) {
-	cgColorspace = CGColorSpaceCreateDeviceRGB();
-	stride = width * 4;
-	bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_RGB24) {
-	cgColorspace = CGColorSpaceCreateDeviceRGB();
-	stride = width * 4;
-	bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_A8) {
-	cgColorspace = CGColorSpaceCreateDeviceGray();
-	if (width % 4 == 0)
-	    stride = width;
-	else
-	    stride = (width & ~3) + 4;
-	bitinfo = kCGImageAlphaNone;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_A1) {
-	/* I don't think we can usefully support this, as defined by
-	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
-	 * quantities.
-	 */
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    } else {
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    imageData = malloc (height * stride);
-    if (!imageData) {
-	CGColorSpaceRelease (cgColorspace);
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    cgc = CGBitmapContextCreate (imageData,
-				 width,
-				 height,
-				 bitsPerComponent,
-				 stride,
-				 cgColorspace,
-				 bitinfo);
-    CGColorSpaceRelease (cgColorspace);
-
-    if (!cgc) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    surf = _cairo_nquartz_surface_create_internal (cgc, NULL, _cairo_content_from_format (format),
-						   width, height, FALSE);
-    if (!surf) {
-	CGContextRelease (cgc);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    surf->imageData = imageData;
-
-    return (cairo_surface_t *) surf;
-}
-
-CGContextRef
-cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf)
-{
-    cairo_nquartz_surface_t *nquartz = (cairo_nquartz_surface_t*)surf;
-
-    if (!cairo_surface_is_nquartz(surf))
-	return NULL;
-
-    return nquartz->cgContext;
-}
-
-
-/* Debug stuff */
-
-#ifdef NQUARTZ_DEBUG
-
-#include <Movies.h>
-
-void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest)
-{
-    Handle  dataRef = NULL;
-    OSType  dataRefType;
-    CFStringRef inPath = CFStringCreateWithCString(NULL, dest, kCFStringEncodingASCII);
-
-    GraphicsExportComponent grex = 0;
-    unsigned long sizeWritten;
-
-    ComponentResult result;
-
-    // create the data reference
-    result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle,
-						    0, &dataRef, &dataRefType);
-
-    if (NULL != dataRef && noErr == result) {
-	// get the PNG exporter
-	result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG,
-				       &grex);
-
-	if (grex) {
-	    // tell the exporter where to find its source image
-	    result = GraphicsExportSetInputCGImage(grex, inImageRef);
-
-	    if (noErr == result) {
-		// tell the exporter where to save the exporter image
-		result = GraphicsExportSetOutputDataReference(grex, dataRef,
-							      dataRefType);
-
-		if (noErr == result) {
-		    // write the PNG file
-		    result = GraphicsExportDoExport(grex, &sizeWritten);
-		}
-	    }
-
-	    // remember to close the component
-	    CloseComponent(grex);
-	}
-
-	// remember to dispose of the data reference handle
-	DisposeHandle(dataRef);
-    }
-}
-#endif
-
-void
-nquartz_image_to_png (CGImageRef imgref, char *dest)
-{
-#if 0
-    static int sctr = 0;
-    char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png";
-
-    if (dest == NULL) {
-	fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr);
-	sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr);
-	sctr++;
-	dest = sptr;
-    }
-
-    ExportCGImageToPNGFile(imgref, dest);
-#endif
-}
-
-void
-nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest)
-{
-#if 0
-    static int sctr = 0;
-    char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png";
-
-    if (nq->base.type != CAIRO_SURFACE_TYPE_NQUARTZ) {
-	fprintf (stderr, "** nquartz_surface_to_png: surface %p isn't nquartz!\n", nq);
-	return;
-    }
-
-    if (dest == NULL) {
-	fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr);
-	sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr);
-	sctr++;
-	dest = sptr;
-    }
-
-    CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext);
-    if (imgref == NULL) {
-	fprintf (stderr, "nquartz surface at %p is not a bitmap context!\n", nq);
-	return;
-    }
-
-    ExportCGImageToPNGFile(imgref, dest);
-
-    CGImageRelease(imgref);
-#endif
-}
-
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-nquartz.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright  2006 Mozilla Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Mozilla Corporation.
- *
- * Contributor(s):
- *      Vladimir Vukicevic <vladimir@mozilla.com>
- */
-
-#ifndef CAIRO_NQUARTZ_H
-#define CAIRO_NQUARTZ_H
-
-#include <cairo.h>
-
-#if CAIRO_HAS_NQUARTZ_SURFACE
-
-#include <Carbon/Carbon.h>
-
-#include <AGL/agl.h>
-
-CAIRO_BEGIN_DECLS
-
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create (cairo_format_t format,
-                              unsigned int width,
-                              unsigned int height);
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
-                                              unsigned int width,
-                                              unsigned int height,
-                                              cairo_bool_t y_grows_down);
-#endif
-
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
-                                             unsigned int width,
-                                             unsigned int height,
-                                             cairo_bool_t y_grows_down);
-
-cairo_public cairo_bool_t
-cairo_surface_is_nquartz (cairo_surface_t *surf);
-
-cairo_public CGContextRef
-cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf);
-
-CAIRO_END_DECLS
-
-#else  /* CAIRO_HAS_NQUARTZ_SURFACE */
-# error Cairo was not compiled with support for the nquartz backend
-#endif /* CAIRO_HAS_NQUARTZ_SURFACE */
-
-#endif /* CAIRO_NQUARTZ_H */
--- a/gfx/cairo/cairo/src/cairo-os2-surface.c
+++ b/gfx/cairo/cairo/src/cairo-os2-surface.c
@@ -64,21 +64,21 @@
  * and termination, if the code is built to be a DLL.
  * (if BUILD_CAIRO_DLL is defined)
  */
 
 /* Initialization counter: */
 static int cairo_os2_initialization_count = 0;
 
 /* The mutex semaphores Cairo uses all around: */
-HMTX cairo_toy_font_face_hash_table_mutex = 0;
-HMTX cairo_scaled_font_map_mutex = 0;
+HMTX _cairo_scaled_font_map_mutex = 0;
 HMTX _global_image_glyph_cache_mutex = 0;
+HMTX _cairo_font_face_mutex = 0;
 #ifdef CAIRO_HAS_FT_FONT
-HMTX cairo_ft_unscaled_font_map_mutex = 0;
+HMTX _cairo_ft_unscaled_font_map_mutex = 0;
 #endif
 
 static void inline
 DisableFPUException (void)
 {
     unsigned short usCW;
 
     /* Some OS/2 PM API calls modify the FPU Control Word,
@@ -101,23 +101,23 @@ cairo_os2_init (void)
     cairo_os2_initialization_count++;
     if (cairo_os2_initialization_count > 1) return;
 
     DisableFPUException ();
 
     /* Create the mutex semaphores we'll use! */
 
     /* cairo-font.c: */
-    DosCreateMutexSem (NULL, &cairo_toy_font_face_hash_table_mutex, 0, FALSE);
-    DosCreateMutexSem (NULL, &cairo_scaled_font_map_mutex, 0, FALSE);
+    DosCreateMutexSem (NULL, &_cairo_scaled_font_map_mutex, 0, FALSE);
     DosCreateMutexSem (NULL, &_global_image_glyph_cache_mutex, 0, FALSE);
+    DosCreateMutexSem (NULL, &_cairo_font_face_mutex, 0, FALSE);
 
 #ifdef CAIRO_HAS_FT_FONT
     /* cairo-ft-font.c: */
-    DosCreateMutexSem (NULL, &cairo_ft_unscaled_font_map_mutex, 0, FALSE);
+    DosCreateMutexSem (NULL, &_cairo_ft_unscaled_font_map_mutex, 0, FALSE);
 #endif
 
     /* Initialize FontConfig */
     FcInit ();
 }
 
 cairo_public void
 cairo_os2_fini (void)
@@ -134,34 +134,34 @@ cairo_os2_fini (void)
     /* (Check cairo_debug_reset_static_date () for an example of this!) */
     _cairo_font_reset_static_data ();
 #ifdef CAIRO_HAS_FT_FONT
     _cairo_ft_font_reset_static_data ();
 #endif
 
     /* Destroy the mutex semaphores we've created! */
     /* cairo-font.c: */
-    if (cairo_toy_font_face_hash_table_mutex) {
-        DosCloseMutexSem (cairo_toy_font_face_hash_table_mutex);
-        cairo_toy_font_face_hash_table_mutex = 0;
-    }
-    if (cairo_scaled_font_map_mutex) {
-        DosCloseMutexSem (cairo_scaled_font_map_mutex);
-        cairo_scaled_font_map_mutex = 0;
+    if (_cairo_scaled_font_map_mutex) {
+        DosCloseMutexSem (_cairo_scaled_font_map_mutex);
+        _cairo_scaled_font_map_mutex = 0;
     }
     if (_global_image_glyph_cache_mutex) {
         DosCloseMutexSem (_global_image_glyph_cache_mutex);
         _global_image_glyph_cache_mutex = 0;
     }
+    if (_cairo_font_face_mutex) {
+        DosCloseMutexSem (_cairo_font_face_mutex);
+        _cairo_font_face_mutex = 0;
+    }
 
 #ifdef CAIRO_HAS_FT_FONT
     /* cairo-ft-font.c: */
-    if (cairo_ft_unscaled_font_map_mutex) {
-        DosCloseMutexSem (cairo_ft_unscaled_font_map_mutex);
-        cairo_ft_unscaled_font_map_mutex = 0;
+    if (_cairo_ft_unscaled_font_map_mutex) {
+        DosCloseMutexSem (_cairo_ft_unscaled_font_map_mutex);
+        _cairo_ft_unscaled_font_map_mutex = 0;
     }
 #endif
 
     /* Uninitialize FontConfig */
     FcFini ();
 
 #ifdef __WATCOMC__
     /* It can happen that the libraries we use have memory leaks,
--- a/gfx/cairo/cairo/src/cairo-os2.h
+++ b/gfx/cairo/cairo/src/cairo-os2.h
@@ -189,13 +189,15 @@ cairo_os2_surface_set_manual_window_refr
 /* cairo_os2_surface_get_manual_window_refresh () :                 */
 /*                                                                  */
 /* This API can return the current mode of the surface. It is       */
 /* TRUE by default.                                                 */
 
 cairo_public cairo_bool_t
 cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface);
 
+#else  /* CAIRO_HAS_OS2_SURFACE */
+# error Cairo was not compiled with support for the OS/2 backend
 #endif /* CAIRO_HAS_OS2_SURFACE */
 
 CAIRO_END_DECLS
 
 #endif /* _CAIRO_OS2_H_ */
--- a/gfx/cairo/cairo/src/cairo-output-stream.c
+++ b/gfx/cairo/cairo/src/cairo-output-stream.c
@@ -219,16 +219,20 @@ int
 _cairo_dtostr (char *buffer, size_t size, double d)
 {
   struct lconv *locale_data;
   const char *decimal_point;
   int decimal_point_len;
   char *p;
   int decimal_len;
 
+  /* Omit the minus sign from negative zero. */
+  if (d == 0.0)
+      d = 0.0;
+
   snprintf (buffer, size, "%f", d);
 
   locale_data = localeconv ();
   decimal_point = locale_data->decimal_point;
   decimal_point_len = strlen (decimal_point);
 
   assert (decimal_point_len != 0);
   p = buffer;
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -65,16 +65,17 @@ typedef struct _cairo_paginated_surface 
     /* Paginated-surface specific functions for the target */
     const cairo_paginated_surface_backend_t *backend;
 
     /* A cairo_meta_surface to record all operations. To be replayed
      * against target, and also against image surface as necessary for
      * fallbacks. */
     cairo_surface_t *meta;
 
+    int page_num;
     cairo_bool_t page_is_blank;
 
 } cairo_paginated_surface_t;
 
 const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
 
 static cairo_int_status_t
 _cairo_paginated_surface_show_page (void *abstract_surface);
@@ -117,16 +118,17 @@ cairo_surface_t *
     surface->height = height;
 
     surface->backend = backend;
 
     surface->meta = _cairo_meta_surface_create (content, width, height);
     if (cairo_surface_status (surface->meta))
 	goto FAIL_CLEANUP_SURFACE;
 
+    surface->page_num = 1;
     surface->page_is_blank = TRUE;
 
     return &surface->base;
 
   FAIL_CLEANUP_SURFACE:
     free (surface);
   FAIL:
     _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -150,22 +152,32 @@ cairo_surface_t *
 
     return paginated_surface->target;
 }
 
 static cairo_status_t
 _cairo_paginated_surface_finish (void *abstract_surface)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (surface->page_is_blank == FALSE || surface->page_num == 1)
+	status = _cairo_paginated_surface_show_page (abstract_surface);
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	cairo_surface_finish (surface->target);
+
+    if (status == CAIRO_STATUS_SUCCESS)
+	cairo_surface_finish (surface->meta);
+
+    cairo_surface_destroy (surface->target);
 
     cairo_surface_destroy (surface->meta);
 
-    cairo_surface_destroy (surface->target);
-
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static cairo_surface_t *
 _cairo_paginated_surface_create_image_surface (void	       *abstract_surface,
 					       int		width,
 					       int		height)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
@@ -283,27 +295,27 @@ static cairo_int_status_t
     cairo_paginated_surface_t *surface = abstract_surface;
 
     status = _start_page (surface);
     if (status)
 	return status;
 
     _paint_page (surface);
 
+    surface->page_num++;
+
     /* XXX: It might make sense to add some suport here for calling
      * _cairo_surface_copy_page on the target surface. It would be an
      * optimization for the output, (so that PostScript could include
      * copypage, for example), but the interaction with image
      * fallbacks gets tricky. For now, we just let the target see a
      * show_page and we implement the copying by simply not destroying
      * the meta-surface. */
 
-    _cairo_surface_show_page (surface->target);
-
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_surface_show_page (surface->target);
 }
 
 static cairo_int_status_t
 _cairo_paginated_surface_show_page (void *abstract_surface)
 {
     cairo_status_t status;
     cairo_paginated_surface_t *surface = abstract_surface;
 
@@ -317,16 +329,17 @@ static cairo_int_status_t
 
     cairo_surface_destroy (surface->meta);
 
     surface->meta = _cairo_meta_surface_create (surface->content,
 						surface->width, surface->height);
     if (cairo_surface_status (surface->meta))
 	return cairo_surface_status (surface->meta);
 
+    surface->page_num++;
     surface->page_is_blank = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_paginated_surface_intersect_clip_path (void	  *abstract_surface,
 					      cairo_path_fixed_t *path,
@@ -437,26 +450,41 @@ static cairo_int_status_t
 _cairo_paginated_surface_show_glyphs (void			*abstract_surface,
 				      cairo_operator_t		 op,
 				      cairo_pattern_t		*source,
 				      cairo_glyph_t		*glyphs,
 				      int			 num_glyphs,
 				      cairo_scaled_font_t	*scaled_font)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
 
     /* Optimize away erasing of nothing. */
     if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
 	return CAIRO_STATUS_SUCCESS;
 
     surface->page_is_blank = FALSE;
 
-    return _cairo_surface_show_glyphs (surface->meta, op, source,
-				       glyphs, num_glyphs,
-				       scaled_font);
+    /* Since this is a "wrapping" surface, we're calling back into
+     * _cairo_surface_show_glyphs from within a call to the same.
+     * Since _cairo_surface_show_glyphs acquires a mutex, we release
+     * and re-acquire the mutex around this nested call.
+     *
+     * Yes, this is ugly, but we consider it pragmatic as compared to
+     * adding locking code to all 18 surface-backend-specific
+     * show_glyphs functions, (which would get less testing and likely
+     * lead to bugs).
+     */
+    CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
+    status = _cairo_surface_show_glyphs (surface->meta, op, source,
+					 glyphs, num_glyphs,
+					 scaled_font);
+    CAIRO_MUTEX_LOCK (scaled_font->mutex);
+
+    return status;
 }
 
 static cairo_surface_t *
 _cairo_paginated_surface_snapshot (void *abstract_other)
 {
     cairo_paginated_surface_t *other = abstract_other;
 
     /* XXX: Just making a snapshot of other->meta is what we really
--- a/gfx/cairo/cairo/src/cairo-path-fill.c
+++ b/gfx/cairo/cairo/src/cairo-path-fill.c
@@ -30,16 +30,17 @@
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
+#include "cairo-path-fixed-private.h"
 
 typedef struct cairo_filler {
     double tolerance;
     cairo_traps_t *traps;
 
     cairo_point_t current_point;
 
     cairo_polygon_t polygon;
@@ -164,25 +165,35 @@ static cairo_status_t
 
     status = _cairo_polygon_close (polygon);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_int_status_t
+_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
+				  cairo_traps_t		*traps);
+
 cairo_status_t
 _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
 				 cairo_fill_rule_t   fill_rule,
 				 double              tolerance,
 				 cairo_traps_t      *traps)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_filler_t filler;
 
+    /* Before we do anything else, we use a special-case filler for
+     * a device-axis aligned rectangle if possible. */
+    status = _cairo_path_fixed_fill_rectangle (path, traps);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
     _cairo_filler_init (&filler, tolerance, traps);
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_filler_move_to,
 					  _cairo_filler_line_to,
 					  _cairo_filler_curve_to,
 					  _cairo_filler_close_path,
@@ -200,8 +211,89 @@ cairo_status_t
     if (status)
 	goto BAIL;
 
 BAIL:
     _cairo_filler_fini (&filler);
 
     return status;
 }
+
+/* This special-case filler supports only a path that describes a
+ * device-axis aligned rectangle. It exists to avoid the overhead of
+ * the general tessellator when drawing very common rectangles.
+ *
+ * If the path described anything but a device-axis aligned rectangle,
+ * this function will return CAIRO_INT_STATUS_UNSUPPORTED.
+ */
+static cairo_int_status_t
+_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
+				  cairo_traps_t		*traps)
+{
+    cairo_path_buf_t *buf = path->buf_head;
+    int final;
+
+    /* Ensure the path has the operators we expect for a rectangular path.
+     */
+    if (buf == NULL || buf->num_ops < 5)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO ||
+	buf->op[1] != CAIRO_PATH_OP_LINE_TO ||
+	buf->op[2] != CAIRO_PATH_OP_LINE_TO ||
+	buf->op[3] != CAIRO_PATH_OP_LINE_TO)
+    {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* Now, there are choices. The rectangle might end with a LINE_TO
+     * (to the original point), but this isn't required. If it
+     * doesn't, then it must end with a CLOSE_PATH. */
+    if (buf->op[4] == CAIRO_PATH_OP_LINE_TO) {
+	if (buf->points[4].x != buf->points[0].x ||
+	    buf->points[4].y != buf->points[0].y)
+	{
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+    } else if (buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* Finally, a trailing CLOSE_PATH or MOVE_TO after the rectangle
+     * is fine. But anything more than that means we must return
+     * unsupported. */
+    final = 5;
+    if (final < buf->num_ops &&
+	buf->op[final] == CAIRO_PATH_OP_CLOSE_PATH)
+    {
+	final++;
+    }
+    if (final < buf->num_ops &&
+	buf->op[final] == CAIRO_PATH_OP_MOVE_TO)
+    {
+	final++;
+    }
+    if (final < buf->num_ops)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Now that we've verified the operators, we must ensure that the
+     * path coordinates are consistent with a rectangle. There are two
+     * choices here. */
+    if (buf->points[0].y == buf->points[1].y &&
+	buf->points[1].x == buf->points[2].x &&
+	buf->points[2].y == buf->points[3].y &&
+	buf->points[3].x == buf->points[0].x)
+    {
+	return _cairo_traps_tessellate_convex_quad (traps,
+						    buf->points);
+    }
+
+    if (buf->points[0].x == buf->points[1].x &&
+	buf->points[1].y == buf->points[2].y &&
+	buf->points[2].x == buf->points[3].x &&
+	buf->points[3].y == buf->points[0].y)
+    {
+	return _cairo_traps_tessellate_convex_quad (traps,
+						    buf->points);
+    }
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
--- a/gfx/cairo/cairo/src/cairo-path-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-path-fixed-private.h
@@ -37,39 +37,35 @@
 #define CAIRO_PATH_FIXED_PRIVATE_H
 
 typedef enum cairo_path_op {
     CAIRO_PATH_OP_MOVE_TO = 0,
     CAIRO_PATH_OP_LINE_TO = 1,
     CAIRO_PATH_OP_CURVE_TO = 2,
     CAIRO_PATH_OP_CLOSE_PATH = 3
 } __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
+/* XXX Shall we just not use char instead of hoping for __attribute__ working? */
 
-#define CAIRO_PATH_BUF_SIZE 64
+/* make cairo_path_fixed fit a 512 bytes.  about 50 items */
+#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \
+			   / (sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
 
-typedef struct _cairo_path_op_buf {
+typedef struct _cairo_path_buf {
+    struct _cairo_path_buf *next, *prev;
     int num_ops;
+    int num_points;
+
     cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
-
-    struct _cairo_path_op_buf *next, *prev;
-} cairo_path_op_buf_t;
-
-typedef struct _cairo_path_arg_buf {
-    int num_points;
     cairo_point_t points[CAIRO_PATH_BUF_SIZE];
 
-    struct _cairo_path_arg_buf *next, *prev;
-} cairo_path_arg_buf_t;
+} cairo_path_buf_t;
 
 struct _cairo_path_fixed {
-    cairo_path_op_buf_t *op_buf_head;
-    cairo_path_op_buf_t *op_buf_tail;
-
-    cairo_path_arg_buf_t *arg_buf_head;
-    cairo_path_arg_buf_t *arg_buf_tail;
-
     cairo_point_t last_move_point;
     cairo_point_t current_point;
     unsigned int has_current_point	: 1;
     unsigned int has_curve_to		: 1;
+
+    cairo_path_buf_t *buf_tail;
+    cairo_path_buf_t  buf_head[1];
 };
 
 #endif /* CAIRO_PATH_FIXED_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-path-fixed.c
+++ b/gfx/cairo/cairo/src/cairo-path-fixed.c
@@ -43,97 +43,80 @@
 /* private functions */
 static cairo_status_t
 _cairo_path_fixed_add (cairo_path_fixed_t *path,
 		       cairo_path_op_t 	   op,
 		       cairo_point_t	  *points,
 		       int		   num_points);
 
 static void
-_cairo_path_fixed_add_op_buf (cairo_path_fixed_t  *path,
-			      cairo_path_op_buf_t *op_buf);
+_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
+			   cairo_path_buf_t   *buf);
 
-static void
-_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t   *path,
-			       cairo_path_arg_buf_t *arg_buf);
-
-static cairo_path_op_buf_t *
-_cairo_path_op_buf_create (void);
-
-static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf);
+static cairo_path_buf_t *
+_cairo_path_buf_create (void);
 
 static void
-_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
-			   cairo_path_op_t      op);
-
-static cairo_path_arg_buf_t *
-_cairo_path_arg_buf_create (void);
+_cairo_path_buf_destroy (cairo_path_buf_t *buf);
 
 static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf);
+_cairo_path_buf_add_op (cairo_path_buf_t *buf,
+			cairo_path_op_t   op);
 
 static void
-_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
-				cairo_point_t	     *points,
-				int		      num_points);
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+			    cairo_point_t    *points,
+			    int		      num_points);
 
 void
 _cairo_path_fixed_init (cairo_path_fixed_t *path)
 {
-    path->op_buf_head = NULL;
-    path->op_buf_tail = NULL;
+    path->buf_head->next = NULL;
+    path->buf_head->prev = NULL;
+    path->buf_tail = path->buf_head;
 
-    path->arg_buf_head = NULL;
-    path->arg_buf_tail = NULL;
+    path->buf_head->num_ops = 0;
+    path->buf_head->num_points = 0;
 
     path->current_point.x = 0;
     path->current_point.y = 0;
     path->has_current_point = FALSE;
     path->has_curve_to = FALSE;
     path->last_move_point = path->current_point;
 }
 
 cairo_status_t
 _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
 			     cairo_path_fixed_t *other)
 {
-    cairo_path_op_buf_t *op_buf, *other_op_buf;
-    cairo_path_arg_buf_t *arg_buf, *other_arg_buf;
+    cairo_path_buf_t *buf, *other_buf;
 
     _cairo_path_fixed_init (path);
     path->current_point = other->current_point;
     path->has_current_point = other->has_current_point;
     path->has_curve_to = other->has_curve_to;
     path->last_move_point = other->last_move_point;
 
-    for (other_op_buf = other->op_buf_head;
-	 other_op_buf;
-	 other_op_buf = other_op_buf->next)
+    path->buf_head->num_ops = other->buf_head->num_ops;
+    path->buf_head->num_points = other->buf_head->num_points;
+    memcpy (path->buf_head->op, other->buf_head->op,
+	    other->buf_head->num_ops * sizeof (other->buf_head->op[0]));
+    memcpy (path->buf_head->points, other->buf_head->points,
+	    other->buf_head->num_points * sizeof (other->buf_head->points[0]));
+    for (other_buf = other->buf_head->next;
+	 other_buf;
+	 other_buf = other_buf->next)
     {
-	op_buf = _cairo_path_op_buf_create ();
-	if (op_buf == NULL) {
+	buf = _cairo_path_buf_create ();
+	if (buf == NULL) {
 	    _cairo_path_fixed_fini (path);
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
-	memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t));
-	_cairo_path_fixed_add_op_buf (path, op_buf);
-    }
-
-    for (other_arg_buf = other->arg_buf_head;
-	 other_arg_buf;
-	 other_arg_buf = other_arg_buf->next)
-    {
-	arg_buf = _cairo_path_arg_buf_create ();
-	if (arg_buf == NULL) {
-	    _cairo_path_fixed_fini (path);
-	    return CAIRO_STATUS_NO_MEMORY;
-	}
-	memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t));
-	_cairo_path_fixed_add_arg_buf (path, arg_buf);
+	memcpy (buf, other_buf, sizeof (cairo_path_buf_t));
+	_cairo_path_fixed_add_buf (path, buf);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_path_fixed_t *
 _cairo_path_fixed_create (void)
 {
@@ -143,32 +126,29 @@ cairo_path_fixed_t *
 	return NULL;
     _cairo_path_fixed_init (path);
     return path;
 }
 
 void
 _cairo_path_fixed_fini (cairo_path_fixed_t *path)
 {
-    cairo_path_op_buf_t *op_buf;
-    cairo_path_arg_buf_t *arg_buf;
+    cairo_path_buf_t *buf;
 
-    while (path->op_buf_head) {
-	op_buf = path->op_buf_head;
-	path->op_buf_head = op_buf->next;
-	_cairo_path_op_buf_destroy (op_buf);
+    buf = path->buf_head->next;
+    while (buf) {
+	cairo_path_buf_t *this = buf;
+	buf = buf->next;
+	_cairo_path_buf_destroy (this);
     }
-    path->op_buf_tail = NULL;
-
-    while (path->arg_buf_head) {
-	arg_buf = path->arg_buf_head;
-	path->arg_buf_head = arg_buf->next;
-	_cairo_path_arg_buf_destroy (arg_buf);
-    }
-    path->arg_buf_tail = NULL;
+    path->buf_head->next = NULL;
+    path->buf_head->prev = NULL;
+    path->buf_tail = path->buf_head;
+    path->buf_head->num_ops = 0;
+    path->buf_head->num_points = 0;
 
     path->has_current_point = FALSE;
     path->has_curve_to = FALSE;
 }
 
 void
 _cairo_path_fixed_destroy (cairo_path_fixed_t *path)
 {
@@ -184,21 +164,21 @@ cairo_status_t
     cairo_status_t status;
     cairo_point_t point;
 
     point.x = x;
     point.y = y;
 
     /* If the previous op was also a MOVE_TO, then just change its
      * point rather than adding a new op. */
-    if (path->op_buf_tail && path->op_buf_tail->num_ops &&
-	path->op_buf_tail->op[path->op_buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
+    if (path->buf_tail && path->buf_tail->num_ops &&
+	path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
     {
 	cairo_point_t *last_move_to_point;
-	last_move_to_point = &path->arg_buf_tail->points[path->arg_buf_tail->num_points - 1];
+	last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1];
 	*last_move_to_point = point;
     } else {
 	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
 	if (status)
 	    return status;
     }
 
     path->current_point = point;
@@ -371,143 +351,87 @@ cairo_status_t
 }
 
 static cairo_status_t
 _cairo_path_fixed_add (cairo_path_fixed_t *path,
 		       cairo_path_op_t	   op,
 		       cairo_point_t	  *points,
 		       int		   num_points)
 {
-    if (path->op_buf_tail == NULL ||
-	path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
+    if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
+	path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
     {
-	cairo_path_op_buf_t *op_buf;
+	cairo_path_buf_t *buf;
 
-	op_buf = _cairo_path_op_buf_create ();
-	if (op_buf == NULL)
+	buf = _cairo_path_buf_create ();
+	if (buf == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
 
-	_cairo_path_fixed_add_op_buf (path, op_buf);
+	_cairo_path_fixed_add_buf (path, buf);
     }
 
-    _cairo_path_op_buf_add_op (path->op_buf_tail, op);
-
-    if (path->arg_buf_tail == NULL ||
-	path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
-    {
-	cairo_path_arg_buf_t *arg_buf;
-
-	arg_buf = _cairo_path_arg_buf_create ();
-
-	if (arg_buf == NULL)
-	    return CAIRO_STATUS_NO_MEMORY;
-
-	_cairo_path_fixed_add_arg_buf (path, arg_buf);
-    }
-
-    _cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points);
+    _cairo_path_buf_add_op (path->buf_tail, op);
+    _cairo_path_buf_add_points (path->buf_tail, points, num_points);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_path_fixed_add_op_buf (cairo_path_fixed_t  *path,
-			      cairo_path_op_buf_t *op_buf)
+_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
+			   cairo_path_buf_t   *buf)
 {
-    op_buf->next = NULL;
-    op_buf->prev = path->op_buf_tail;
+    buf->next = NULL;
+    buf->prev = path->buf_tail;
+
+    path->buf_tail->next = buf;
+    path->buf_tail = buf;
+}
 
-    if (path->op_buf_tail) {
-	path->op_buf_tail->next = op_buf;
-    } else {
-	path->op_buf_head = op_buf;
+static cairo_path_buf_t *
+_cairo_path_buf_create (void)
+{
+    cairo_path_buf_t *buf;
+
+    buf = malloc (sizeof (cairo_path_buf_t));
+
+    if (buf) {
+	buf->next = NULL;
+	buf->prev = NULL;
+	buf->num_ops = 0;
+	buf->num_points = 0;
     }
 
-    path->op_buf_tail = op_buf;
+    return buf;
 }
 
 static void
-_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t   *path,
-			       cairo_path_arg_buf_t *arg_buf)
+_cairo_path_buf_destroy (cairo_path_buf_t *buf)
 {
-    arg_buf->next = NULL;
-    arg_buf->prev = path->arg_buf_tail;
-
-    if (path->arg_buf_tail) {
-	path->arg_buf_tail->next = arg_buf;
-    } else {
-	path->arg_buf_head = arg_buf;
-    }
-
-    path->arg_buf_tail = arg_buf;
-}
-
-static cairo_path_op_buf_t *
-_cairo_path_op_buf_create (void)
-{
-    cairo_path_op_buf_t *op_buf;
-
-    op_buf = malloc (sizeof (cairo_path_op_buf_t));
-
-    if (op_buf) {
-	op_buf->num_ops = 0;
-	op_buf->next = NULL;
-    }
-
-    return op_buf;
+    free (buf);
 }
 
 static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf)
+_cairo_path_buf_add_op (cairo_path_buf_t *buf,
+			cairo_path_op_t	  op)
 {
-    free (op_buf);
+    buf->op[buf->num_ops++] = op;
 }
 
 static void
-_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
-			   cairo_path_op_t	op)
-{
-    op_buf->op[op_buf->num_ops++] = op;
-}
-
-static cairo_path_arg_buf_t *
-_cairo_path_arg_buf_create (void)
-{
-    cairo_path_arg_buf_t *arg_buf;
-
-    arg_buf = malloc (sizeof (cairo_path_arg_buf_t));
-
-    if (arg_buf) {
-	arg_buf->num_points = 0;
-	arg_buf->next = NULL;
-    }
-
-    return arg_buf;
-}
-
-static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf)
-{
-    free (arg_buf);
-}
-
-static void
-_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
-				cairo_point_t	     *points,
-				int		      num_points)
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+			    cairo_point_t    *points,
+			    int		      num_points)
 {
     int i;
 
     for (i=0; i < num_points; i++) {
-	arg_buf->points[arg_buf->num_points++] = points[i];
+	buf->points[buf->num_points++] = points[i];
     }
 }
 
-#define CAIRO_PATH_OP_MAX_ARGS 3
-
 static int const num_args[] =
 {
     1, /* cairo_path_move_to */
     1, /* cairo_path_op_line_to */
     3, /* cairo_path_op_curve_to */
     0, /* cairo_path_op_close_path */
 };
 
@@ -516,117 +440,104 @@ cairo_status_t
 			     cairo_direction_t			 dir,
 			     cairo_path_fixed_move_to_func_t	*move_to,
 			     cairo_path_fixed_line_to_func_t	*line_to,
 			     cairo_path_fixed_curve_to_func_t	*curve_to,
 			     cairo_path_fixed_close_path_func_t	*close_path,
 			     void				*closure)
 {
     cairo_status_t status;
-    int i, arg;
-    cairo_path_op_buf_t *op_buf;
+    cairo_path_buf_t *buf;
     cairo_path_op_t op;
-    cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
-    int buf_i = 0;
-    cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
     cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
     int step = forward ? 1 : -1;
 
-    for (op_buf = forward ? path->op_buf_head : path->op_buf_tail;
-	 op_buf;
-	 op_buf = forward ? op_buf->next : op_buf->prev)
+    for (buf = forward ? path->buf_head : path->buf_tail;
+	 buf;
+	 buf = forward ? buf->next : buf->prev)
     {
-	int start, stop;
+	cairo_point_t *points;
+	int start, stop, i;
 	if (forward) {
 	    start = 0;
-	    stop = op_buf->num_ops;
+	    stop = buf->num_ops;
+	    points = buf->points;
 	} else {
-	    start = op_buf->num_ops - 1;
+	    start = buf->num_ops - 1;
 	    stop = -1;
+	    points = buf->points + buf->num_points;
 	}
 
 	for (i=start; i != stop; i += step) {
-	    op = op_buf->op[i];
+	    op = buf->op[i];
 
 	    if (! forward) {
-		if (buf_i == 0) {
-		    arg_buf = arg_buf->prev;
-		    buf_i = arg_buf->num_points;
-		}
-		buf_i -= num_args[op];
-	    }
-
-	    for (arg = 0; arg < num_args[op]; arg++) {
-		point[arg] = arg_buf->points[buf_i];
-		buf_i++;
-		if (buf_i >= arg_buf->num_points) {
-		    arg_buf = arg_buf->next;
-		    buf_i = 0;
-		}
-	    }
-
-	    if (! forward) {
-		buf_i -= num_args[op];
+		points -= num_args[op];
 	    }
 
 	    switch (op) {
 	    case CAIRO_PATH_OP_MOVE_TO:
-		status = (*move_to) (closure, &point[0]);
+		status = (*move_to) (closure, &points[0]);
 		break;
 	    case CAIRO_PATH_OP_LINE_TO:
-		status = (*line_to) (closure, &point[0]);
+		status = (*line_to) (closure, &points[0]);
 		break;
 	    case CAIRO_PATH_OP_CURVE_TO:
-		status = (*curve_to) (closure, &point[0], &point[1], &point[2]);
+		status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
 		break;
 	    case CAIRO_PATH_OP_CLOSE_PATH:
 	    default:
 		status = (*close_path) (closure);
 		break;
 	    }
 	    if (status)
 		return status;
+
+	    if (forward) {
+		points += num_args[op];
+	    }
+
 	}
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
 				    cairo_fixed_t offx,
 				    cairo_fixed_t offy,
 				    cairo_fixed_t scalex,
 				    cairo_fixed_t scaley)
 {
-    cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
+    cairo_path_buf_t *buf = path->buf_head;
     int i;
     cairo_int64_t i64temp;
     cairo_fixed_t fixedtemp;
 
-    while (arg_buf) {
-	 for (i = 0; i < arg_buf->num_points; i++) {
+    while (buf) {
+	 for (i = 0; i < buf->num_points; i++) {
 	     if (scalex == CAIRO_FIXED_ONE) {
-		 arg_buf->points[i].x += offx;
+		 buf->points[i].x += offx;
 	     } else {
-		 fixedtemp = arg_buf->points[i].x + offx;
+		 fixedtemp = buf->points[i].x + offx;
 		 i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
-		 arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
+		 buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
 	     }
 
 	     if (scaley == CAIRO_FIXED_ONE) {
-		 arg_buf->points[i].y += offy;
+		 buf->points[i].y += offy;
 	     } else {
-		 fixedtemp = arg_buf->points[i].y + offy;
+		 fixedtemp = buf->points[i].y + offy;
 		 i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
-		 arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
+		 buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
 	     }
 	 }
 
-	 arg_buf = arg_buf->next;
+	 buf = buf->next;
     }
 }
 
 
 /**
  * _cairo_path_fixed_device_transform:
  * @path: a #cairo_path_fixed_t to be transformed
  * @device_transform: a matrix with only scaling/translation (no rotation or shear)
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -46,27 +46,28 @@ typedef struct cairo_stroker {
 
     cairo_traps_t *traps;
 
     cairo_pen_t	  pen;
 
     cairo_point_t current_point;
     cairo_point_t first_point;
 
-    cairo_bool_t has_sub_path;
+    cairo_bool_t has_initial_sub_path;
 
     cairo_bool_t has_current_face;
     cairo_stroke_face_t current_face;
 
     cairo_bool_t has_first_face;
     cairo_stroke_face_t first_face;
 
     cairo_bool_t dashed;
     unsigned int dash_index;
-    int dash_on;
+    cairo_bool_t dash_on;
+    cairo_bool_t dash_starts_on;
     double dash_remain;
 } cairo_stroker_t;
 
 /* private functions */
 static void
 _cairo_stroker_init (cairo_stroker_t		*stroker,
 		     cairo_stroke_style_t	*stroke_style,
 		     cairo_matrix_t		*ctm,
@@ -109,45 +110,45 @@ static int
 
 static cairo_status_t
 _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out);
 
 static void
 _cairo_stroker_start_dash (cairo_stroker_t *stroker)
 {
     double offset;
-    int	on = 1;
+    cairo_bool_t on = TRUE;
     unsigned int i = 0;
 
     offset = stroker->style->dash_offset;
 
     /* We stop searching for a starting point as soon as the
        offset reaches zero.  Otherwise when an initial dash
        segment shrinks to zero it will be skipped over. */
     while (offset > 0.0 && offset >= stroker->style->dash[i]) {
 	offset -= stroker->style->dash[i];
-	on = 1-on;
+	on = !on;
 	if (++i == stroker->style->num_dashes)
 	    i = 0;
     }
     stroker->dashed = TRUE;
     stroker->dash_index = i;
-    stroker->dash_on = on;
+    stroker->dash_on = stroker->dash_starts_on = on;
     stroker->dash_remain = stroker->style->dash[i] - offset;
 }
 
 static void
 _cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
 {
     stroker->dash_remain -= step;
     if (stroker->dash_remain <= 0) {
 	stroker->dash_index++;
 	if (stroker->dash_index == stroker->style->num_dashes)
 	    stroker->dash_index = 0;
-	stroker->dash_on = 1-stroker->dash_on;
+	stroker->dash_on = !stroker->dash_on;
 	stroker->dash_remain = stroker->style->dash[stroker->dash_index];
     }
 }
 
 static void
 _cairo_stroker_init (cairo_stroker_t		*stroker,
 		     cairo_stroke_style_t	*stroke_style,
 		     cairo_matrix_t		*ctm,
@@ -162,17 +163,17 @@ static void
     stroker->traps = traps;
 
     _cairo_pen_init (&stroker->pen,
 		     stroke_style->line_width / 2.0,
 		     tolerance, ctm);
 
     stroker->has_current_face = FALSE;
     stroker->has_first_face = FALSE;
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
 
     if (stroker->style->dash)
 	_cairo_stroker_start_dash (stroker);
     else
 	stroker->dashed = FALSE;
 }
 
 static void
@@ -461,27 +462,35 @@ static cairo_status_t
 static void
 _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stroker, cairo_stroke_face_t *face);
 
 static cairo_status_t
 _cairo_stroker_add_caps (cairo_stroker_t *stroker)
 {
     cairo_status_t status;
     /* check for a degenerative sub_path */
-    if (stroker->has_sub_path
+    if (stroker->has_initial_sub_path
 	&& !stroker->has_first_face
 	&& !stroker->has_current_face
 	&& stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND)
     {
 	/* pick an arbitrary slope to use */
 	cairo_slope_t slope = {1, 0};
-	_compute_face (&stroker->first_point, &slope, stroker, &stroker->first_face);
+	cairo_stroke_face_t face;
+
+	/* arbitrarily choose first_point
+	 * first_point and current_point should be the same */
+	_compute_face (&stroker->first_point, &slope, stroker, &face);
 
-	stroker->has_first_face = stroker->has_current_face = TRUE;
-	stroker->current_face = stroker->first_face;
+	status = _cairo_stroker_add_leading_cap (stroker, &face);
+	if (status)
+	    return status;
+	status = _cairo_stroker_add_trailing_cap (stroker, &face);
+	if (status)
+	    return status;
     }
 
     if (stroker->has_first_face) {
 	status = _cairo_stroker_add_leading_cap (stroker, &stroker->first_face);
 	if (status)
 	    return status;
     }
 
@@ -589,26 +598,27 @@ static cairo_status_t
 }
 
 static cairo_status_t
 _cairo_stroker_move_to (void *closure, cairo_point_t *point)
 {
     cairo_status_t status;
     cairo_stroker_t *stroker = closure;
 
+    /* Cap the start and end of the previous sub path as needed */
     status = _cairo_stroker_add_caps (stroker);
     if (status)
 	return status;
 
     stroker->first_point = *point;
     stroker->current_point = *point;
 
     stroker->has_first_face = FALSE;
     stroker->has_current_face = FALSE;
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_stroker_move_to_dashed (void *closure, cairo_point_t *point)
 {
     /* reset the dash pattern for new sub paths */
@@ -623,36 +633,36 @@ static cairo_status_t
 {
     cairo_status_t status;
     cairo_stroker_t *stroker = closure;
     cairo_stroke_face_t start, end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
     cairo_slope_t slope;
 
-    stroker->has_sub_path = TRUE;
+    stroker->has_initial_sub_path = TRUE;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
 
     _cairo_slope_init (&slope, p1, p2);
 
     status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &slope, &start, &end);
     if (status)
 	return status;
 
     if (stroker->has_current_face) {
+	/* Join with final face from previous segment */
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
 	if (status)
 	    return status;
-    } else {
-	if (!stroker->has_first_face) {
-	    stroker->first_face = start;
-	    stroker->has_first_face = TRUE;
-	}
+    } else if (!stroker->has_first_face) {
+	/* Save sub path's first face in case needed for closing join */
+	stroker->first_face = start;
+	stroker->has_first_face = TRUE;
     }
     stroker->current_face = end;
     stroker->has_current_face = TRUE;
 
     stroker->current_point = *point;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -660,122 +670,106 @@ static cairo_status_t
 /*
  * Dashed lines.  Cap each dash end, join around turns when on
  */
 static cairo_status_t
 _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_stroker_t *stroker = closure;
-    double mag, remain, tmp;
+    double mag, remain, step_length = 0;
     double dx, dy;
     double dx2, dy2;
     cairo_point_t fd1, fd2;
-    cairo_bool_t first = TRUE;
     cairo_stroke_face_t sub_start, sub_end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
     cairo_slope_t slope;
 
-    stroker->has_sub_path = stroker->dash_on;
+    stroker->has_initial_sub_path = stroker->dash_starts_on;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
 
     _cairo_slope_init (&slope, p1, p2);
 
     dx = _cairo_fixed_to_double (p2->x - p1->x);
     dy = _cairo_fixed_to_double (p2->y - p1->y);
 
     cairo_matrix_transform_distance (stroker->ctm_inverse, &dx, &dy);
 
-    mag = sqrt (dx *dx + dy * dy);
+    mag = sqrt (dx * dx + dy * dy);
     remain = mag;
     fd1 = *p1;
     while (remain) {
-	tmp = stroker->dash_remain;
-	if (tmp > remain)
-	    tmp = remain;
-	remain -= tmp;
-        dx2 = dx * (mag - remain)/mag;
+	step_length = MIN (stroker->dash_remain, remain);
+	remain -= step_length;
+	dx2 = dx * (mag - remain)/mag;
 	dy2 = dy * (mag - remain)/mag;
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
-	fd2.x = _cairo_fixed_from_double (dx2);
-	fd2.y = _cairo_fixed_from_double (dy2);
-	fd2.x += p1->x;
-	fd2.y += p1->y;
-	/*
-	 * XXX simplify this case analysis
-	 */
+	fd2.x = _cairo_fixed_from_double (dx2) + p1->x;
+	fd2.y = _cairo_fixed_from_double (dy2) + p1->y;
+
 	if (stroker->dash_on) {
 	    status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
 	    if (status)
 		return status;
-	    if (!first) {
-		/*
-		 * Not first dash in this segment, cap start
-		 */
+
+	    if (stroker->has_current_face) {
+		/* Join with final face from previous segment */
+		status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
+		stroker->has_current_face = FALSE;
+		if (status)
+		    return status;
+	    } else if (!stroker->has_first_face && stroker->dash_starts_on) {
+		/* Save sub path's first face in case needed for closing join */
+		stroker->first_face = sub_start;
+		stroker->has_first_face = TRUE;
+	    } else {
+		/* Cap dash start if not connecting to a previous segment */
 		status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
 		if (status)
 		    return status;
-	    } else {
-		/*
-		 * First in this segment, join to any current_face, else
-		 * if at start of sub-path, mark position, else
-		 * cap
-		 */
-		if (stroker->has_current_face) {
-		    status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
-		    if (status)
-			return status;
-		} else {
-		    if (!stroker->has_first_face) {
-			stroker->first_face = sub_start;
-			stroker->has_first_face = TRUE;
-		    } else {
-			status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
-			if (status)
-			    return status;
-		    }
-		}
-		stroker->has_sub_path = TRUE;
 	    }
+
 	    if (remain) {
-		/*
-		 * Cap if not at end of segment
-		 */
+		/* Cap dash end if not at end of segment */
 		status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
 		if (status)
 		    return status;
 	    } else {
-		/*
-		 * Mark previous line face and fix up next time
-		 * through
-		 */
 		stroker->current_face = sub_end;
 		stroker->has_current_face = TRUE;
 	    }
 	} else {
-	    /*
-	     * If starting with off dash, check previous face
-	     * and cap if necessary
-	     */
-	    if (first) {
-		if (stroker->has_current_face) {
-		    status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
-		    if (status)
-			return status;
-		}
+	    if (stroker->has_current_face) {
+		/* Cap final face from previous segment */
+		status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
+		if (status)
+		    return status;
+		stroker->has_current_face = FALSE;
 	    }
-	    if (!remain)
-		stroker->has_current_face = FALSE;
 	}
-	_cairo_stroker_step_dash (stroker, tmp);
+	_cairo_stroker_step_dash (stroker, step_length);
 	fd1 = fd2;
-	first = FALSE;
+    }
+
+    if (stroker->dash_on && !stroker->has_current_face) {
+	/* This segment ends on a transition to dash_on, compute a new face
+	 * and add cap for the begining of the next dash_on step.
+	 *
+	 * Note: this will create a degenerate cap if this is not the last line
+	 * in the path. Whether this behaviour is desirable or not is debatable.
+	 * On one side these degnerate caps can not be reproduced with regular path stroking.
+	 * On the other side Acroread 7 also produces the degenerate caps. */
+	_compute_face (point, &slope, stroker, &stroker->current_face);
+	stroker->has_current_face = TRUE;
+	status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
+	if (status)
+	    return status;
     }
 
     stroker->current_point = *point;
 
     return status;
 }
 
 static cairo_status_t
@@ -802,21 +796,19 @@ static cairo_status_t
 
     _compute_face (a, &spline.initial_slope, stroker, &start);
     _compute_face (d, &spline.final_slope, stroker, &end);
 
     if (stroker->has_current_face) {
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
 	if (status)
 	    return status;
-    } else {
-	if (!stroker->has_first_face) {
-	    stroker->first_face = start;
-	    stroker->has_first_face = TRUE;
-	}
+    } else if (!stroker->has_first_face) {
+	stroker->first_face = start;
+	stroker->has_first_face = TRUE;
     }
     stroker->current_face = end;
     stroker->has_current_face = TRUE;
 
     extra_points[0] = start.cw;
     extra_points[0].x -= start.point.x;
     extra_points[0].y -= start.point.y;
     extra_points[1] = start.ccw;
@@ -923,26 +915,28 @@ static cairo_status_t
     if (stroker->dashed)
 	status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
     else
 	status = _cairo_stroker_line_to (stroker, &stroker->first_point);
     if (status)
 	return status;
 
     if (stroker->has_first_face && stroker->has_current_face) {
+	/* Join first and final faces of sub path */
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
 	if (status)
 	    return status;
     } else {
+	/* Cap the start and end of the sub path as needed */
 	status = _cairo_stroker_add_caps (stroker);
 	if (status)
 	    return status;
     }
 
-    stroker->has_sub_path = FALSE;
+    stroker->has_initial_sub_path = FALSE;
     stroker->has_first_face = FALSE;
     stroker->has_current_face = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t	*path,
@@ -991,16 +985,17 @@ cairo_status_t
 					      _cairo_stroker_move_to,
 					      _cairo_stroker_line_to,
 					      _cairo_stroker_curve_to,
 					      _cairo_stroker_close_path,
 					      &stroker);
     if (status)
 	goto BAIL;
 
+    /* Cap the start and end of the final sub path as needed */
     status = _cairo_stroker_add_caps (&stroker);
 
 BAIL:
     _cairo_stroker_fini (&stroker);
 
     return status;
 }
 
@@ -1282,21 +1277,22 @@ static cairo_int_status_t
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_rectilinear_stroker_move_to,
 					  _cairo_rectilinear_stroker_line_to,
 					  NULL,
 					  _cairo_rectilinear_stroker_close_path,
 					  &rectilinear_stroker);
-    if (status) {
-	_cairo_traps_fini (traps);
-	return status;
-    }
+    if (status)
+	goto BAIL;
 
     status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
-    if (status)
-	return status;
+
+BAIL:
 
     _cairo_rectilinear_stroker_fini (&rectilinear_stroker);
 
-    return CAIRO_STATUS_SUCCESS;
+    if (status)
+	_cairo_traps_fini (traps);
+
+    return status;
 }
--- a/gfx/cairo/cairo/src/cairo-path.c
+++ b/gfx/cairo/cairo/src/cairo-path.c
@@ -460,37 +460,37 @@ cairo_status_t
 {
     int i;
     cairo_path_data_t *p;
 
     for (i=0; i < path->num_data; i += path->data[i].header.length) {
 	p = &path->data[i];
 	switch (p->header.type) {
 	case CAIRO_PATH_MOVE_TO:
-	    if (p->header.length != 2)
+	    if (p->header.length < 2)
 		return CAIRO_STATUS_INVALID_PATH_DATA;
 	    cairo_move_to (cr,
 			   p[1].point.x, p[1].point.y);
 	    break;
 	case CAIRO_PATH_LINE_TO:
-	    if (p->header.length != 2)
+	    if (p->header.length < 2)
 		return CAIRO_STATUS_INVALID_PATH_DATA;
 	    cairo_line_to (cr,
 			   p[1].point.x, p[1].point.y);
 	    break;
 	case CAIRO_PATH_CURVE_TO:
-	    if (p->header.length != 4)
+	    if (p->header.length < 4)
 		return CAIRO_STATUS_INVALID_PATH_DATA;
 	    cairo_curve_to (cr,
 			    p[1].point.x, p[1].point.y,
 			    p[2].point.x, p[2].point.y,
 			    p[3].point.x, p[3].point.y);
 	    break;
 	case CAIRO_PATH_CLOSE_PATH:
-	    if (p->header.length != 1)
+	    if (p->header.length < 1)
 		return CAIRO_STATUS_INVALID_PATH_DATA;
 	    cairo_close_path (cr);
 	    break;
 	default:
 	    return CAIRO_STATUS_INVALID_PATH_DATA;
 	}
     }
 
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -29,25 +29,27 @@
  */
 
 #include "cairoint.h"
 
 const cairo_solid_pattern_t cairo_pattern_nil = {
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
       CAIRO_REF_COUNT_INVALID,		/* ref_count */
       CAIRO_STATUS_NO_MEMORY,	/* status */
+      { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., }, /* matrix */
       CAIRO_FILTER_DEFAULT,	/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
 static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
       CAIRO_REF_COUNT_INVALID,		/* ref_count */
       CAIRO_STATUS_NULL_POINTER,/* status */
+      { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., }, /* matrix */
       CAIRO_FILTER_DEFAULT,	/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
 /**
  * _cairo_pattern_set_error:
  * @pattern: a pattern
@@ -79,16 +81,18 @@ static void
 
 static void
 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
 {
     pattern->type      = type;
     pattern->ref_count = 1;
     pattern->status    = CAIRO_STATUS_SUCCESS;
 
+    _cairo_user_data_array_init (&pattern->user_data);
+
     if (type == CAIRO_PATTERN_TYPE_SURFACE)
 	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
     else
 	pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
 
     pattern->filter    = CAIRO_FILTER_DEFAULT;
 
     cairo_matrix_init_identity (&pattern->matrix);
@@ -108,21 +112,25 @@ static void
     else
     {
 	cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
 	cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
 
 	*dst = *src;
     }
 
-    if (other->n_stops)
+    if (other->stops == other->stops_embedded)
+	pattern->stops = pattern->stops_embedded;
+    else if (other->stops)
     {
-	pattern->stops = malloc (other->n_stops *
+	pattern->stops = malloc (other->stops_size *
 				 sizeof (pixman_gradient_stop_t));
 	if (pattern->stops == NULL) {
+	    pattern->stops_size = 0;
+	    pattern->n_stops = 0;
 	    _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
 	    return;
 	}
 
 	memcpy (pattern->stops, other->stops,
 		other->n_stops * sizeof (pixman_gradient_stop_t));
     }
 }
@@ -160,31 +168,33 @@ void
     }
 
     pattern->ref_count = 1;
 }
 
 void
 _cairo_pattern_fini (cairo_pattern_t *pattern)
 {
+    _cairo_user_data_array_fini (&pattern->user_data);
+
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
 	break;
     case CAIRO_PATTERN_TYPE_SURFACE: {
 	cairo_surface_pattern_t *surface_pattern =
 	    (cairo_surface_pattern_t *) pattern;
 
 	cairo_surface_destroy (surface_pattern->surface);
     } break;
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL: {
 	cairo_gradient_pattern_t *gradient =
 	    (cairo_gradient_pattern_t *) pattern;
 
-	if (gradient->stops)
+	if (gradient->stops && gradient->stops != gradient->stops_embedded)
 	    free (gradient->stops);
     } break;
     }
 }
 
 void
 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
 			   const cairo_color_t	 *color)
@@ -210,18 +220,19 @@ void
 }
 
 static void
 _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
 			      cairo_pattern_type_t     type)
 {
     _cairo_pattern_init (&pattern->base, type);
 
-    pattern->stops   = NULL;
-    pattern->n_stops = 0;
+    pattern->n_stops    = 0;
+    pattern->stops_size = 0;
+    pattern->stops      = NULL;
 }
 
 void
 _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
 			    double x0, double y0, double x1, double y1)
 {
     _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
 
@@ -233,22 +244,22 @@ void
 
 void
 _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
 			    double cx0, double cy0, double radius0,
 			    double cx1, double cy1, double radius1)
 {
     _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
 
-    pattern->gradient.inner.x	   = _cairo_fixed_from_double (cx0);
-    pattern->gradient.inner.y	   = _cairo_fixed_from_double (cy0);
-    pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0));
-    pattern->gradient.outer.x	   = _cairo_fixed_from_double (cx1);
-    pattern->gradient.outer.y	   = _cairo_fixed_from_double (cy1);
-    pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1));
+    pattern->gradient.c1.x	   = _cairo_fixed_from_double (cx0);
+    pattern->gradient.c1.y	   = _cairo_fixed_from_double (cy0);
+    pattern->gradient.c1.radius = _cairo_fixed_from_double (fabs (radius0));
+    pattern->gradient.c2.x	   = _cairo_fixed_from_double (cx1);
+    pattern->gradient.c2.y	   = _cairo_fixed_from_double (cy1);
+    pattern->gradient.c2.radius = _cairo_fixed_from_double (fabs (radius1));
 }
 
 cairo_pattern_t *
 _cairo_pattern_create_solid (const cairo_color_t *color)
 {
     cairo_solid_pattern_t *pattern;
 
     pattern = malloc (sizeof (cairo_solid_pattern_t));
@@ -485,25 +496,25 @@ cairo_pattern_create_radial (double cx0,
 /**
  * cairo_pattern_reference:
  * @pattern: a #cairo_pattern_t
  *
  * Increases the reference count on @pattern by one. This prevents
  * @pattern from being destroyed until a matching call to
  * cairo_pattern_destroy() is made.
  *
+ * The number of references to a #cairo_pattern_t can be get using
+ * cairo_pattern_get_reference_count().
+ *
  * Return value: the referenced #cairo_pattern_t.
  **/
 cairo_pattern_t *
 cairo_pattern_reference (cairo_pattern_t *pattern)
 {
-    if (pattern == NULL)
-	return NULL;
-
-    if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
+    if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
 	return pattern;
 
     assert (pattern->ref_count > 0);
 
     pattern->ref_count++;
 
     return pattern;
 }
@@ -550,73 +561,180 @@ slim_hidden_def (cairo_pattern_status);
  *
  * Decreases the reference count on @pattern by one. If the result is
  * zero, then @pattern and all associated resources are freed.  See
  * cairo_pattern_reference().
  **/
 void
 cairo_pattern_destroy (cairo_pattern_t *pattern)
 {
-    if (pattern == NULL)
-	return;
-
-    if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
+    if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
 	return;
 
     assert (pattern->ref_count > 0);
 
     pattern->ref_count--;
     if (pattern->ref_count)
 	return;
 
     _cairo_pattern_fini (pattern);
     free (pattern);
 }
 slim_hidden_def (cairo_pattern_destroy);
 
+/**
+ * cairo_pattern_get_reference_count:
+ * @pattern: a #cairo_pattern_t
+ *
+ * Returns the current reference count of @pattern.
+ *
+ * Return value: the current reference count of @pattern.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
+{
+    if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
+	return 0;
+
+    return pattern->ref_count;
+}
+
+/**
+ * cairo_pattern_get_user_data:
+ * @pattern: a #cairo_pattern_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @pattern using the
+ * specified key.  If no user data has been attached with the given
+ * key this function returns %NULL.
+ *
+ * Return value: the user data previously attached or %NULL.
+ *
+ * Since: 1.4
+ **/
+void *
+cairo_pattern_get_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key)
+{
+    return _cairo_user_data_array_get_data (&pattern->user_data,
+					    key);
+}
+
+/**
+ * cairo_pattern_set_user_data:
+ * @pattern: a #cairo_pattern_t
+ * @key: the address of a #cairo_user_data_key_t to attach the user data to
+ * @user_data: the user data to attach to the #cairo_pattern_t
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * #cairo_t is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @pattern.  To remove user data from a surface,
+ * call this function with the key that was used to set it and %NULL
+ * for @data.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
+ * slot could not be allocated for the user data.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_set_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key,
+			     void			 *user_data,
+			     cairo_destroy_func_t	  destroy)
+{
+    if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return _cairo_user_data_array_set_data (&pattern->user_data,
+					    key, user_data, destroy);
+}
+
+/* make room for at least one more color stop */
+static cairo_status_t
+_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
+{
+    pixman_gradient_stop_t *new_stops;
+    int old_size = pattern->stops_size;
+    int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]);
+    int new_size = 2 * MAX (old_size, 4);
+
+    /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
+     * from there. */
+    if (old_size < embedded_size) {
+	pattern->stops = pattern->stops_embedded;
+	pattern->stops_size = embedded_size;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    assert (pattern->n_stops <= pattern->stops_size);
+
+    if (pattern->stops == pattern->stops_embedded) {
+	new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t));
+	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));
+    }
+
+    if (new_stops == NULL) {
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    pattern->stops = new_stops;
+    pattern->stops_size = new_size;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static void
 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
 			       double			 offset,
 			       double			 red,
 			       double			 green,
 			       double			 blue,
 			       double			 alpha)
 {
-    pixman_gradient_stop_t *new_stops;
+    pixman_gradient_stop_t *stops;
     cairo_fixed_t	   x;
     unsigned int	   i;
 
-    new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *
-			 sizeof (pixman_gradient_stop_t));
-    if (new_stops == NULL)
-    {
-	_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
-	return;
+    if (pattern->n_stops >= pattern->stops_size) {
+        cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
+	if (status) {
+	    _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
+	    return;
+	}
     }
 
-    pattern->stops = new_stops;
+    stops = pattern->stops;
 
     x = _cairo_fixed_from_double (offset);
     for (i = 0; i < pattern->n_stops; i++)
     {
-	if (x < new_stops[i].x)
+	if (x < stops[i].x)
 	{
-	    memmove (&new_stops[i + 1], &new_stops[i],
+	    memmove (&stops[i + 1], &stops[i],
 		     sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i));
 
 	    break;
 	}
     }
 
-    new_stops[i].x = x;
+    stops[i].x = x;
 
-    new_stops[i].color.red   = red   * 65535.0;
-    new_stops[i].color.green = green * 65535.0;
-    new_stops[i].color.blue  = blue  * 65535.0;
-    new_stops[i].color.alpha = alpha * 65535.0;
+    stops[i].color.red   = _cairo_color_double_to_short (red);
+    stops[i].color.green = _cairo_color_double_to_short (green);
+    stops[i].color.blue  = _cairo_color_double_to_short (blue);
+    stops[i].color.alpha = _cairo_color_double_to_short (alpha);
 
     pattern->n_stops++;
 }
 
 /**
  * cairo_pattern_add_color_stop_rgb:
  * @pattern: a #cairo_pattern_t
  * @offset: an offset in the range [0.0 .. 1.0]
@@ -762,25 +880,43 @@ slim_hidden_def (cairo_pattern_set_matri
  * Stores the pattern's transformation matrix into @matrix.
  **/
 void
 cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
 {
     *matrix = pattern->matrix;
 }
 
+/**
+ * cairo_pattern_set_filter:
+ * @pattern: a #cairo_pattern_t
+ * @filter: a #cairo_filter_t describing the filter to use for resizing
+ * the pattern
+ *
+ * Sets the filter to be used for resizing when using this pattern.
+ * See #cairo_filter_t for details on each filter.
+ **/
 void
 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
 {
     if (pattern->status)
 	return;
 
     pattern->filter = filter;
 }
 
+/**
+ * cairo_pattern_get_filter:
+ * @pattern: a #cairo_pattern_t
+ *
+ * Gets the current filter for a pattern.  See #cairo_filter_t
+ * for details on each filter.
+ *
+ * Return value: the current filter used for resizing the pattern.
+ **/
 cairo_filter_t
 cairo_pattern_get_filter (cairo_pattern_t *pattern)
 {
     return pattern->filter;
 }
 
 /**
  * cairo_pattern_set_extend:
@@ -1139,65 +1275,157 @@ static cairo_int_status_t
     else
     {
 	attr->matrix = pattern->base.matrix;
 	attr->x_offset = attr->y_offset = 0;
 	tx = 0;
 	ty = 0;
     }
 
+    /* XXX: Hack:
+     *
+     * The way we currently support CAIRO_EXTEND_REFLECT is to create
+     * an image twice bigger on each side, and create a pattern of four
+     * images such that the new image, when repeated, has the same effect
+     * of reflecting the original pattern.
+     *
+     * This is because the reflect support in pixman is broken and we
+     * pass repeat instead of reflect to pixman.  See
+     * _cairo_image_surface_set_attributes() for that.
+     */
+    if (attr->extend == CAIRO_EXTEND_REFLECT) {
+	cairo_t *cr;
+	int w,h;
+
+	cairo_rectangle_int16_t extents;
+	status = _cairo_surface_get_extents (pattern->surface, &extents);
+	if (status)
+	    return status;
+
+	attr->extend = CAIRO_EXTEND_REPEAT;
+
+	x = extents.x;
+	y = extents.y;
+	w = 2 * extents.width;
+	h = 2 * extents.height;
+
+	*out = cairo_surface_create_similar (dst, dst->content, w, h);
+	if (!*out)
+	    return CAIRO_STATUS_NO_MEMORY;
+
+	(*out)->device_transform = pattern->surface->device_transform;
+	(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
+
+	cr = cairo_create (*out);
+
+	cairo_set_source_surface (cr, pattern->surface, -x, -y);
+	cairo_paint (cr);
+
+	cairo_scale (cr, -1, +1);
+	cairo_set_source_surface (cr, pattern->surface, x-w, -y);
+	cairo_paint (cr);
+
+	cairo_scale (cr, +1, -1);
+	cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
+	cairo_paint (cr);
+
+	cairo_scale (cr, -1, +1);
+	cairo_set_source_surface (cr, pattern->surface, -x, y-h);
+	cairo_paint (cr);
+
+	status = cairo_status (cr);
+	cairo_destroy (cr);
+
+	return status;
+    }
+
     if (_cairo_surface_is_image (dst))
     {
 	cairo_image_surface_t *image;
 
 	status = _cairo_surface_acquire_source_image (pattern->surface,
 						      &image,
 						      &attr->extra);
 	if (status)
 	    return status;
 
 	*out = &image->base;
 	attr->acquired = TRUE;
     }
     else
     {
+	cairo_rectangle_int16_t extents;
+	status = _cairo_surface_get_extents (pattern->surface, &extents);
+	if (status)
+	    return status;
+
 	/* If we're repeating, we just play it safe and clone the entire surface. */
-	if (attr->extend == CAIRO_EXTEND_REPEAT) {
-	    cairo_rectangle_int16_t extents;
-	    status = _cairo_surface_get_extents (pattern->surface, &extents);
+	/* If requested width and height are -1, clone the entire surface.
+	 * This is relied on in the svg backend. */
+	if (attr->extend == CAIRO_EXTEND_REPEAT ||
+	    (width == (unsigned int) -1 && height == (unsigned int) -1)) {
 	    x = extents.x;
 	    y = extents.y;
 	    width = extents.width;
 	    height = extents.height;
 	} else {
 	    /* Otherwise, we first transform the rectangle to the
 	     * coordinate space of the source surface so that we can
 	     * clone only that portion of the surface that will be
 	     * read. */
 	    if (! _cairo_matrix_is_identity (&attr->matrix)) {
 		double x1 = x;
 		double y1 = y;
 		double x2 = x + width;
 		double y2 = y + height;
 		cairo_bool_t is_tight;
 
-		cairo_matrix_transform_bounding_box  (&attr->matrix,
-						      &x1, &y1, &x2, &y2,
-						      &is_tight);
-		x = floor (x1);
-		y = floor (y1);
-		width = ceil (x2) - x;
-		height = ceil (y2) - y;
+		_cairo_matrix_transform_bounding_box  (&attr->matrix,
+						       &x1, &y1, &x2, &y2,
+						       &is_tight);
+
+		/* The transform_bounding_box call may have resulted
+		 * in a region larger than the surface, but we never
+		 * want to clone more than the surface itself, (we
+		 * know we're not repeating at this point due to the
+		 * above. */
+		x = MAX (0, floor (x1));
+		y = MAX (0, floor (y1));
+		width = MIN (extents.width, ceil (x2)) - x;
+		height = MIN (extents.height, ceil (y2)) - y;
 	    }
 	    x += tx;
 	    y += ty;
 	}
 
 	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);
+	    if (!*out)
+		return CAIRO_STATUS_NO_MEMORY;
+
+	    (*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);
+	}
     }
 
     return status;
 }
 
 /**
  * _cairo_pattern_acquire_surface:
  * @pattern: a #cairo_pattern_t
@@ -1251,20 +1479,20 @@ cairo_int_status_t
 	{
 	    cairo_solid_pattern_t solid;
 
 	    if (src->n_stops)
 	    {
 		cairo_color_t color;
 
 		_cairo_color_init_rgba (&color,
-					src->stops->color.red / 65536.0,
-					src->stops->color.green / 65536.0,
-					src->stops->color.blue / 65536.0,
-					src->stops->color.alpha / 65536.0);
+					src->stops->color.red / 65535.0,
+					src->stops->color.green / 65535.0,
+					src->stops->color.blue / 65535.0,
+					src->stops->color.alpha / 65535.0);
 
 		_cairo_pattern_init_solid (&solid, &color);
 	    }
 	    else
 	    {
 		const cairo_color_t *color;
 
 		color =	_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
@@ -1446,16 +1674,17 @@ cairo_status_t
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
 	if (status)
 	    return status;
 
 	imatrix = pattern->matrix;
 	cairo_matrix_invert (&imatrix);
 
+	/* XXX Use _cairo_matrix_transform_bounding_box here */
 	for (sy = 0; sy <= 1; sy++) {
 	    for (sx = 0; sx <= 1; sx++) {
 		x = surface_extents.x + sx * surface_extents.width;
 		y = surface_extents.y + sy * surface_extents.height;
 		cairo_matrix_transform_point (&imatrix, &x, &y);
 		if (x < 0) x = 0;
 		if (x > INT16_MAX) x = INT16_MAX;
 		if (y < 0) y = 0;
@@ -1564,16 +1793,17 @@ cairo_pattern_get_surface (cairo_pattern
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * cairo_pattern_get_color_stop_rgba
  * @pattern: a #cairo_pattern_t
  * @index: index of the stop to return data for
+ * @offset: return value for the offset of the stop, or %NULL
  * @red: return value for red component of color, or %NULL
  * @green: return value for green component of color, or %NULL
  * @blue: return value for blue component of color, or %NULL
  * @alpha: return value for alpha component of color, or %NULL
  *
  * Gets the color and offset information at the given @index for a
  * gradient pattern.  Values of @index are 0 to 1 less than the number
  * returned by cairo_pattern_get_color_stop_count().
@@ -1680,22 +1910,22 @@ cairo_pattern_get_linear_points (cairo_p
 	*y1 = _cairo_fixed_to_double (linear->gradient.p2.y);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * cairo_pattern_get_radial_circles
  * @pattern: a #cairo_pattern_t
- * @x0: return value for the x coordinate of the center of the first (inner) circle, or %NULL
- * @y0: return value for the y coordinate of the center of the first (inner) circle, or %NULL
- * @r0: return value for the radius of the first (inner) circle, or %NULL
- * @x1: return value for the x coordinate of the center of the second (outer) circle, or %NULL
- * @y1: return value for the y coordinate of the center of the second (outer) circle, or %NULL
- * @r1: return value for the radius of the second (outer) circle, or %NULL
+ * @x0: return value for the x coordinate of the center of the first circle, or %NULL
+ * @y0: return value for the y coordinate of the center of the first circle, or %NULL
+ * @r0: return value for the radius of the first circle, or %NULL
+ * @x1: return value for the x coordinate of the center of the second circle, or %NULL
+ * @y1: return value for the y coordinate of the center of the second circle, or %NULL
+ * @r1: return value for the radius of the second circle, or %NULL
  *
  * Gets the gradient endpoint circles for a radial gradient, each
  * specified as a center coordinate and a radius.
  *
  * Return value: %CAIRO_STATUS_SUCCESS, or
  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
  * gradient pattern.
  *
@@ -1707,22 +1937,22 @@ cairo_pattern_get_radial_circles (cairo_
 				  double *x1, double *y1, double *r1)
 {
     cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
 
     if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
 
     if (x0)
-	*x0 = _cairo_fixed_to_double (radial->gradient.inner.x);
+	*x0 = _cairo_fixed_to_double (radial->gradient.c1.x);
     if (y0)
-	*y0 = _cairo_fixed_to_double (radial->gradient.inner.y);
+	*y0 = _cairo_fixed_to_double (radial->gradient.c1.y);
     if (r0)
-	*r0 = _cairo_fixed_to_double (radial->gradient.inner.radius);
+	*r0 = _cairo_fixed_to_double (radial->gradient.c1.radius);
     if (x1)
-	*x1 = _cairo_fixed_to_double (radial->gradient.outer.x);
+	*x1 = _cairo_fixed_to_double (radial->gradient.c2.x);
     if (y1)
-	*y1 = _cairo_fixed_to_double (radial->gradient.outer.y);
+	*y1 = _cairo_fixed_to_double (radial->gradient.c2.y);
     if (r1)
-	*r1 = _cairo_fixed_to_double (radial->gradient.outer.radius);
+	*r1 = _cairo_fixed_to_double (radial->gradient.c2.radius);
 
     return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-pdf-surface.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c
@@ -272,17 +272,18 @@ static cairo_surface_t *
 
     _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
     _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->alphas, sizeof (double));
 
-    surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT);
+    surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT,
+                                                               PDF_SURFACE_MAX_GLYPHS_PER_FONT);
     if (! surface->font_subsets) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (surface);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
 
@@ -374,17 +375,19 @@ cairo_pdf_surface_create (const char		*f
 {
     cairo_status_t status;
     cairo_output_stream_t *output;
 
     output = _cairo_output_stream_create_for_filename (filename);
     status = _cairo_output_stream_get_status (output);
     if (status) {
 	_cairo_error (status);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return (status == CAIRO_STATUS_WRITE_ERROR) ?
+		(cairo_surface_t*) &_cairo_surface_nil_write_error :
+		(cairo_surface_t*) &_cairo_surface_nil;
     }
 
     return _cairo_pdf_surface_create_for_stream_internal (output,
 							  width_in_points,
 							  height_in_points);
 }
 
 static cairo_bool_t
@@ -649,17 +652,17 @@ compress_dup (const void *data, unsigned
 
 /* Emit alpha channel from the image into the given data, providing
  * an id that can be used to reference the resulting SMask object.
  *
  * In the case that the alpha channel happens to be all opaque, then
  * no SMask object will be emitted and *id_ret will be set to 0.
  */
 static cairo_status_t
-emit_smask (cairo_pdf_surface_t		*surface,
+_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t		*surface,
 	    cairo_image_surface_t	*image,
 	    cairo_pdf_resource_t	*stream_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     char *alpha, *alpha_compressed;
     unsigned long alpha_size, alpha_compressed_size;
     pixman_bits_t *pixel;
     int i, x, y;
@@ -720,17 +723,17 @@ emit_smask (cairo_pdf_surface_t		*surfac
     free (alpha);
  CLEANUP:
     return status;
 }
 
 /* Emit image data into the given surface, providing a resource that
  * can be used to reference the data in image_ret. */
 static cairo_status_t
-emit_image (cairo_pdf_surface_t		*surface,
+_cairo_pdf_surface_emit_image (cairo_pdf_surface_t		*surface,
 	    cairo_image_surface_t	*image,
 	    cairo_pdf_resource_t	*image_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
     pixman_bits_t *pixel;
     int i, x, y;
@@ -739,17 +742,17 @@ emit_image (cairo_pdf_surface_t		*surfac
 
     /* XXX: Need to rewrite this as a pdf_surface function with
      * pause/resume of content_stream, (currently the only caller does
      * the pause/resume already, but that is expected to change in the
      * future). */
 
     /* These are the only image formats we currently support, (which
      * makes things a lot simpler here). This is enforced through
-     * _analyze_operation which only accept source surfaces of
+     * _cairo_pdf_surface_analyze_operation which only accept source surfaces of
      * CONTENT_COLOR or CONTENT_COLOR_ALPHA.
      */
     assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32);
 
     rgb_size = image->height * image->width * 3;
     rgb = malloc (rgb_size);
     if (rgb == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
@@ -789,17 +792,17 @@ emit_image (cairo_pdf_surface_t		*surfac
     compressed = compress_dup (rgb, rgb_size, &compressed_size);
     if (compressed == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto CLEANUP_RGB;
     }
 
     need_smask = FALSE;
     if (image->format == CAIRO_FORMAT_ARGB32) {
-	status = emit_smask (surface, image, &smask);
+	status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
 	if (status)
 	    goto CLEANUP_COMPRESSED;
 
 	if (smask.id)
 	    need_smask = TRUE;
     }
 
 #define IMAGE_DICTIONARY	"   /Type /XObject\r\n"		\
@@ -833,17 +836,17 @@ emit_image (cairo_pdf_surface_t		*surfac
     free (compressed);
  CLEANUP_RGB:
     free (rgb);
  CLEANUP:
     return status;
 }
 
 static cairo_status_t
-emit_solid_pattern (cairo_pdf_surface_t *surface,
+_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
 		    cairo_solid_pattern_t *pattern)
 {
     cairo_pdf_resource_t alpha;
 
     alpha = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha);
 
     /* With some work, we could separate the stroking
      * or non-stroking color here as actually needed. */
@@ -858,87 +861,90 @@ emit_solid_pattern (cairo_pdf_surface_t 
 				 pattern->color.green,
 				 pattern->color.blue,
 				 alpha.id);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-emit_surface_pattern (cairo_pdf_surface_t	*surface,
+_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
 		      cairo_surface_pattern_t	*pattern)
 {
     cairo_pdf_resource_t stream;
+    cairo_surface_t *pat_surface;
+    cairo_surface_attributes_t pat_attr;
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
-    int xstep, ystep;
+    double xstep, ystep;
     cairo_rectangle_int16_t surface_extents;
 
     /* XXX: Should do something clever here for PDF source surfaces ? */
 
     _cairo_pdf_surface_pause_content_stream (surface);
 
-    status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
+    status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
+					     (cairo_surface_t *)surface,
+					     0, 0, -1, -1,
+					     &pat_surface, &pat_attr);
     if (status)
 	return status;
 
-    status = emit_image (surface, image, &image_resource);
+    status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
+    if (status)
+	goto BAIL2;
+
+    status = _cairo_pdf_surface_emit_image (surface, image, &image_resource);
     if (status)
 	goto BAIL;
 
     _cairo_surface_get_extents (&surface->base, &surface_extents);
 
     switch (extend) {
+    /* We implement EXTEND_PAD like EXTEND_NONE for now */
+    case CAIRO_EXTEND_PAD:
     case CAIRO_EXTEND_NONE:
         {
-	    /* In PDF, (as far as I can tell), all patterns are
+	    /* In PS/PDF, (as far as I can tell), all patterns are
 	     * repeating. So we support cairo's EXTEND_NONE semantics
 	     * by setting the repeat step size to a size large enough
 	     * to guarantee that no more than a single occurrence will
 	     * be visible.
 	     *
-	     * First, map the pattern's extents through the inverse
-	     * pattern matrix to compute the device-space bounds of
-	     * the desired single occurrence. Then consider the bounds
-	     * of (the union of this rectangle with the target surface
-	     * extents). If the repeat size is larger than the
-	     * diagonal of the bounds of the union, then it is
-	     * guaranteed to never repeat visibly.
+	     * First, map the surface extents into pattern space (since
+	     * xstep and ystep are in pattern space).  Then use an upper
+	     * bound on the length of the diagonal of the pattern image
+	     * and the surface as repeat size.  This guarantees to never
+	     * repeat visibly.
 	     */
 	    double x1 = 0.0, y1 = 0.0;
-	    double x2 = image->width, y2 = image->height;
-	    cairo_matrix_t surface_to_device = pattern->base.matrix;
-	    cairo_matrix_invert (&surface_to_device);
-	    cairo_matrix_transform_bounding_box (&surface_to_device,
-						 &x1, &y1, &x2, &y2,
-						 NULL);
+	    double x2 = surface->width, y2 = surface->height;
+	    _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
+						  &x1, &y1, &x2, &y2,
+						  NULL);
+
 	    /* Rather than computing precise bounds of the union, just
 	     * add the surface extents unconditionally. We only
 	     * required an answer that's large enough, we don't really
-	     * care if it's not as tight as possible. */
-	    x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width;
-	    y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height;
-	    /* Similarly, don't bother computing the square root to
-	     * determine the length of the final diagonal. */
-	    xstep = _cairo_lround (ceil (x1 * y1));
-	    ystep = _cairo_lround (ceil (x1 * y1));
+	     * care if it's not as tight as possible.*/
+	    xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
+				  image->width + image->height);
 	}
 	break;
     case CAIRO_EXTEND_REPEAT:
+    case CAIRO_EXTEND_REFLECT:
 	xstep = image->width;
 	ystep = image->height;
 	break;
-    /* All the rest should have been analyzed away, so this case
-     * should be unreachable. */
-    case CAIRO_EXTEND_REFLECT:
-    case CAIRO_EXTEND_PAD:
+    /* All the rest (if any) should have been analyzed away, so this
+     * case should be unreachable. */
     default:
 	ASSERT_NOT_REACHED;
 	xstep = 0;
 	ystep = 0;
     }
 
     /* At this point, (that is, within the surface backend interface),
      * the pattern's matrix maps from cairo's device space to cairo's
@@ -975,18 +981,18 @@ emit_surface_pattern (cairo_pdf_surface_
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
     cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
     stream = _cairo_pdf_surface_open_stream (surface,
                                              FALSE,
 					     "   /BBox [0 0 %d %d]\r\n"
-					     "   /XStep %d\r\n"
-					     "   /YStep %d\r\n"
+					     "   /XStep %f\r\n"
+					     "   /YStep %f\r\n"
 					     "   /PatternType 1\r\n"
 					     "   /TilingType 1\r\n"
 					     "   /PaintType 1\r\n"
 					     "   /Matrix [ %f %f %f %f %f %f ]\r\n"
 					     "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
 					     image->width, image->height,
 					     xstep, ystep,
 					     pdf_p2d.xx, pdf_p2d.yx,
@@ -1011,29 +1017,31 @@ emit_surface_pattern (cairo_pdf_surface_
      * or non-stroking pattern here as actually needed. */
     _cairo_output_stream_printf (surface->output,
 				 "/Pattern CS /res%d SCN "
 				 "/Pattern cs /res%d scn "
 				 "/a%d gs\r\n",
 				 stream.id, stream.id, alpha.id);
 
  BAIL:
-    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+    _cairo_surface_release_source_image (pat_surface, image, image_extra);
+ BAIL2:
+    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
 
     return status;
 }
 
 typedef struct _cairo_pdf_color_stop {
     double	  		offset;
     cairo_pdf_resource_t	gradient;
     unsigned char		color_char[4];
 } cairo_pdf_color_stop_t;
 
 static cairo_pdf_resource_t
-emit_linear_colorgradient (cairo_pdf_surface_t		*surface,
+_cairo_pdf_surface_emit_linear_colorgradient (cairo_pdf_surface_t		*surface,
 			   cairo_pdf_color_stop_t	*stop1,
 			   cairo_pdf_color_stop_t	*stop2)
 {
     cairo_pdf_resource_t function = _cairo_pdf_surface_new_object (surface);
 
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 0\r\n"
@@ -1052,26 +1060,26 @@ emit_linear_colorgradient (cairo_pdf_sur
 				 "\r\n"
 				 "endstream\r\n"
 				 "endobj\r\n");
 
     return function;
 }
 
 static cairo_pdf_resource_t
-emit_stitched_colorgradient (cairo_pdf_surface_t   *surface,
+_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t   *surface,
 			    unsigned int 	   n_stops,
 			    cairo_pdf_color_stop_t stops[])
 {
     cairo_pdf_resource_t function;
     unsigned int i;
 
     /* emit linear gradients between pairs of subsequent stops... */
     for (i = 0; i < n_stops-1; i++) {
-	stops[i].gradient = emit_linear_colorgradient (surface,
+	stops[i].gradient = _cairo_pdf_surface_emit_linear_colorgradient (surface,
 						       &stops[i],
 						       &stops[i+1]);
     }
 
     /* ... and stitch them together */
     function = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
@@ -1114,17 +1122,17 @@ emit_stitched_colorgradient (cairo_pdf_s
 				 "endobj\r\n");
 
     return function;
 }
 
 #define COLOR_STOP_EPSILON 1e-6
 
 static cairo_pdf_resource_t
-emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
+_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
 {
     cairo_pdf_resource_t    function;
     cairo_pdf_color_stop_t *allstops, *stops;
     unsigned int i, n_stops;
 
     function = _cairo_pdf_surface_new_object (surface);
 
     allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
@@ -1157,40 +1165,40 @@ emit_pattern_stops (cairo_pdf_surface_t 
 		    &stops[n_stops - 1],
 		    sizeof (cairo_pdf_color_stop_t));
 	    stops[n_stops].offset = 1.0;
 	    n_stops++;
     }
 
     if (n_stops == 2) {
 	/* no need for stitched function */
-	function = emit_linear_colorgradient (surface, &stops[0], &stops[1]);
+	function = _cairo_pdf_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
     } else {
 	/* multiple stops: stitch. XXX possible optimization: regulary spaced
 	 * stops do not require stitching. XXX */
-	function = emit_stitched_colorgradient (surface,
+	function = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
 					       n_stops,
 					       stops);
     }
 
     free (allstops);
 
     return function;
 }
 
 static cairo_status_t
-emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
+_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
 {
     cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1;
     cairo_matrix_t p2u;
 
     _cairo_pdf_surface_pause_content_stream (surface);
 
-    function = emit_pattern_stops (surface, &pattern->base);
+    function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
     if (function.id == 0)
 	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
     cairo_matrix_invert (&p2u);
 
     x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);
     y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);
@@ -1235,38 +1243,38 @@ emit_linear_pattern (cairo_pdf_surface_t
 				 alpha.id);
 
     _cairo_pdf_surface_resume_content_stream (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
+_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
 {
     cairo_pdf_resource_t function, pattern_resource, alpha;
     double x0, y0, x1, y1, r0, r1;
     cairo_matrix_t p2u;
 
     _cairo_pdf_surface_pause_content_stream (surface);
 
-    function = emit_pattern_stops (surface, &pattern->base);
+    function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
     if (function.id == 0)
 	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
     cairo_matrix_invert (&p2u);
 
-    x0 = _cairo_fixed_to_double (pattern->gradient.inner.x);
-    y0 = _cairo_fixed_to_double (pattern->gradient.inner.y);
-    r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius);
+    x0 = _cairo_fixed_to_double (pattern->gradient.c1.x);
+    y0 = _cairo_fixed_to_double (pattern->gradient.c1.y);
+    r0 = _cairo_fixed_to_double (pattern->gradient.c1.radius);
     cairo_matrix_transform_point (&p2u, &x0, &y0);
-    x1 = _cairo_fixed_to_double (pattern->gradient.outer.x);
-    y1 = _cairo_fixed_to_double (pattern->gradient.outer.y);
-    r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius);
+    x1 = _cairo_fixed_to_double (pattern->gradient.c2.x);
+    y1 = _cairo_fixed_to_double (pattern->gradient.c2.y);
+    r1 = _cairo_fixed_to_double (pattern->gradient.c2.radius);
     cairo_matrix_transform_point (&p2u, &x1, &y1);
 
     /* FIXME: This is surely crack, but how should you scale a radius
      * in a non-orthogonal coordinate system? */
     cairo_matrix_transform_distance (&p2u, &r0, &r1);
 
     /* FIXME: There is a difference between the cairo gradient extend
      * semantics and PDF extend semantics. PDFs extend=false means
@@ -1311,30 +1319,30 @@ emit_radial_pattern (cairo_pdf_surface_t
 				 alpha.id);
 
     _cairo_pdf_surface_resume_content_stream (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
+_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
 {
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
 
     case CAIRO_PATTERN_TYPE_SURFACE:
-	return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
 
     case CAIRO_PATTERN_TYPE_LINEAR:
-	return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
 
     case CAIRO_PATTERN_TYPE_RADIAL:
-	return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
 
     }
 
     ASSERT_NOT_REACHED;
     return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
 }
 
 static cairo_int_status_t
@@ -1625,21 +1633,100 @@ static void
 
     /* TODO: Figure out wich other defaults to be inherited by /Page
      * objects. */
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 }
 
+static cairo_pdf_resource_t
+_cairo_pdf_surface_emit_toUnicode_stream (cairo_pdf_surface_t		*surface,
+                                          cairo_scaled_font_subset_t	*font_subset)
+{
+    const cairo_scaled_font_backend_t *backend;
+    cairo_pdf_resource_t stream;
+    unsigned int i;
+
+    if (font_subset->to_unicode == NULL) {
+        stream.id = 0;
+        return stream;
+    }
+
+    if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) {
+        backend = font_subset->scaled_font->backend;
+        if (backend->map_glyphs_to_unicode == NULL) {
+            stream.id = 0;
+            return stream;
+        }
+        backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset);
+    }
+
+    stream = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
+    _cairo_output_stream_printf (surface->output,
+                                 "/CIDInit /ProcSet findresource begin\r\n"
+                                 "12 dict begin\r\n"
+                                 "begincmap\r\n"
+                                 "/CIDSystemInfo\r\n"
+                                 "<< /Registry (Cairo)\r\n"
+                                 "   /Ordering (ToUnicode-%d-%d)\r\n"
+                                 "   /Supplement 0\r\n"
+                                 ">> def\r\n"
+                                 "/CMapName /Cairo-ToUnicode-%d-%d def\r\n"
+                                 "/CMapType 2 def\r\n"
+                                 "1 begincodespacerange\r\n"
+                                 "<00> <ff>\r\n"
+                                 "endcodespacerange\r\n",
+                                 font_subset->font_id,
+                                 font_subset->subset_id,
+                                 font_subset->font_id,
+                                 font_subset->subset_id);
+
+    /* The CMap specification has a limit of 100 characters per beginbfchar operator */
+    _cairo_output_stream_printf (surface->output,
+                                 "%d beginbfchar\r\n",
+                                 font_subset->num_glyphs > 100 ? 100 : font_subset->num_glyphs);
+    for (i = 0; i < font_subset->num_glyphs; i++) {
+        if (i != 0 && i % 100 == 0) {
+            _cairo_output_stream_printf (surface->output,
+                                         "endbfchar\r\n"
+                                         "%d beginbfchar\r\n",
+                                         font_subset->num_glyphs - i > 100 ? 100 : font_subset->num_glyphs - i);
+        }
+        _cairo_output_stream_printf (surface->output,
+                                     "<%02x> <%04x>\r\n",
+                                     i, font_subset->to_unicode[i]);
+    }
+    _cairo_output_stream_printf (surface->output,
+                                 "endbfchar\r\n");
+
+    if (font_subset->num_glyphs < 256) {
+        _cairo_output_stream_printf (surface->output,
+                                     "1 beginnotdefrange\r\n"
+                                     "<%02x> <ff> 0\r\n"
+                                     "endnotdefrange\r\n",
+                                     font_subset->num_glyphs);
+    }
+
+    _cairo_output_stream_printf (surface->output,
+                                "endcmap\r\n"
+                                "CMapName currentdict /CMap defineresource pop\r\n"
+                                "end\r\n"
+                                 "end\r\n");
+
+    _cairo_pdf_surface_close_stream (surface);
+
+    return stream;
+}
+
 static cairo_status_t
 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t		*surface,
                                          cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
     cairo_status_t status;
     cairo_pdf_font_t font;
     cairo_cff_subset_t subset;
     unsigned long compressed_length;
     char *compressed;
     unsigned int i;
     char name[64];
 
@@ -1667,16 +1754,18 @@ static cairo_status_t
 				 compressed_length);
     _cairo_output_stream_write (surface->output, compressed, compressed_length);
     _cairo_output_stream_printf (surface->output,
 				 "\r\n"
 				 "endstream\r\n"
 				 "endobj\r\n");
     free (compressed);
 
+    to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
+
     descriptor = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /FontDescriptor\r\n"
 				 "   /FontName /%s\r\n"
 				 "   /Flags 4\r\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
 				 "   /ItalicAngle 0\r\n"
@@ -1705,26 +1794,33 @@ static cairo_status_t
 				 "   /Subtype /Type1\r\n"
 				 "   /BaseFont /%s\r\n"
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n"
 				 "   /FontDescriptor %d 0 R\r\n"
 				 "   /Widths [",
 				 subset_resource.id,
 				 subset.base_font,
-				 font_subset->num_glyphs,
+				 font_subset->num_glyphs - 1,
 				 descriptor.id);
 
     for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output,
 				     " %d",
 				     subset.widths[i]);
 
     _cairo_output_stream_printf (surface->output,
-				 " ]\r\n"
+				 " ]\r\n");
+
+    if (to_unicode_stream.id != 0)
+        _cairo_output_stream_printf (surface->output,
+                                     "    /ToUnicode %d 0 R\r\n",
+                                     to_unicode_stream.id);
+
+    _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
     font.subset_resource = subset_resource;
     _cairo_array_append (&surface->fonts, &font);
 
@@ -1733,17 +1829,17 @@ static cairo_status_t
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
                                     cairo_scaled_font_subset_t	*font_subset,
                                     cairo_type1_subset_t        *subset)
 {
-    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
     unsigned long length, compressed_length;
     char *compressed;
     unsigned int i;
 
 
     /* We ignore the zero-trailer and set Length3 to 0. */
     length = subset->header_length + subset->data_length;
@@ -1767,16 +1863,18 @@ static cairo_status_t
 				 subset->data_length);
     _cairo_output_stream_write (surface->output, compressed, compressed_length);
     _cairo_output_stream_printf (surface->output,
 				 "\r\n"
 				 "endstream\r\n"
 				 "endobj\r\n");
     free (compressed);
 
+    to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
+
     descriptor = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /FontDescriptor\r\n"
 				 "   /FontName /%s\r\n"
 				 "   /Flags 4\r\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
 				 "   /ItalicAngle 0\r\n"
@@ -1814,17 +1912,24 @@ static cairo_status_t
 				 descriptor.id);
 
     for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output,
 				     " %d",
 				     subset->widths[i]);
 
     _cairo_output_stream_printf (surface->output,
-				 " ]\r\n"
+				 " ]\r\n");
+
+    if (to_unicode_stream.id != 0)
+        _cairo_output_stream_printf (surface->output,
+                                     "    /ToUnicode %d 0 R\r\n",
+                                     to_unicode_stream.id);
+
+    _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
     font.subset_resource = subset_resource;
     _cairo_array_append (&surface->fonts, &font);
 
@@ -1868,21 +1973,23 @@ static cairo_status_t
 	return status;
 
     status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
 
     _cairo_type1_fallback_fini (&subset);
     return status;
 }
 
+#define PDF_UNITS_PER_EM 1000
+
 static cairo_status_t
 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 					      cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_pdf_resource_t stream, descriptor, encoding, subset_resource, to_unicode_stream;
     cairo_status_t status;
     cairo_pdf_font_t font;
     cairo_truetype_subset_t subset;
     unsigned long compressed_length;
     char *compressed;
     unsigned int i;
 
     status = _cairo_truetype_subset_init (&subset, font_subset);
@@ -1909,64 +2016,91 @@ static cairo_status_t
 				 subset.data_length);
     _cairo_output_stream_write (surface->output, compressed, compressed_length);
     _cairo_output_stream_printf (surface->output,
 				 "\r\n"
 				 "endstream\r\n"
 				 "endobj\r\n");
     free (compressed);
 
+    to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
+
     descriptor = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /FontDescriptor\r\n"
-				 "   /FontName /7%s\r\n"
+				 "   /FontName /%s\r\n"
 				 "   /Flags 4\r\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
 				 "   /ItalicAngle 0\r\n"
 				 "   /Ascent %ld\r\n"
 				 "   /Descent %ld\r\n"
-				 "   /CapHeight 500\r\n"
+				 "   /CapHeight %ld\r\n"
 				 "   /StemV 80\r\n"
 				 "   /StemH 80\r\n"
 				 "   /FontFile2 %u 0 R\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
 				 descriptor.id,
 				 subset.base_font,
-				 subset.x_min,
-				 subset.y_min,
-				 subset.x_max,
-				 subset.y_max,
-				 subset.ascent,
-				 subset.descent,
+				 (long)(subset.x_min*PDF_UNITS_PER_EM),
+				 (long)(subset.y_min*PDF_UNITS_PER_EM),
+                                 (long)(subset.x_max*PDF_UNITS_PER_EM),
+				 (long)(subset.y_max*PDF_UNITS_PER_EM),
+				 (long)(subset.ascent*PDF_UNITS_PER_EM),
+				 (long)(subset.descent*PDF_UNITS_PER_EM),
+				 (long)(subset.y_max*PDF_UNITS_PER_EM),
 				 stream.id);
 
+    encoding = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Encoding\r\n"
+				 "   /Differences [0 ",
+                                 encoding.id);
+
+    for (i = 0; i < font_subset->num_glyphs; i++)
+            _cairo_output_stream_printf (surface->output, "/g%d ", i);
+
+    _cairo_output_stream_printf (surface->output,
+                                 " ]\r\n"
+				 ">>\r\n"
+				 "endobj\r\n");
+
     subset_resource = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /TrueType\r\n"
 				 "   /BaseFont /%s\r\n"
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n"
 				 "   /FontDescriptor %d 0 R\r\n"
+				 "   /Encoding %d 0 R\r\n"
 				 "   /Widths [",
 				 subset_resource.id,
 				 subset.base_font,
 				 font_subset->num_glyphs - 1,
-				 descriptor.id);
+				 descriptor.id,
+                                 encoding.id);
 
     for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output,
-				     " %d",
-				     subset.widths[i]);
+				     " %ld",
+				     (long)(subset.widths[i]*PDF_UNITS_PER_EM));
 
     _cairo_output_stream_printf (surface->output,
-				 " ]\r\n"
+				 " ]\r\n");
+
+    if (to_unicode_stream.id != 0)
+        _cairo_output_stream_printf (surface->output,
+                                     "    /ToUnicode %d 0 R\r\n",
+                                     to_unicode_stream.id);
+
+    _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
     font.subset_resource = subset_resource;
     _cairo_array_append (&surface->fonts, &font);
 
@@ -2020,50 +2154,60 @@ static cairo_int_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t	*surface,
 				      cairo_scaled_font_t	*scaled_font,
 				      unsigned long		 glyph_index,
-				      cairo_pdf_resource_t	*glyph_ret)
+				      cairo_pdf_resource_t	*glyph_ret,
+                                      cairo_box_t               *bbox,
+                                      double                    *width)
 {
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_status_t status;
     cairo_image_surface_t *image;
     unsigned char *row, *byte;
     int rows, cols;
+    double x_advance, y_advance;
 
     status = _cairo_scaled_glyph_lookup (scaled_font,
 					 glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					 &scaled_glyph);
     if (status)
 	return status;
 
+    x_advance = scaled_glyph->metrics.x_advance;
+    y_advance = scaled_glyph->metrics.y_advance;
+    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
+    *bbox = scaled_glyph->bbox;
+    *width = x_advance;
+
     image = scaled_glyph->surface;
     if (image->format != CAIRO_FORMAT_A1) {
 	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
 	if (cairo_surface_status (&image->base))
 	    return cairo_surface_status (&image->base);
     }
 
-    *glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
+    *glyph_ret = _cairo_pdf_surface_open_stream (surface, TRUE, NULL);
 
     _cairo_output_stream_printf (surface->output,
-				 "0 0 %f %f %f %f d1\r\n",
+				 "%f 0 %f %f %f %f d1\r\n",
+                                 x_advance,
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
+				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
-				 - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
+				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 
     _cairo_output_stream_printf (surface->output,
-				 "%f 0.0 0.0 %f %f %f cm\r\n",
+				 "%f 0 0 %f %f %f cm\r\n",
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
 
     _cairo_output_stream_printf (surface->output,
 				 "BI\r\n"
 				 "/IM true\r\n"
@@ -2092,54 +2236,85 @@ static cairo_int_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t	*surface,
 			       cairo_scaled_font_t	*scaled_font,
 			       unsigned long		 glyph_index,
-			       cairo_pdf_resource_t	*glyph_ret)
+			       cairo_pdf_resource_t	*glyph_ret,
+                               cairo_box_t              *bbox,
+                               double                   *width)
 {
     cairo_status_t status;
 
     status = _cairo_pdf_surface_emit_outline_glyph (surface,
 						    scaled_font,
 						    glyph_index,
 						    glyph_ret);
     if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
 						       scaled_font,
 						       glyph_index,
-						       glyph_ret);
+						       glyph_ret,
+                                                       bbox,
+                                                       width);
 
     if (status)
 	_cairo_surface_set_error (&surface->base, status);
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
+    cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
     cairo_matrix_t matrix;
+    double *widths;
     unsigned int i;
+    cairo_box_t font_bbox = {{0,0},{0,0}};
+    cairo_box_t bbox = {{0,0},{0,0}};
 
     glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
     if (glyphs == NULL) {
 	_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
+    widths = malloc (font_subset->num_glyphs * sizeof (double));
+    if (widths == NULL) {
+        free (glyphs);
+	_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	_cairo_pdf_surface_emit_glyph (surface,
 				       font_subset->scaled_font,
 				       font_subset->glyphs[i],
-				       &glyphs[i]);
+				       &glyphs[i],
+                                       &bbox,
+                                       &widths[i]);
+        if (i == 0) {
+            font_bbox.p1.x = bbox.p1.x;
+            font_bbox.p1.y = bbox.p1.y;
+            font_bbox.p2.x = bbox.p2.x;
+            font_bbox.p2.y = bbox.p2.y;
+        } else {
+            if (bbox.p1.x < font_bbox.p1.x)
+                font_bbox.p1.x = bbox.p1.x;
+            if (bbox.p1.y < font_bbox.p1.y)
+                font_bbox.p1.y = bbox.p1.y;
+            if (bbox.p2.x > font_bbox.p2.x)
+                font_bbox.p2.x = bbox.p2.x;
+            if (bbox.p2.y > font_bbox.p2.y)
+                font_bbox.p2.y = bbox.p2.y;
+        }
     }
 
     encoding = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Encoding\r\n"
 				 "   /Differences [0", encoding.id);
     for (i = 0; i < font_subset->num_glyphs; i++)
@@ -2159,60 +2334,72 @@ static cairo_status_t
 				     " /%d %d 0 R\r\n",
 				     i, glyphs[i].id);
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     free (glyphs);
 
+    to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
+
     subset_resource = _cairo_pdf_surface_new_object (surface);
     matrix = font_subset->scaled_font->scale;
     cairo_matrix_invert (&matrix);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type3\r\n"
-				 "   /FontBBox [0 0 0 0]\r\n"
+				 "   /FontBBox [%f %f %f %f]\r\n"
 				 "   /FontMatrix [ %f %f %f %f 0 0 ]\r\n"
 				 "   /Encoding %d 0 R\r\n"
 				 "   /CharProcs %d 0 R\r\n"
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n",
 				 subset_resource.id,
+				 _cairo_fixed_to_double (font_bbox.p1.x),
+				 _cairo_fixed_to_double (font_bbox.p1.y),
+				 _cairo_fixed_to_double (font_bbox.p2.x),
+				 _cairo_fixed_to_double (font_bbox.p2.y),
 				 matrix.xx,
 				 matrix.yx,
 				 -matrix.xy,
 				 -matrix.yy,
 				 encoding.id,
 				 char_procs.id,
 				 font_subset->num_glyphs - 1);
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Widths [");
     for (i = 0; i < font_subset->num_glyphs; i++)
-	_cairo_output_stream_printf (surface->output, " 0");
+	_cairo_output_stream_printf (surface->output, " %f", widths[i]);
     _cairo_output_stream_printf (surface->output,
 				 "]\r\n");
+    free (widths);
+
+    if (to_unicode_stream.id != 0)
+        _cairo_output_stream_printf (surface->output,
+                                     "    /ToUnicode %d 0 R\r\n",
+                                     to_unicode_stream.id);
 
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
     font.subset_resource = subset_resource;
     _cairo_array_append (&surface->fonts, &font);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				     void			*closure)
+_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                              void			 *closure)
 {
     cairo_pdf_surface_t *surface = closure;
     cairo_status_t status;
 
     status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
 
@@ -2224,147 +2411,50 @@ static void
 
     status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
 
     status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
+}
+
+static void
+_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                            void		       *closure)
+{
+    cairo_pdf_surface_t *surface = closure;
+    cairo_status_t status;
 
     status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status;
 
-    status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
-						 _cairo_pdf_surface_emit_font_subset,
-						 surface);
+    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
+                                                          _cairo_pdf_surface_emit_unscaled_font_subset,
+                                                          surface);
+    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
+                                                        _cairo_pdf_surface_emit_scaled_font_subset,
+                                                        surface);
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
     surface->font_subsets = NULL;
 
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-#if 0
-static cairo_status_t
-_cairo_pdf_surface_write_fonts (cairo_pdf_surface_t *surface)
-{
-    cairo_font_subset_t *font;
-    cairo_pdf_resource_t font_resource;
-    int num_fonts, i, j;
-    const char *data;
-    char *compressed;
-    unsigned long data_size, compressed_size;
-    cairo_pdf_resource_t stream, descriptor;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    num_fonts = _cairo_array_num_elements (&surface->fonts);
-    for (i = 0; i < num_fonts; i++) {
-	_cairo_array_copy_element (&surface->fonts, i, &font);
-
-	status = _cairo_font_subset_generate (font, &data, &data_size);
-	if (status)
-	    goto fail;
-
-	compressed = compress_dup (data, data_size, &compressed_size);
-	if (compressed == NULL) {
-	    status = CAIRO_STATUS_NO_MEMORY;
-	    goto fail;
-	}
-
-	stream = _cairo_pdf_surface_new_object (surface);
-	_cairo_output_stream_printf (surface->output,
-				     "%d 0 obj\r\n"
-				     "<< /Filter /FlateDecode\r\n"
-				     "   /Length %lu\r\n"
-				     "   /Length1 %lu\r\n"
-				     ">>\r\n"
-				     "stream\r\n",
-				     stream.id,
-				     compressed_size,
-				     data_size);
-	_cairo_output_stream_write (surface->output, compressed, compressed_size);
-	_cairo_output_stream_printf (surface->output,
-				     "\r\n"
-				     "endstream\r\n"
-				     "endobj\r\n");
-	free (compressed);
-
-	descriptor = _cairo_pdf_surface_new_object (surface);
-	_cairo_output_stream_printf (surface->output,
-				     "%d 0 obj\r\n"
-				     "<< /Type /FontDescriptor\r\n"
-				     "   /FontName /7%s\r\n"
-				     "   /Flags 4\r\n"
-				     "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
-				     "   /ItalicAngle 0\r\n"
-				     "   /Ascent %ld\r\n"
-				     "   /Descent %ld\r\n"
-				     "   /CapHeight 500\r\n"
-				     "   /StemV 80\r\n"
-				     "   /StemH 80\r\n"
-				     "   /FontFile2 %u 0 R\r\n"
-				     ">>\r\n"
-				     "endobj\r\n",
-				     descriptor.id,
-				     font->base_font,
-				     font->x_min,
-				     font->y_min,
-				     font->x_max,
-				     font->y_max,
-				     font->ascent,
-				     font->descent,
-				     stream.id);
-
-	font_resource.id = font->font_id;
-	_cairo_pdf_surface_update_object (surface, font_resource);
-	_cairo_output_stream_printf (surface->output,
-				     "%d 0 obj\r\n"
-				     "<< /Type /Font\r\n"
-				     "   /Subtype /TrueType\r\n"
-				     "   /BaseFont /%s\r\n"
-				     "   /FirstChar 0\r\n"
-				     "   /LastChar %d\r\n"
-				     "   /FontDescriptor %d 0 R\r\n"
-				     "   /Widths ",
-				     font->font_id,
-				     font->base_font,
-				     font->num_glyphs,
-				     descriptor.id);
-
-	_cairo_output_stream_printf (surface->output,
-				     "[");
-
-	for (j = 0; j < font->num_glyphs; j++)
-	    _cairo_output_stream_printf (surface->output,
-					 " %d",
-					 font->widths[j]);
-
-	_cairo_output_stream_printf (surface->output,
-				     " ]\r\n"
-				     ">>\r\n"
-				     "endobj\r\n");
-
-    fail:
-	_cairo_font_subset_destroy (font);
-    }
-
-    return status;
-}
-#endif
-
 static cairo_pdf_resource_t
 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
 {
     cairo_pdf_resource_t catalog;
 
     catalog = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
@@ -2439,19 +2529,22 @@ static cairo_status_t
     num_streams = _cairo_array_num_elements (&surface->streams);
     for (i = 0; i < num_streams; i++) {
 	_cairo_array_copy_element (&surface->streams, i, &stream);
 	_cairo_output_stream_printf (surface->output,
 				     " %d 0 R",
 				     stream.id);
     }
     _cairo_output_stream_printf (surface->output,
-				 " ]\r\n");
-
-    _cairo_output_stream_printf (surface->output,
+				 " ]\r\n"
+                                 "   /Group <<\r\n"
+                                 "      /Type /Group\r\n"
+                                 "      /S /Transparency\r\n"
+                                 "      /CS /DeviceRGB\r\n"
+                                 "   >>\r\n"
 				 ">>\r\n"
 				 "endobj\r\n");
 
     status = _cairo_array_append (&surface->pages, &page);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
@@ -2473,20 +2566,21 @@ static cairo_bool_t
     if (content == CAIRO_CONTENT_ALPHA)
 	return FALSE;
 */
 
     extend = cairo_pattern_get_extend (&pattern->base);
     switch (extend) {
     case CAIRO_EXTEND_NONE:
     case CAIRO_EXTEND_REPEAT:
+    case CAIRO_EXTEND_REFLECT:
+    /* There's no point returning FALSE for EXTEND_PAD, as the image
+     * surface does not currently implement it either */
+    case CAIRO_EXTEND_PAD:
 	return TRUE;
-    case CAIRO_EXTEND_REFLECT:
-    case CAIRO_EXTEND_PAD:
-	return FALSE;
     }
 
     ASSERT_NOT_REACHED;
     return FALSE;
 }
 
 static cairo_bool_t
 _pattern_supported (cairo_pattern_t *pattern)
@@ -2516,17 +2610,17 @@ static cairo_bool_t cairo_pdf_force_fall
  **/
 void
 _cairo_pdf_test_force_fallbacks (void)
 {
     cairo_pdf_force_fallbacks = TRUE;
 }
 
 static cairo_int_status_t
-_operation_supported (cairo_pdf_surface_t *surface,
+__cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
 		      cairo_operator_t op,
 		      cairo_pattern_t *pattern)
 {
     if (cairo_pdf_force_fallbacks)
 	return FALSE;
 
     if (! _pattern_supported (pattern))
 	return FALSE;
@@ -2535,48 +2629,48 @@ static cairo_int_status_t
      * but this should cover many common cases at least. */
     if (op == CAIRO_OPERATOR_OVER)
 	return TRUE;
 
     return FALSE;
 }
 
 static cairo_int_status_t
-_analyze_operation (cairo_pdf_surface_t *surface,
+_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
 		    cairo_operator_t op,
 		    cairo_pattern_t *pattern)
 {
-    if (_operation_supported (surface, op, pattern))
+    if (__cairo_pdf_surface_operation_supported (surface, op, pattern))
 	return CAIRO_STATUS_SUCCESS;
     else
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
 			  cairo_pattern_t	*source)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
+	return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
     /* XXX: It would be nice to be able to assert this condition
      * here. But, we actually allow one 'cheat' that is used when
      * painting the final image-based fallbacks. The final fallbacks
      * do have alpha which we support by blending with white. This is
      * possible only because there is nothing between the fallback
      * images and the paper, nor is anything painted above. */
     /*
-    assert (_operation_supported (op, source));
+    assert (__cairo_pdf_surface_operation_supported (op, source));
     */
 
-    status = emit_pattern (surface, source);
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     _cairo_output_stream_printf (surface->output,
 				 "0 0 %f %f re f\r\n",
 				 surface->width, surface->height);
 
     return _cairo_output_stream_get_status (surface->output);
@@ -2675,21 +2769,21 @@ static cairo_int_status_t
 			   double		 tolerance,
 			   cairo_antialias_t	 antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     pdf_path_info_t info;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
-
-    assert (_operation_supported (surface, op, source));
-
-    status = emit_pattern (surface, source);
+	return _cairo_pdf_surface_analyze_operation (surface, op, source);
+
+    assert (__cairo_pdf_surface_operation_supported (surface, op, source));
+
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     status = _cairo_pdf_surface_emit_stroke_style (surface,
 						   style);
     if (status)
 	return status;
 
@@ -2724,21 +2818,21 @@ static cairo_int_status_t
 			 cairo_antialias_t	 antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     const char *pdf_operator;
     cairo_status_t status;
     pdf_path_info_t info;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
-
-    assert (_operation_supported (surface, op, source));
-
-    status = emit_pattern (surface, source);
+	return _cairo_pdf_surface_analyze_operation (surface, op, source);
+
+    assert (__cairo_pdf_surface_operation_supported (surface, op, source));
+
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     info.output = surface->output;
     info.ctm_inverse = NULL;
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -2777,21 +2871,21 @@ static cairo_int_status_t
     cairo_pdf_surface_t *surface = abstract_surface;
     unsigned int current_subset_id = (unsigned int)-1;
     unsigned int font_id, subset_id, subset_glyph_index;
     cairo_bool_t diagonal;
     cairo_status_t status;
     int i;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
-
-    assert (_operation_supported (surface, op, source));
-
-    status = emit_pattern (surface, source);
+	return _cairo_pdf_surface_analyze_operation (surface, op, source);
+
+    assert (__cairo_pdf_surface_operation_supported (surface, op, source));
+
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     _cairo_output_stream_printf (surface->output,
 				 "BT\r\n");
 
     if (scaled_font->scale.xy == 0.0 &&
         scaled_font->scale.yx == 0.0)
@@ -2821,17 +2915,17 @@ static cairo_int_status_t
                                          glyphs[i].x,
                                          glyphs[i].y,
                                          subset_glyph_index);
 	    current_subset_id = subset_id;
         } else {
             _cairo_output_stream_printf (surface->output,
                                          "%f %f Td <%02x> Tj\r\n",
                                          (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
-                                         (glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy,
+                                         (glyphs[i].y - glyphs[i-1].y)/-scaled_font->scale.yy,
                                          subset_glyph_index);
         }
     }
 
     _cairo_output_stream_printf (surface->output,
 				 "ET\r\n");
 
     return _cairo_output_stream_get_status (surface->output);
--- a/gfx/cairo/cairo/src/cairo-polygon.c
+++ b/gfx/cairo/cairo/src/cairo-polygon.c
@@ -35,80 +35,92 @@
  */
 
 #include <stdlib.h>
 #include "cairoint.h"
 
 /* private functions */
 
 static cairo_status_t
-_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
+_cairo_polygon_grow (cairo_polygon_t *polygon);
 
 void
 _cairo_polygon_init (cairo_polygon_t *polygon)
 {
     polygon->num_edges = 0;
 
     polygon->edges_size = 0;
     polygon->edges = NULL;
 
-    polygon->has_current_point = 0;
+    polygon->has_current_point = FALSE;
 }
 
 void
 _cairo_polygon_fini (cairo_polygon_t *polygon)
 {
-    if (polygon->edges_size) {
+    if (polygon->edges && polygon->edges != polygon->edges_embedded)
 	free (polygon->edges);
-	polygon->edges = NULL;
-	polygon->edges_size = 0;
-	polygon->num_edges = 0;
-    }
 
-    polygon->has_current_point = 0;
+    polygon->edges = NULL;
+    polygon->edges_size = 0;
+    polygon->num_edges = 0;
+
+    polygon->has_current_point = FALSE;
 }
 
+/* make room for at least one more edge */
 static cairo_status_t
-_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
+_cairo_polygon_grow (cairo_polygon_t *polygon)
 {
     cairo_edge_t *new_edges;
     int old_size = polygon->edges_size;
-    int new_size = polygon->num_edges + additional;
+    int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]);
+    int new_size = 2 * MAX (old_size, 16);
 
-    if (new_size <= polygon->edges_size) {
+    /* we have a local buffer at polygon->edges_embedded.  try to fulfill the request
+     * from there. */
+    if (old_size < embedded_size) {
+	polygon->edges = polygon->edges_embedded;
+	polygon->edges_size = embedded_size;
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    polygon->edges_size = new_size;
-    new_edges = realloc (polygon->edges, polygon->edges_size * sizeof (cairo_edge_t));
+    assert (polygon->num_edges <= polygon->edges_size);
+
+    if (polygon->edges == polygon->edges_embedded) {
+	new_edges = malloc (new_size * sizeof (cairo_edge_t));
+	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));
+    }
 
     if (new_edges == NULL) {
-	polygon->edges_size = old_size;
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
     polygon->edges = new_edges;
+    polygon->edges_size = new_size;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
 {
     cairo_status_t status;
     cairo_edge_t *edge;
 
     /* drop horizontal edges */
     if (p1->y == p2->y) {
 	goto DONE;
     }
 
     if (polygon->num_edges >= polygon->edges_size) {
-	int additional = polygon->edges_size ? polygon->edges_size : 16;
-	status = _cairo_polygon_grow_by (polygon, additional);
+	status = _cairo_polygon_grow (polygon);
 	if (status) {
 	    return status;
 	}
     }
 
     edge = &polygon->edges[polygon->num_edges];
     if (p1->y < p2->y) {
 	edge->edge.p1 = *p1;
@@ -129,17 +141,17 @@ cairo_status_t
 }
 
 cairo_status_t
 _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
 {
     if (! polygon->has_current_point)
 	polygon->first_point = *point;
     polygon->current_point = *point;
-    polygon->has_current_point = 1;
+    polygon->has_current_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -160,13 +172,13 @@ cairo_status_t
 
     if (polygon->has_current_point) {
 	status = _cairo_polygon_add_edge (polygon,
 					  &polygon->current_point,
 					  &polygon->first_point);
 	if (status)
 	    return status;
 
-	polygon->has_current_point = 0;
+	polygon->has_current_point = FALSE;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-private.h
+++ b/gfx/cairo/cairo/src/cairo-private.h
@@ -39,14 +39,17 @@
 #include "cairo-gstate-private.h"
 #include "cairo-path-fixed-private.h"
 
 struct _cairo {
     unsigned int ref_count;
 
     cairo_status_t status;
 
-    cairo_path_fixed_t path;
+    cairo_user_data_array_t user_data;
 
     cairo_gstate_t *gstate;
+    cairo_gstate_t  gstate_tail[1];
+
+    cairo_path_fixed_t path[1];
 };
 
 #endif /* CAIRO_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-ps-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ps-surface.c
@@ -479,28 +479,28 @@ static cairo_status_t
 				 "/FontBBox [ 0 0 0 0 ] def\n"
 				 "/Encoding 256 array def\n"
 				 "0 1 255 { Encoding exch /.notdef put } for\n",
 				 font_subset->font_id,
 				 font_subset->subset_id);
 
     /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
 
-    for (i = 1; i < font_subset->num_glyphs; i++)
+    for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->final_stream,
 				     "Encoding %d /g%d put\n", i, i);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "/CharStrings %d dict dup begin\n"
 				 "/.notdef 0 def\n",
-				 font_subset->num_glyphs);
+				 font_subset->num_glyphs + 1);
 
-    for (i = 1; i < font_subset->num_glyphs; i++)
+    for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->final_stream,
-				     "/g%d %d def\n", i, i);
+				     "/g%d %d def\n", i, i + 1);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "end readonly def\n");
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "/sfnts [\n");
     begin = 0;
     end = 0;
@@ -704,18 +704,18 @@ static cairo_status_t
 				 "\t}\n"
 				 ">> definefont pop\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 
 static void
-_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				    void			*closure)
+_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				            void			*closure)
 {
     cairo_ps_surface_t *surface = closure;
     cairo_status_t status;
 
 #if CAIRO_HAS_FT_FONT
     status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
@@ -723,33 +723,44 @@ static void
 
     status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
 
     status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
+}
+
+static void
+_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                           void			      *closure)
+{
+    cairo_ps_surface_t *surface = closure;
+    cairo_status_t status;
 
     status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
 {
     cairo_status_t status;
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_font_subsets\n");
 
-    status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
-						 _cairo_ps_surface_emit_font_subset,
-						 surface);
+    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
+                                                          _cairo_ps_surface_emit_unscaled_font_subset,
+                                                          surface);
+    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
+                                                        _cairo_ps_surface_emit_scaled_font_subset,
+                                                        surface);
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
     surface->font_subsets = NULL;
 
     return status;
 }
 
 static void
 _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
@@ -793,17 +804,18 @@ static cairo_surface_t *
     if (surface->tmpfile == NULL)
 	goto CLEANUP_SURFACE;
 
     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
     status = _cairo_output_stream_get_status (surface->stream);
     if (status)
 	goto CLEANUP_TMPFILE;
 
-    surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT);
+    surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
+                                                               PS_SURFACE_MAX_GLYPHS_PER_FONT);
     if (! surface->font_subsets)
 	goto CLEANUP_OUTPUT_STREAM;
 
     surface->width  = width;
     surface->height = height;
     surface->max_width = width;
     surface->max_height = height;
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
@@ -863,17 +875,19 @@ cairo_ps_surface_create (const char		*fi
 {
     cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_filename (filename);
     status = _cairo_output_stream_get_status (stream);
     if (status) {
 	_cairo_error (status);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	return (status == CAIRO_STATUS_WRITE_ERROR) ?
+		(cairo_surface_t*) &_cairo_surface_nil_write_error :
+		(cairo_surface_t*) &_cairo_surface_nil;
     }
 
     return _cairo_ps_surface_create_for_stream_internal (stream,
 							 width_in_points,
 							 height_in_points);
 }
 
 /**
@@ -1318,19 +1332,47 @@ color_is_gray (cairo_color_t *color)
 
     return (fabs (color->red - color->green) < epsilon &&
 	    fabs (color->red - color->blue) < epsilon);
 }
 
 static cairo_bool_t
 surface_pattern_supported (const cairo_surface_pattern_t *pattern)
 {
-    if (pattern->surface->backend->acquire_source_image != NULL)
+    cairo_extend_t extend;
+
+    if (pattern->surface->backend->acquire_source_image == NULL)
+	return FALSE;
+
+    /* Does an ALPHA-only source surface even make sense? Maybe, but I
+     * don't think it's worth the extra code to support it. */
+
+/* XXX: Need to write this function here...
+    content = cairo_surface_get_content (pattern->surface);
+    if (content == CAIRO_CONTENT_ALPHA)
+	return FALSE;
+*/
+
+    /* Cast away the const, trusting get_extend not to muck with it.
+     * And I really wish I had a way to cast away just the const, and
+     * not potentially coerce this pointer to an incorrect type at the
+     * same time. :-(
+     */
+    extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base);
+    switch (extend) {
+    case CAIRO_EXTEND_NONE:
+    case CAIRO_EXTEND_REPEAT:
+    case CAIRO_EXTEND_REFLECT:
+    /* There's no point returning FALSE for EXTEND_PAD, as the image
+     * surface does not currently implement it either */
+    case CAIRO_EXTEND_PAD:
 	return TRUE;
+    }
 
+    ASSERT_NOT_REACHED;
     return FALSE;
 }
 
 static cairo_bool_t
 pattern_supported (const cairo_pattern_t *pattern)
 {
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 	return TRUE;
@@ -1357,17 +1399,17 @@ static cairo_bool_t cairo_ps_force_fallb
  **/
 void
 _cairo_ps_test_force_fallbacks (void)
 {
     cairo_ps_force_fallbacks = TRUE;
 }
 
 static cairo_int_status_t
-operation_supported (cairo_ps_surface_t *surface,
+_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
 		      cairo_operator_t op,
 		      const cairo_pattern_t *pattern)
 {
     if (cairo_ps_force_fallbacks)
 	return FALSE;
 
     if (! pattern_supported (pattern))
 	return FALSE;
@@ -1377,21 +1419,21 @@ operation_supported (cairo_ps_surface_t 
 
     if (_cairo_operator_always_translucent (op))
 	return FALSE;
 
     return _cairo_pattern_is_opaque (pattern);
 }
 
 static cairo_int_status_t
-_analyze_operation (cairo_ps_surface_t *surface,
+_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
 		    cairo_operator_t op,
 		    const cairo_pattern_t *pattern)
 {
-    if (operation_supported (surface, op, pattern))
+    if (_cairo_ps_surface_operation_supported (surface, op, pattern))
 	return CAIRO_STATUS_SUCCESS;
     else
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 /* The "standard" implementation limit for PostScript string sizes is
  * 65535 characters (see PostScript Language Reference, Appendix
  * B). We go one short of that because we sometimes need two
@@ -1511,19 +1553,18 @@ static cairo_output_stream_t *
 
     return &stream->base;
 }
 
 /* PS Output - this section handles output of the parts of the meta
  * surface we can render natively in PS. */
 
 static cairo_status_t
-emit_image (cairo_ps_surface_t    *surface,
+_cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 	    cairo_image_surface_t *image,
-	    cairo_matrix_t	  *matrix,
 	    const char		  *name)
 {
     cairo_status_t status;
     unsigned char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
     cairo_surface_t *opaque;
     cairo_image_surface_t *opaque_image;
     cairo_pattern_union_t pattern;
@@ -1622,63 +1663,61 @@ emit_image (cairo_ps_surface_t    *surfa
 				 "	/Height %d\n"
 				 "	/BitsPerComponent 8\n"
 				 "	/Decode [ 0 1 0 1 0 1 ]\n"
 				 "	/DataSource {\n"
 				 "	    %sData %sDataIndex get\n"
 				 "	    /%sDataIndex %sDataIndex 1 add def\n"
 				 "	    %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
 				 "	} /ASCII85Decode filter /LZWDecode filter\n"
-				 "	/ImageMatrix [ %f %f %f %f %f %f ]\n"
+				 "	/ImageMatrix [ 1 0 0 1 0 0 ]\n"
 				 "    >>\n"
 				 "    image\n"
 				 "} def\n",
 				 name,
 				 opaque_image->width,
 				 opaque_image->height,
-				 name, name, name, name, name, name, name,
-				 matrix->xx, matrix->yx,
-				 matrix->xy, matrix->yy,
-				 0.0, 0.0);
+				 name, name, name, name, name, name, name);
 
     status = CAIRO_STATUS_SUCCESS;
 
     free (compressed);
  bail2:
     free (rgb);
  bail1:
     if (opaque_image != image)
 	cairo_surface_destroy (opaque);
  bail0:
     return status;
 }
 
 static void
-emit_solid_pattern (cairo_ps_surface_t *surface,
+_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
 		    cairo_solid_pattern_t *pattern)
 {
     if (color_is_gray (&pattern->color))
 	_cairo_output_stream_printf (surface->stream,
 				     "%f G\n",
 				     pattern->color.red);
     else
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f %f R\n",
 				     pattern->color.red,
 				     pattern->color.green,
 				     pattern->color.blue);
 }
 
 static void
-emit_surface_pattern (cairo_ps_surface_t *surface,
+_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
 		      cairo_surface_pattern_t *pattern)
 {
     double bbox_width, bbox_height;
-    int xstep, ystep;
+    double xstep, ystep;
     cairo_matrix_t inverse = pattern->base.matrix;
+
     cairo_matrix_invert (&inverse);
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
 	_cairo_meta_surface_replay (pattern->surface, &surface->base);
 	bbox_width = surface->width;
 	bbox_height = surface->height;
 	xstep = surface->width;
@@ -1689,107 +1728,126 @@ emit_surface_pattern (cairo_ps_surface_t
 	void			*image_extra;
 	cairo_status_t		status;
 
 	status = _cairo_surface_acquire_source_image (pattern->surface,
 						      &image,
 						      &image_extra);
 	assert (status == CAIRO_STATUS_SUCCESS);
 
-	emit_image (surface, image, &pattern->base.matrix, "MyPattern");
+	_cairo_ps_surface_emit_image (surface, image, "MyPattern");
 
 	bbox_width = image->width;
 	bbox_height = image->height;
-	cairo_matrix_transform_distance (&inverse,
-					 &bbox_width, &bbox_height);
 
-	/* In PostScript, (as far as I can tell), all patterns are
-	 * repeating. So we support cairo's EXTEND_NONE semantics by
-	 * setting the repeat step size to the larger of the image size
-	 * and the extents of the destination surface. That way we
-	 * guarantee the pattern will not repeat.
-	 */
 	switch (pattern->base.extend) {
+	/* We implement EXTEND_PAD like EXTEND_NONE for now */
+	case CAIRO_EXTEND_PAD:
 	case CAIRO_EXTEND_NONE:
-	    xstep = MAX (image->width, surface->width);
-	    ystep = MAX (image->height, surface->height);
+	{
+	    /* In PS/PDF, (as far as I can tell), all patterns are
+	     * repeating. So we support cairo's EXTEND_NONE semantics
+	     * by setting the repeat step size to a size large enough
+	     * to guarantee that no more than a single occurrence will
+	     * be visible.
+	     *
+	     * First, map the surface extents into pattern space (since
+	     * xstep and ystep are in pattern space).  Then use an upper
+	     * bound on the length of the diagonal of the pattern image
+	     * and the surface as repeat size.  This guarantees to never
+	     * repeat visibly.
+	     */
+	    double x1 = 0.0, y1 = 0.0;
+	    double x2 = surface->width, y2 = surface->height;
+	    _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
+						  &x1, &y1, &x2, &y2,
+						  NULL);
+
+	    /* Rather than computing precise bounds of the union, just
+	     * add the surface extents unconditionally. We only
+	     * required an answer that's large enough, we don't really
+	     * care if it's not as tight as possible.*/
+	    xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
+				  image->width + image->height);
 	    break;
+	}
 	case CAIRO_EXTEND_REPEAT:
+	case CAIRO_EXTEND_REFLECT:
 	    xstep = image->width;
 	    ystep = image->height;
 	    break;
-	/* All the rest should have been analyzed away, so these cases
-	 * should be unreachable. */
-	case CAIRO_EXTEND_REFLECT:
-	case CAIRO_EXTEND_PAD:
+	/* All the rest (if any) should have been analyzed away, so these
+	 * cases should be unreachable. */
 	default:
 	    ASSERT_NOT_REACHED;
 	    xstep = 0;
 	    ystep = 0;
 	}
 
 	_cairo_surface_release_source_image (pattern->surface, image,
 					     image_extra);
     }
     _cairo_output_stream_printf (surface->stream,
 				 "<< /PatternType 1\n"
 				 "   /PaintType 1\n"
 				 "   /TilingType 1\n");
     _cairo_output_stream_printf (surface->stream,
-				 "   /BBox [0 0 %d %d]\n",
-				 (int) bbox_width, (int) bbox_height);
+				 "   /BBox [0 0 %f %f]\n",
+				 bbox_width, bbox_height);
     _cairo_output_stream_printf (surface->stream,
-				 "   /XStep %d /YStep %d\n",
+				 "   /XStep %f /YStep %f\n",
 				 xstep, ystep);
     _cairo_output_stream_printf (surface->stream,
 				 "   /PaintProc { MyPattern } bind\n"
 				 ">>\n");
     _cairo_output_stream_printf (surface->stream,
-				 "[ 1 0 0 1 %f %f ]\n",
+				 "[ %f %f %f %f %f %f ]\n",
+				 inverse.xx, inverse.yx,
+				 inverse.xy, inverse.yy,
 				 inverse.x0, inverse.y0);
     _cairo_output_stream_printf (surface->stream,
 				 "makepattern setpattern\n");
 }
 
 static void
-emit_linear_pattern (cairo_ps_surface_t *surface,
+_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
 		     cairo_linear_pattern_t *pattern)
 {
     /* XXX: NYI */
 }
 
 static void
-emit_radial_pattern (cairo_ps_surface_t *surface,
+_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
 		     cairo_radial_pattern_t *pattern)
 {
     /* XXX: NYI */
 }
 
 static void
-emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
+_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
 {
     /* FIXME: We should keep track of what pattern is currently set in
      * the postscript file and only emit code if we're setting a
      * different pattern. */
 
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
+	_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
 	break;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
-	emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
+	_cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
 	break;
 
     case CAIRO_PATTERN_TYPE_LINEAR:
-	emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	_cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
 	break;
 
     case CAIRO_PATTERN_TYPE_RADIAL:
-	emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+	_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
 	break;
     }
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_intersect_clip_path (void		   *abstract_surface,
 				cairo_path_fixed_t *path,
 				cairo_fill_rule_t   fill_rule,
@@ -1869,36 +1927,36 @@ static cairo_int_status_t
 			 cairo_operator_t	 op,
 			 cairo_pattern_t	*source)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_rectangle_int16_t extents, pattern_extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
+	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
     /* XXX: It would be nice to be able to assert this condition
      * here. But, we actually allow one 'cheat' that is used when
      * painting the final image-based fallbacks. The final fallbacks
      * do have alpha which we support by blending with white. This is
      * possible only because there is nothing between the fallback
      * images and the paper, nor is anything painted above. */
     /*
-    assert (_operation_supported (op, source));
+    assert (__cairo_ps_surface_operation_supported (op, source));
     */
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_paint\n");
 
     _cairo_surface_get_extents (&surface->base, &extents);
     _cairo_pattern_get_extents (source, &pattern_extents);
     _cairo_rectangle_intersect (&extents, &pattern_extents);
 
-    emit_pattern (surface, source);
+    _cairo_ps_surface_emit_pattern (surface, source);
 
     _cairo_output_stream_printf (stream, "%d %d M\n",
 				 extents.x, extents.y);
     _cairo_output_stream_printf (stream, "%d %d L\n",
 				 extents.x + extents.width,
 				 extents.y);
     _cairo_output_stream_printf (stream, "%d %d L\n",
 				 extents.x + extents.width,
@@ -1956,19 +2014,19 @@ static cairo_int_status_t
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_int_status_t status;
     double *dash = style->dash;
     int num_dashes = style->num_dashes;
     double dash_offset = style->dash_offset;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
+	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
-    assert (operation_supported (surface, op, source));
+    assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_stroke\n");
 
     /* PostScript has "special needs" when it comes to zero-length
      * dash segments with butt caps. It apparently (at least
      * according to ghostscript) draws hairlines for this
@@ -2027,17 +2085,17 @@ static cairo_int_status_t
 		 * we rotated a 0.0 value to the front of the list.
 		 * Set i to -2 so it will get incremented to 0. */
 		if (i == 2)
 		    i = -2;
 	    }
 	}
     }
 
-    emit_pattern (surface, source);
+    _cairo_ps_surface_emit_pattern (surface, source);
 
     _cairo_output_stream_printf (stream,
 				 "gsave\n");
     status = _cairo_ps_surface_emit_path (surface, stream, path,
 					  style->line_cap);
 
     /*
      * Switch to user space to set line parameters
@@ -2087,24 +2145,24 @@ static cairo_int_status_t
 		 cairo_antialias_t	 antialias)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_int_status_t status;
     const char *ps_operator;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
+	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
-    assert (operation_supported (surface, op, source));
+    assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_fill\n");
 
-    emit_pattern (surface, source);
+    _cairo_ps_surface_emit_pattern (surface, source);
 
     /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
     status = _cairo_ps_surface_emit_path (surface, stream, path,
 					  CAIRO_LINE_CAP_ROUND);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
 	ps_operator = "F";
@@ -2145,29 +2203,29 @@ static cairo_int_status_t
     unsigned int font_id;
     cairo_ps_glyph_id_t *glyph_ids;
     cairo_status_t status;
     unsigned int num_glyphs_unsigned, i, j, last, end;
     cairo_bool_t vertical, horizontal;
     cairo_output_stream_t *word_wrap;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return _analyze_operation (surface, op, source);
+	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
-    assert (operation_supported (surface, op, source));
+    assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_show_glyphs\n");
 
     if (num_glyphs <= 0)
         return CAIRO_STATUS_SUCCESS;
 
     num_glyphs_unsigned = num_glyphs;
 
-    emit_pattern (surface, source);
+    _cairo_ps_surface_emit_pattern (surface, source);
     glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
     if (glyph_ids == NULL)
         return CAIRO_STATUS_NO_MEMORY;
 
     for (i = 0; i < num_glyphs_unsigned; i++) {
         status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
                                                        scaled_font, glyphs[i].index,
                                                        &font_id,
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
@@ -1,11 +1,12 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Calum Robinson
+ * Copyright (C) 2006,2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -26,41 +27,48 @@
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Calum Robinson
  *
  * Contributor(s):
  *    Calum Robinson <calumr@mac.com>
+ *    Vladimir Vukicevic <vladimir@mozilla.com>
  */
 
 #ifndef CAIRO_QUARTZ_PRIVATE_H
 #define CAIRO_QUARTZ_PRIVATE_H
 
 #include <cairoint.h>
+
+#ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include <cairo-quartz.h>
 
 typedef struct cairo_quartz_surface {
     cairo_surface_t base;
 
-    CGContextRef context;
+    void *imageData;
 
-    cairo_bool_t y_grows_down;
+    CGContextRef cgContext;
+    CGAffineTransform cgContextBaseCTM;
 
     cairo_rectangle_int16_t extents;
 
-    pixman_region16_t *clip_region;
+    /* These are stored while drawing operations are in place, set up
+     * by quartz_setup_source() and quartz_finish_source()
+     */
+    CGAffineTransform imageTransform;
+    CGImageRef sourceImage;
+    CGShadingRef sourceShading;
+    CGPatternRef sourcePattern;
 } cairo_quartz_surface_t;
+#endif /* CAIRO_HAS_QUARTZ_SURFACE */
 
-cairo_bool_t
-_cairo_surface_is_quartz (cairo_surface_t *surface);
-
-cairo_bool_t
-_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont);
-
+#if CAIRO_HAS_ATSUI_FONT
 ATSUStyle
 _cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont);
 
 ATSUFontID
 _cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont);
+#endif /* CAIRO_HAS_ATSUI_FONT */
 
 #endif /* CAIRO_QUARTZ_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -1,11 +1,12 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2004 Calum Robinson
+ * Copyright  2006, 2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -22,244 +23,1754 @@
  * http://www.mozilla.org/MPL/
  *
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
- * The Initial Developer of the Original Code is Calum Robinson
+ * The Initial Developer of the Original Code is Mozilla Corporation.
  *
  * Contributor(s):
- *    Calum Robinson <calumr@mac.com>
+ *	Vladimir Vukicevic <vladimir@mozilla.com>
  */
 
+#include <Carbon/Carbon.h>
+
 #include "cairoint.h"
-#include "cairo-private.h"
+
 #include "cairo-quartz-private.h"
 
+#undef QUARTZ_DEBUG
+
+#ifdef QUARTZ_DEBUG
+#define ND(_x)	fprintf _x
+#else
+#define ND(_x)	do {} while(0)
+#endif
+
+/* This method is private, but it exists.  Its params are are exposed
+ * as args to the NS* method, but not as CG.
+ */
+enum PrivateCGCompositeMode {
+    kPrivateCGCompositeClear		= 0,
+    kPrivateCGCompositeCopy		= 1,
+    kPrivateCGCompositeSourceOver	= 2,
+    kPrivateCGCompositeSourceIn		= 3,
+    kPrivateCGCompositeSourceOut	= 4,
+    kPrivateCGCompositeSourceAtop	= 5,
+    kPrivateCGCompositeDestinationOver	= 6,
+    kPrivateCGCompositeDestinationIn	= 7,
+    kPrivateCGCompositeDestinationOut	= 8,
+    kPrivateCGCompositeDestinationAtop	= 9,
+    kPrivateCGCompositeXOR		= 10,
+    kPrivateCGCompositePlusDarker	= 11, // (max (0, (1-d) + (1-s)))
+    kPrivateCGCompositePlusLighter	= 12, // (min (1, s + d))
+};
+typedef enum PrivateCGCompositeMode PrivateCGCompositeMode;
+CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
+CG_EXTERN void CGContextResetCTM (CGContextRef);
+CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform);
+CG_EXTERN void CGContextResetClip (CGContextRef);
+CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
+
+/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
+ * has all the stuff we care about, just some of it isn't exported in the SDK.
+ */ 
+#ifndef kCGBitmapByteOrder32Host
+#define USE_10_3_WORKAROUNDS
+#define kCGBitmapAlphaInfoMask 0x1F
+#define kCGBitmapByteOrderMask 0x7000
+#define kCGBitmapByteOrder32Host 0
+
+typedef uint32_t CGBitmapInfo;
+
+/* public in 10.4, present in 10.3.9 */
+CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
+CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
+#endif
+
+
+/*
+ * Utility functions
+ */
+
+static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest);
+static void quartz_image_to_png (CGImageRef, char *dest);
+
+/*
+ * Cairo path -> Quartz path conversion helpers
+ */
+
+/* cairo path -> mutable path */
+static cairo_status_t
+_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
+{
+    CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
+		       _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
+{
+    CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
+			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
+{
+    CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
+			   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+			   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+			   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_close_path (void *closure)
+{
+    CGPathCloseSubpath ((CGMutablePathRef) closure);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* cairo path -> execute in context */
+static cairo_status_t
+_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
+{
+    //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
+    CGContextMoveToPoint ((CGContextRef) closure,
+			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
+{
+    //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
+    if (CGContextIsPathEmpty ((CGContextRef) closure))
+	CGContextMoveToPoint ((CGContextRef) closure,
+			      _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    else
+	CGContextAddLineToPoint ((CGContextRef) closure,
+				 _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
+{
+    //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n",
+    //		   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+    //		   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+    //		   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
+
+    CGContextAddCurveToPoint ((CGContextRef) closure,
+			      _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+			      _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+			      _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_close_path (void *closure)
+{
+    //ND((stderr, "closepath\n"));
+    CGContextClosePath ((CGContextRef) closure);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_quartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
+					  CGMutablePathRef cgPath)
+{
+    return _cairo_path_fixed_interpret (path,
+					CAIRO_DIRECTION_FORWARD,
+					_cairo_path_to_quartz_path_move_to,
+					_cairo_path_to_quartz_path_line_to,
+					_cairo_path_to_quartz_path_curve_to,
+					_cairo_path_to_quartz_path_close_path,
+					cgPath);
+}
+
 static cairo_status_t
-_cairo_quartz_surface_finish(void *abstract_surface)
+_cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
+					     CGContextRef cgc)
+{
+    return _cairo_path_fixed_interpret (path,
+					CAIRO_DIRECTION_FORWARD,
+					_cairo_path_to_quartz_context_move_to,
+					_cairo_path_to_quartz_context_line_to,
+					_cairo_path_to_quartz_context_curve_to,
+					_cairo_path_to_quartz_context_close_path,
+					cgc);
+}
+
+/*
+ * Misc helpers/callbacks
+ */
+
+static PrivateCGCompositeMode
+_cairo_quartz_cairo_operator_to_quartz (cairo_operator_t op)
+{
+    switch (op) {
+	case CAIRO_OPERATOR_CLEAR:
+	    return kPrivateCGCompositeClear;
+	case CAIRO_OPERATOR_SOURCE:
+	    return kPrivateCGCompositeCopy;
+	case CAIRO_OPERATOR_OVER:
+	    return kPrivateCGCompositeSourceOver;
+	case CAIRO_OPERATOR_IN:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeSourceIn;
+	case CAIRO_OPERATOR_OUT:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeSourceOut;
+	case CAIRO_OPERATOR_ATOP:
+	    return kPrivateCGCompositeSourceAtop;
+
+	case CAIRO_OPERATOR_DEST:
+	    /* XXX this is handled specially (noop)! */
+	    return kPrivateCGCompositeCopy;
+	case CAIRO_OPERATOR_DEST_OVER:
+	    return kPrivateCGCompositeDestinationOver;
+	case CAIRO_OPERATOR_DEST_IN:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeDestinationIn;
+	case CAIRO_OPERATOR_DEST_OUT:
+	    return kPrivateCGCompositeDestinationOut;
+	case CAIRO_OPERATOR_DEST_ATOP:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeDestinationAtop;
+
+	case CAIRO_OPERATOR_XOR:
+	    return kPrivateCGCompositeXOR; /* This will generate strange results */
+	case CAIRO_OPERATOR_ADD:
+	    return kPrivateCGCompositePlusLighter;
+	case CAIRO_OPERATOR_SATURATE:
+	    /* XXX This doesn't match image output for SATURATE; there's no equivalent */
+	    return kPrivateCGCompositePlusDarker;  /* ??? */
+    }
+
+
+    return kPrivateCGCompositeCopy;
+}
+
+static CGLineCap
+_cairo_quartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap)
+{
+    switch (ccap) {
+	case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break;
+	case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break;
+	case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break;
+    }
+
+    return kCGLineCapButt;
+}
+
+static CGLineJoin
+_cairo_quartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin)
+{
+    switch (cjoin) {
+	case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break;
+	case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break;
+	case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break;
+    }
+
+    return kCGLineJoinMiter;
+}
+
+static void
+_cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
+				       CGAffineTransform *dst)
+{
+    dst->a = src->xx;
+    dst->b = src->xy;
+    dst->c = src->yx;
+    dst->d = src->yy;
+    dst->tx = src->x0;
+    dst->ty = src->y0;
+}
+
+/*
+ * Source -> Quartz setup and finish functions
+ */
+
+static void
+ComputeGradientValue (void *info, const float *in, float *out)
+{
+    float fdist = *in; /* 0.0 .. 1.0 */
+    cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
+    cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
+    unsigned int i;
+
+    for (i = 0; i < grad->n_stops; i++) {
+	if (grad->stops[i].x > fdist_fix)
+	    break;
+    }
+
+    if (i == 0 || i == grad->n_stops) {
+	if (i == grad->n_stops)
+	    --i;
+	out[0] = grad->stops[i].color.red / 65535.;
+	out[1] = grad->stops[i].color.green / 65535.;
+	out[2] = grad->stops[i].color.blue / 65535.;
+	out[3] = grad->stops[i].color.alpha / 65535.;
+    } else {
+	float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
+	float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
+	float bp = (fdist - ax)/bx;
+	float ap = 1.0 - bp;
+
+	out[0] =
+	    (grad->stops[i-1].color.red / 65535.) * ap +
+	    (grad->stops[i].color.red / 65535.) * bp;
+	out[1] =
+	    (grad->stops[i-1].color.green / 65535.) * ap +
+	    (grad->stops[i].color.green / 65535.) * bp;
+	out[2] =
+	    (grad->stops[i-1].color.blue / 65535.) * ap +
+	    (grad->stops[i].color.blue / 65535.) * bp;
+	out[3] =
+	    (grad->stops[i-1].color.alpha / 65535.) * ap +
+	    (grad->stops[i].color.alpha / 65535.) * bp;
+    }
+}
+
+static CGFunctionRef
+CreateGradientFunction (cairo_gradient_pattern_t *gpat)
+{
+    static const float input_value_range[2] = { 0.f, 1.f };
+    static const float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f };
+    static const CGFunctionCallbacks callbacks = {
+	0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
+    };
+
+    return CGFunctionCreate (gpat,
+			     1,
+			     input_value_range,
+			     4,
+			     output_value_ranges,
+			     &callbacks);
+}
+
+static CGShadingRef
+_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
+{
+    cairo_matrix_t mat;
+    double x0, y0;
+
+    if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
+	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return NULL;
+
+    /* We can only do this if we have an identity pattern matrix;
+     * otherwise fall back through to the generic pattern case.
+     * XXXperf we could optimize this by creating a pattern with the shading;
+     * but we'd need to know the extents to do that.
+     * ... but we don't care; we can use the surface extents for it
+     * XXXtodo - implement gradients with non-identity pattern matrices
+     */
+    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;
+
+    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();
+
+	start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
+			     _cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
+	end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0,
+			   _cairo_fixed_to_double (lpat->gradient.p2.y) - y0);
+
+	cairo_pattern_reference (abspat);
+	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
+	shading = CGShadingCreateAxial (rgb,
+					start, end,
+					gradFunc,
+					true, true);
+	CGColorSpaceRelease(rgb);
+	CGFunctionRelease(gradFunc);
+
+	return shading;
+    }
+
+    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();
+
+	start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c1.x) - x0,
+			     _cairo_fixed_to_double (rpat->gradient.c1.y) - y0);
+	end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c2.x) - x0,
+			   _cairo_fixed_to_double (rpat->gradient.c2.y) - y0);
+
+	cairo_pattern_reference (abspat);
+	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
+	shading = CGShadingCreateRadial (rgb,
+					 start,
+					 _cairo_fixed_to_double (rpat->gradient.c1.radius),
+					 end,
+					 _cairo_fixed_to_double (rpat->gradient.c2.radius),
+					 gradFunc,
+					 true, true);
+	CGColorSpaceRelease(rgb);
+	CGFunctionRelease(gradFunc);
+
+	return shading;
+    }
+
+    /* Shouldn't be reached */
+    ASSERT_NOT_REACHED;
+    return NULL;
+}
+
+
+/* Generic cairo_pattern -> CGPattern function */
+static void
+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 = NULL;
+
+    cairo_bool_t flip = FALSE;
+
+    CGImageRef img;
+
+    if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
+	/* This sucks; we should really store a dummy quartz surface
+	 * for passing in here
+	 * XXXtodo store a dummy quartz surface somewhere for handing off to clone_similar
+	 * XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
+	 * just create the CGImage directly!
+	 */
+
+	cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+	cairo_surface_t *new_surf = NULL;
+	cairo_rectangle_int16_t rect;
+
+	_cairo_surface_get_extents (pat_surf, &rect);
+
+	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
+				      rect.width, rect.height, &new_surf);
+
+	cairo_surface_destroy(dummy);
+
+	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;
+
+	/* XXXtodo WHY does this need to be flipped?  Writing this stuff
+	 * to disk shows that in both this path and the path above the source image
+	 * has an identical orientation, and the destination context at all times has a Y
+	 * flip.  So why do we need to flip in this case?
+	 */
+	flip = TRUE;
+    }
+
+    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+
+    if (!img) {
+	// ... give up.
+	ND((stderr, "CGBitmapContextCreateImage failed\n"));
+	cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
+	return;
+    }
+
+    if (flip) {
+	CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
+	CGContextScaleCTM (context, 1, -1);
+    }
+
+    CGRect imageBounds;
+    imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
+    imageBounds.origin.x = 0;
+    imageBounds.origin.y = 0;
+
+    CGContextDrawImage (context, imageBounds, img);
+
+    CGImageRelease (img);
+
+    cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
+}
+
+/* Borrowed from cairo-meta-surface */
+static cairo_status_t
+_init_pattern_with_snapshot (cairo_pattern_t *pattern,
+			     const cairo_pattern_t *other)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
+    _cairo_pattern_init_copy (pattern, other);
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern =
+	    (cairo_surface_pattern_t *) pattern;
+	cairo_surface_t *surface = surface_pattern->surface;
+
+	surface_pattern->surface = _cairo_surface_snapshot (surface);
+
+	cairo_surface_destroy (surface);
+
+	if (surface_pattern->surface->status)
+	    return surface_pattern->surface->status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static CGPatternRef
+_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest,
+							  cairo_pattern_t *abspat)
+{
+    cairo_surface_pattern_t *spat;
+    cairo_surface_t *pat_surf;
+    cairo_rectangle_int16_t extents;
+
+    CGRect pbounds;
+    CGAffineTransform ptransform, stransform;
+    CGPatternCallbacks cb = { 0,
+			      SurfacePatternDrawFunc,
+			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
+    CGPatternRef cgpat;
+    float rw, rh;
+
+    cairo_pattern_union_t *snap_pattern = NULL;
+    cairo_pattern_t *target_pattern = abspat;
+
+    cairo_matrix_t m;
+    /* SURFACE is the only type we'll handle here */
+    if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
+	return NULL;
+
+    spat = (cairo_surface_pattern_t *) abspat;
+    pat_surf = spat->surface;
+
+    _cairo_surface_get_extents (pat_surf, &extents);
+    pbounds.origin.x = 0;
+    pbounds.origin.y = 0;
+    pbounds.size.width = extents.width;
+    pbounds.size.height = extents.height;
+
+    m = spat->base.matrix;
+    cairo_matrix_invert(&m);
+    _cairo_quartz_cairo_matrix_to_quartz (&m, &stransform);
+
+    /* The pattern matrix is relative to the bottom left, again; the
+     * incoming cairo pattern matrix is relative to the upper left.
+     * So we take the pattern matrix and the original context matrix,
+     * which gives us the correct base translation/y flip.
+     */
+    ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM);
+
+#ifdef QUARTZ_DEBUG
+    ND((stderr, "  pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height));
+    ND((stderr, "  pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d));
+    CGAffineTransform xform = CGContextGetCTM(dest->cgContext);
+    ND((stderr, "  context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
+#endif
+
+    // kjs seems to indicate this should work (setting to 0,0 to avoid
+    // tiling); however, the pattern CTM scaling ends up being NaN in
+    // the pattern draw function if either rw or rh are 0.
+    // XXXtodo get pattern drawing working with extend options
+    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
+#if 0
+    if (spat->base.extend == CAIRO_EXTEND_NONE) {
+	/* XXX wasteful; this will keep drawing the pattern in the
+	 * original location.  We need to set up the clip region
+	 * instead to do this right.
+	 */
+	rw = 0;
+	rh = 0;
+    } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
+	rw = extents.width;
+	rh = extents.height;
+    } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
+	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
+	 * and then tiling that
+	 */
+	rw = extents.width;
+	rh = extents.height;
+    } else {
+	/* CAIRO_EXTEND_PAD */
+	/* XXX broken. */
+	rw = 0;
+	rh = 0;
+    }
+#else
+    rw = extents.width;
+    rh = extents.height;
+#endif
+
+    /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
+       other block if it doesn't fafect performance */
+    if (1 /* context is for printing */) {
+	snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
+	target_pattern = (cairo_pattern_t*) snap_pattern;
+	_init_pattern_with_snapshot (target_pattern, abspat);
+    } else {
+	cairo_pattern_reference (abspat);
+	target_pattern = abspat;
+    }
+
+    cgpat = CGPatternCreate (target_pattern,
+			     pbounds,
+			     ptransform,
+			     rw, rh,
+			     kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
+			     TRUE,
+			     &cb);
+    return cgpat;
+}
+
+typedef enum {
+    DO_SOLID,
+    DO_SHADING,
+    DO_PATTERN,
+    DO_UNSUPPORTED
+} cairo_quartz_action_t;
+
+static cairo_quartz_action_t
+_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
+			     cairo_pattern_t *source)
+{
+    assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+
+	CGContextSetRGBStrokeColor (surface->cgContext,
+				    solid->color.red,
+				    solid->color.green,
+				    solid->color.blue,
+				    solid->color.alpha);
+	CGContextSetRGBFillColor (surface->cgContext,
+				  solid->color.red,
+				  solid->color.green,
+				  solid->color.blue,
+				  solid->color.alpha);
+
+	return DO_SOLID;
+    } 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)
+	    return DO_UNSUPPORTED;
+
+	surface->sourceShading = shading;
+
+	return DO_SHADING;
+    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
+	if (!pattern)
+	    return DO_UNSUPPORTED;
 
-    if (surface->clip_region)
-      pixman_region_destroy (surface->clip_region);
+	float patternAlpha = 1.0f;
+
+	// Save before we change the pattern, colorspace, etc. so that
+	// we can restore and make sure that quartz releases our
+	// pattern (which may be stack allocated)
+	CGContextSaveGState(surface->cgContext);
+
+	CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+	CGContextSetFillColorSpace (surface->cgContext, patternSpace);
+	CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
+	CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
+	CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha);
+	CGColorSpaceRelease (patternSpace);
+
+	/* Quartz likes to munge the pattern phase (as yet unexplained
+	 * why); force it to 0,0 as we've already baked in the correct
+	 * pattern translation into the pattern matrix
+	 */
+	CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0));
+
+	surface->sourcePattern = pattern;
+
+	return DO_PATTERN;
+    } else {
+	return DO_UNSUPPORTED;
+    }
+
+    ASSERT_NOT_REACHED;
+}
+
+static void
+_cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
+				cairo_pattern_t *source)
+{
+    if (surface->sourceImage) {
+	// nothing to do; we don't use sourceImage yet
+    }
+
+    if (surface->sourceShading) {
+	CGShadingRelease(surface->sourceShading);
+	surface->sourceShading = NULL;
+    }
+
+    if (surface->sourcePattern) {
+	CGPatternRelease(surface->sourcePattern);
+	// To tear down the pattern and colorspace
+	CGContextRestoreGState(surface->cgContext);
+
+	surface->sourcePattern = NULL;
+    }
+}
+
+/*
+ * get source/dest image implementation
+ */
+
+static void
+ImageDataReleaseFunc(void *info, const void *data, size_t size)
+{
+    if (data != NULL) {
+	free((void *) data);
+    }
+}
+
+/* Read the image from the surface's front buffer */
+static cairo_int_status_t
+_cairo_quartz_get_image (cairo_quartz_surface_t *surface,
+			  cairo_image_surface_t **image_out,
+			  unsigned char **data_out)
+{
+    unsigned char *imageData;
+    cairo_image_surface_t *isurf;
+
+    if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) {
+	unsigned int stride;
+	unsigned int bitinfo;
+	unsigned int bpc, bpp;
+	CGColorSpaceRef colorspace;
+	unsigned int color_comps;
+
+	imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
+#ifdef USE_10_3_WORKAROUNDS
+	bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
+#else