b=838960, ugprade cairo to 1.5.x; and b=377336, printing page from win32 results in hung app, r=stuart
authorvladimir@pobox.com
Thu, 20 Sep 2007 12:24:47 -0700
changeset 6154 5036a2b3fc8afdaeed56b8baa49b2e253dff7385
parent 6153 a45257bb334df0f0cec991b01bc55241dddfe41c
child 6155 57e8e87929722e826d11526ac904d9af6bc2cfeb
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstuart
bugs838960, 377336
milestone1.9a8pre
b=838960, ugprade cairo to 1.5.x; and b=377336, printing page from win32 results in hung app, r=stuart
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface-private.h
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-atsui-font.c
gfx/cairo/cairo/src/cairo-cff-subset.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-directfb-surface.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-malloc-private.h
gfx/cairo/cairo/src/cairo-meta-surface-private.h
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-mutex-type-private.h
gfx/cairo/cairo/src/cairo-os2-private.h
gfx/cairo/cairo/src/cairo-paginated-private.h
gfx/cairo/cairo/src/cairo-paginated-surface.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-pattern.c
gfx/cairo/cairo/src/cairo-pdf-surface-private.h
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-pen.c
gfx/cairo/cairo/src/cairo-platform.h
gfx/cairo/cairo/src/cairo-png.c
gfx/cairo/cairo/src/cairo-ps-surface-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-region-private.h
gfx/cairo/cairo/src/cairo-region.c
gfx/cairo/cairo/src/cairo-rename.h
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface-private.h
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-win32.h
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xlib-display.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-xlib-xrender-private.h
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/filterpublic.awk
gfx/cairo/clone-similar-fallback.patch
gfx/cairo/libpixman/src/Makefile.in
gfx/cairo/libpixman/src/pixman-compose.c
gfx/cairo/libpixman/src/pixman-compute-region.c
gfx/cairo/libpixman/src/pixman-edge-imp.h
gfx/cairo/libpixman/src/pixman-edge.c
gfx/cairo/libpixman/src/pixman-image.c
gfx/cairo/libpixman/src/pixman-mmx.c
gfx/cairo/libpixman/src/pixman-pict.c
gfx/cairo/libpixman/src/pixman-private.h
gfx/cairo/libpixman/src/pixman-region.c
gfx/cairo/libpixman/src/pixman-timer.c
gfx/cairo/libpixman/src/pixman-trap.c
gfx/cairo/libpixman/src/pixman-utils.c
gfx/cairo/libpixman/src/pixman.h
gfx/cairo/scaled-font-create-deadlock.patch
gfx/cairo/win32-no-printer-bitblt.patch
gfx/cairo/win32-scaled-font-size.patch
gfx/thebes/src/Makefile.in
toolkit/library/Makefile.in
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,49 +2,26 @@ 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.5.x - c0a7d33ac6c81dd74ee2a9daaa3749a346ef4897)
-  pixman (0.9.3 - 0c80a0cd84f30616563cef5910df9deb4f8ed687)
+  cairo (1.5.x - d8b0de01d67cdf73d8266a73f54ba1ac42fee3c9)
+  pixman (0.9.x - 3be35594c99b7abd2af43b66349ca53bfa1462d6)
   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 obviously not be defined).
-
 Some specific things:
 
 max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
 
-win32-scaled-font-size.patch: Add cairo_win32_font_face_create_for_logfontw_hfont,
-allow win32 scaled_fonts to rescale themselves properly to the required CTM
-and only use the font_face's hfont if we're sure it's appropriate
-
 win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
 
-win32-no-printer-bitblt.patch: If we need to BitBlt from a DC (to do
-fallback), only bother trying if the IS_DISPLAY flag is set -- many
-printers lie about their support for BitBlt, and we end up getting
-black instead of what we want.
-
 nonfatal-assertions.patch: Make assertions non-fatal
 
-clone-similar-fallback.patch: Implement fallback for clone_similar.
-
-scaled-font-create-deadlock.patch: the "poor man's mutex" that is provided
-for CAIRO_NO_MUTEX will deadlock if a recursive mutex lock occurs.
-It's also just a bunch of useless assignments for applications that makes
-all cairo calls from a single thread.  An example of where a deadlock occurs
-is the cairo_scaled_font_destroy() call from win32_scaled_font_create(),
-which is a bug, but it illustrates the dangers of that "poor man's mutex".
-The patch makes all mutex operations do nothing under CAIRO_NO_MUTEX and
-it fixes the bug in win32_scaled_font_create().
-See  https://bugzilla.mozilla.org/show_bug.cgi?id=378716
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -118,17 +118,18 @@ CSRCS   = \
         cairo-wideint.c \
         $(NULL)
 
 EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
 
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 CSRCS   += cairo-win32-font.c \
-           cairo-win32-surface.c
+           cairo-win32-surface.c \
+	   cairo-win32-printing-surface.c
 EXPORTS += cairo-win32.h
 CSRCS   += cairo-base85-stream.c \
            cairo-pdf-surface.c \
 	   cairo-type1-fallback.c \
 	   cairo-truetype-subset.c \
 	   cairo-cff-subset.c
 EXPORTS += cairo-pdf.h
 endif
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -1,10 +1,9 @@
-/* $Id: cairo-analysis-surface-private.h,v 1.12 2007/08/09 18:54:18 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
  * notice, a recipient may use your version of this file under either
@@ -45,11 +44,14 @@ cairo_private cairo_surface_t *
 
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *surface);
 
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_unsupported (cairo_surface_t *unsupported);
 
 cairo_private cairo_bool_t
+_cairo_analysis_surface_has_supported (cairo_surface_t *unsupported);
+
+cairo_private cairo_bool_t
 _cairo_analysis_surface_has_unsupported (cairo_surface_t *unsupported);
 
 #endif /* CAIRO_ANALYSIS_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -1,10 +1,11 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2007 Adrian Johnson
  *
  * 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.
@@ -25,193 +26,523 @@
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Keith Packard
  *
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
+ *      Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
 
 #include "cairo-analysis-surface-private.h"
 #include "cairo-paginated-private.h"
+#include "cairo-region-private.h"
+#include "cairo-meta-surface-private.h"
 
 typedef struct {
     cairo_surface_t base;
     int width;
     int height;
 
     cairo_surface_t	*target;
 
-    cairo_bool_t fallback;
+    cairo_bool_t has_supported;
+    cairo_bool_t has_unsupported;
+
+    cairo_region_t supported_region;
+    cairo_region_t fallback_region;
+    cairo_rectangle_int_t current_clip;
+
 } cairo_analysis_surface_t;
 
 static cairo_int_status_t
+_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
+						      cairo_pattern_t	       *pattern)
+{
+    cairo_surface_pattern_t *surface_pattern;
+    cairo_surface_t *meta_surface;
+    cairo_surface_t *analysis;
+    cairo_status_t status;
+
+    assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
+    surface_pattern = (cairo_surface_pattern_t *) pattern;
+    assert (_cairo_surface_is_meta (surface_pattern->surface));
+
+    meta_surface = surface_pattern->surface;
+    analysis = _cairo_analysis_surface_create (surface->target,
+					       surface->width, surface->height);
+    if (analysis == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis);
+    if (status == CAIRO_STATUS_SUCCESS)
+	    status = analysis->status;
+    cairo_surface_destroy (analysis);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_analysis_surface_add_operation  (cairo_analysis_surface_t *surface,
+					cairo_rectangle_int_t    *rect,
+					cairo_int_status_t        backend_status)
+{
+    cairo_int_status_t status;
+
+    if (rect->width == 0 || rect->height == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* If the operation is completely enclosed within the fallback
+     * region there is no benefit in emitting a native operation as
+     * the fallback image will be painted on top.
+     */
+    if (_cairo_region_contains_rectangle (&surface->fallback_region, rect) == PIXMAN_REGION_IN)
+	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+
+    if (backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) {
+	/* A status of CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY indicates
+	 * that the backend only supports this operation if the
+	 * transparency removed. If the extents of this operation does
+	 * not intersect any other native operation, the operation is
+	 * natively supported and the backend will blend the
+	 * transparency into the white background.
+	 */
+	if (_cairo_region_contains_rectangle (&surface->supported_region, rect) == PIXMAN_REGION_OUT)
+	    backend_status = CAIRO_STATUS_SUCCESS;
+    }
+
+    if (backend_status == CAIRO_STATUS_SUCCESS) {
+	/* Add the operation to the supported region. Operations in
+	 * this region will be emitted as native operations.
+	 */
+	surface->has_supported = TRUE;
+	status = _cairo_region_union_rect (&surface->supported_region,
+					   &surface->supported_region,
+					   rect);
+	return status;
+    }
+
+    /* Add the operation to the unsupported region. This region will
+     * be painted as an image after all native operations have been
+     * emitted.
+     */
+    surface->has_unsupported = TRUE;
+    status = _cairo_region_union_rect (&surface->fallback_region,
+				       &surface->fallback_region,
+				       rect);
+
+    /* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate
+     * unsupported operations to the meta surface as using
+     * CAIRO_INT_STATUS_UNSUPPORTED would cause cairo-surface to
+     * invoke the cairo-surface-fallback path then return
+     * CAIRO_STATUS_SUCCESS.
+     */
+    if (status == CAIRO_STATUS_SUCCESS)
+	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+    else
+	return status;
+}
+
+static cairo_status_t
+_cairo_analysis_surface_finish (void *abstract_surface)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    _cairo_region_fini (&surface->supported_region);
+    _cairo_region_fini (&surface->fallback_region);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_analysis_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_analysis_surface_t *surface = abstract_surface;
+    double                    x1, y1, x2, y2;
+    cairo_rectangle_int_t   extent;
+    cairo_status_t	      status;
+
+    if (path == NULL) {
+	surface->current_clip.x = 0;
+	surface->current_clip.y = 0;
+	surface->current_clip.width = surface->width;
+	surface->current_clip.height = surface->height;
+	status = CAIRO_STATUS_SUCCESS;
+    } else {
+	status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
+	if (status)
+	    return status;
+
+	extent.x = floor (x1);
+	extent.y = floor (y1);
+	extent.width = ceil (x2) - extent.x;
+	extent.height = ceil (y2) - extent.y;
+
+	_cairo_rectangle_intersect (&surface->current_clip, &extent);
+    }
+
+    return status;
+}
+
+static cairo_int_status_t
 _cairo_analysis_surface_get_extents (void	 		*abstract_surface,
 				     cairo_rectangle_int_t	*rectangle)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
 
     return _cairo_surface_get_extents (surface->target, rectangle);
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_paint (void			*abstract_surface,
 			      cairo_operator_t		op,
 			      cairo_pattern_t		*source)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status;
+    cairo_status_t	     status, backend_status;
+    cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->paint)
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
-	status = (*surface->target->backend->paint) (surface->target, op,
-						     source);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	surface->fallback = TRUE;
-	status = CAIRO_STATUS_SUCCESS;
+	backend_status = (*surface->target->backend->paint) (surface->target, op,
+                                                             source);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+									       source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
     }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
 			      cairo_pattern_t	*source,
 			      cairo_pattern_t	*mask)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status;
+    cairo_status_t	      status, backend_status;
+    cairo_rectangle_int_t   extents;
 
     if (!surface->target->backend->mask)
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
-	status = (*surface->target->backend->mask) (surface->target, op,
-						    source, mask);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	surface->fallback = TRUE;
-	status = CAIRO_STATUS_SUCCESS;
+	backend_status = (*surface->target->backend->mask) (surface->target, op,
+                                                            source, mask);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
+	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+	    if (_cairo_surface_is_meta (surface_pattern->surface))
+		backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+										       source);
+	    if (backend_status != CAIRO_STATUS_SUCCESS &&
+		backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
+		return backend_status;
+	}
+
+	if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
+	    if (_cairo_surface_is_meta (surface_pattern->surface))
+		backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+										       mask);
+	    if (backend_status != CAIRO_STATUS_SUCCESS &&
+		backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
+		return backend_status;
+	}
     }
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
+
+	status = _cairo_pattern_get_extents (mask, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
+    }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_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_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status;
+    cairo_status_t	     status, backend_status;
+    cairo_traps_t            traps;
+    cairo_box_t              box;
+    cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->stroke)
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
-	status = (*surface->target->backend->stroke) (surface->target, op,
-						      source, path, style,
-						      ctm, ctm_inverse,
-						      tolerance, antialias);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	surface->fallback = TRUE;
-	status = CAIRO_STATUS_SUCCESS;
+	backend_status = (*surface->target->backend->stroke) (surface->target, op,
+							      source, path, style,
+							      ctm, ctm_inverse,
+							      tolerance, antialias);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+									       source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
     }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	box.p1.x = _cairo_fixed_from_int (extents.x);
+	box.p1.y = _cairo_fixed_from_int (extents.y);
+	box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
+	box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
+
+	_cairo_traps_init (&traps);
+	_cairo_traps_limit (&traps, &box);
+	status = _cairo_path_fixed_stroke_to_traps (path,
+						    style,
+						    ctm, ctm_inverse,
+						    tolerance,
+						    &traps);
+
+	if (status) {
+	    _cairo_traps_fini (&traps);
+	    return status;
+	}
+
+	_cairo_traps_extents (&traps, &box);
+	extents.x = _cairo_fixed_integer_floor (box.p1.x);
+	extents.y = _cairo_fixed_integer_floor (box.p1.y);
+	extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
+	extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
+	_cairo_traps_fini (&traps);
+    }
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_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_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status;
+    cairo_status_t	     status, backend_status;
+    cairo_traps_t            traps;
+    cairo_box_t              box;
+    cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->fill)
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
-	status = (*surface->target->backend->fill) (surface->target, op,
+	backend_status = (*surface->target->backend->fill) (surface->target, op,
 						    source, path, fill_rule,
 						    tolerance, antialias);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	surface->fallback = TRUE;
-	status = CAIRO_STATUS_SUCCESS;
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+									       source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
     }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	box.p1.x = _cairo_fixed_from_int (extents.x);
+	box.p1.y = _cairo_fixed_from_int (extents.y);
+	box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
+	box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
+
+	_cairo_traps_init (&traps);
+	_cairo_traps_limit (&traps, &box);
+	status = _cairo_path_fixed_fill_to_traps (path,
+						  fill_rule,
+						  tolerance,
+						  &traps);
+
+	if (status) {
+	    _cairo_traps_fini (&traps);
+	    return status;
+	}
+
+	_cairo_traps_extents (&traps, &box);
+	extents.x = _cairo_fixed_integer_floor (box.p1.x);
+	extents.y = _cairo_fixed_integer_floor (box.p1.y);
+	extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
+	extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
+
+	_cairo_traps_fini (&traps);
+    }
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_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_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status;
+    cairo_status_t	     status, backend_status;
+    cairo_rectangle_int_t    extents, glyph_extents;
 
     if (!surface->target->backend->show_glyphs)
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
-	status = (*surface->target->backend->show_glyphs) (surface->target, op,
+	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
 							   source,
 							   glyphs, num_glyphs,
 							   scaled_font);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	surface->fallback = TRUE;
-	status = CAIRO_STATUS_SUCCESS;
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+									       source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
     }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
+							  glyphs,
+							  num_glyphs,
+							  &glyph_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &glyph_extents);
+    }
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
     return status;
 }
 
 static const cairo_surface_backend_t cairo_analysis_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
     NULL, /* create_similar */
-    NULL, /* finish_surface */
+    _cairo_analysis_surface_finish,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* acquire_dest_image */
     NULL, /* release_dest_image */
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
     NULL, /* copy_page */
     NULL, /* show_page */
     NULL, /* set_clip_region */
-    NULL, /* clip_path */
+    _cairo_analysis_surface_intersect_clip_path,
     _cairo_analysis_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_analysis_surface_paint,
     _cairo_analysis_surface_mask,
     _cairo_analysis_surface_stroke,
     _cairo_analysis_surface_fill,
     _cairo_analysis_surface_show_glyphs,
     NULL, /* snapshot */
 };
 
-cairo_private cairo_surface_t *
+cairo_surface_t *
 _cairo_analysis_surface_create (cairo_surface_t		*target,
 				int			 width,
 				int			 height)
 {
     cairo_analysis_surface_t *surface;
 
     surface = malloc (sizeof (cairo_analysis_surface_t));
     if (surface == NULL)
@@ -221,37 +552,55 @@ cairo_private cairo_surface_t *
      * sure nothing will ever use this value. */
     _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     surface->width = width;
     surface->height = height;
 
     surface->target = target;
-    surface->fallback = FALSE;
+    surface->has_supported = FALSE;
+    surface->has_unsupported = FALSE;
+    _cairo_region_init (&surface->supported_region);
+    _cairo_region_init (&surface->fallback_region);
+
+    surface->current_clip.x = 0;
+    surface->current_clip.y = 0;
+    surface->current_clip.width = width;
+    surface->current_clip.height = height;
 
     return &surface->base;
 FAIL:
     _cairo_error (CAIRO_STATUS_NO_MEMORY);
     return NULL;
 }
 
-cairo_private cairo_region_t *
+cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
 {
-    /* XXX */
-    return NULL;
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    return &surface->supported_region;
 }
 
-cairo_private cairo_region_t *
+cairo_region_t *
 _cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
 {
-    /* XXX */
-    return NULL;
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    return &surface->fallback_region;
 }
 
-cairo_private cairo_bool_t
+cairo_bool_t
+_cairo_analysis_surface_has_supported (cairo_surface_t *abstract_surface)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    return surface->has_supported;
+}
+
+cairo_bool_t
 _cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
-    return surface->fallback;
+    return surface->has_unsupported;
 }
--- a/gfx/cairo/cairo/src/cairo-atsui-font.c
+++ b/gfx/cairo/cairo/src/cairo-atsui-font.c
@@ -725,18 +725,18 @@ static cairo_status_t
     CGContextShowGlyphsAtPoint (drawingContext, 0, 0,  
 				&theGlyph, 1);
 
     CGContextRelease (drawingContext);
 
     /* correct for difference between cairo and quartz 
      * coordinate systems.
      */
-    cairo_surface_set_device_offset ((cairo_surface_t *)surface, left, 
-				    -bbox.size.height - bottom);
+    cairo_surface_set_device_offset ((cairo_surface_t *)surface,
+				     -left, (bbox.size.height + bottom));
     _cairo_scaled_glyph_set_surface (scaled_glyph,
 				     &base,
 				     surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -153,17 +153,17 @@ encode_integer (unsigned char *p, int i)
     } else if (i >= 108 && i <= 1131) {
         i -= 108;
         *p++ = (i >> 8)+ 247;
         *p++ = i & 0xff;
     } else if (i >= -1131 && i <= -108) {
         i = -i - 108;
         *p++ = (i >> 8)+ 251;
         *p++ = i & 0xff;
-    } else if (i >= -1131 && i <= -108) {
+    } else if (i >= -32768 && i <= 32767) {
         *p++ = 28;
         *p++ = (i >> 8)  & 0xff;
         *p++ = i & 0xff;
     } else {
         p = encode_integer_max (p, i);
     }
     return p;
 }
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -649,17 +649,16 @@ cairo_private cairo_rectangle_list_t*
             if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
 		_cairo_region_boxes_fini (&clip->region, boxes);
 		free (rectangles);
 		return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 	    }
         }
 
 	_cairo_region_boxes_fini (&clip->region, boxes);
-
     } else {
         cairo_rectangle_int_t extents;
 
 	n_boxes = 1;
 
 	rectangles = malloc(sizeof (cairo_rectangle_t));
 	if (rectangles == NULL)
 	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -1279,18 +1279,18 @@ static cairo_status_t
             case CAIRO_FORMAT_A8:
                 break;
             default:
                 D_DEBUG_AT (Cairo_DirectFB,
                             "Unsupported font format %d!\n", img->format);
                 return CAIRO_INT_STATUS_UNSUPPORTED;
         }
         
-        points[n].x = _cairo_lround (glyphs[i].x + img->base.device_transform.x0);
-        points[n].y = _cairo_lround (glyphs[i].y + img->base.device_transform.y0);
+        points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0);
+        points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0);
         
         if (points[n].x >= surface->width  ||
             points[n].y >= surface->height ||
             points[n].x+img->width  <= 0   ||
             points[n].y+img->height <= 0)
             continue;
         
         if (!scaled_glyph->surface_private) {
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -551,16 +551,17 @@ FT_Face
     }
     _cairo_ft_unscaled_font_map_unlock ();
 
     if (FT_New_Face (font_map->ft_library,
 		     unscaled->filename,
 		     unscaled->id,
 		     &face) != FT_Err_Ok)
     {
+	unscaled->lock_count--;
 	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
 
     unscaled->face = face;
 
     font_map->num_open_faces++;
@@ -582,17 +583,16 @@ void
 }
 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;
-    double tx, ty;
 
     /* The font matrix has x and y "scale" components which we extract and
      * use as character scale values. These influence the way freetype
      * chooses hints, as well as selecting different bitmaps in
      * hand-rendered fonts. We also copy the normalized matrix to
      * freetype's transformation.
      */
 
@@ -601,17 +601,17 @@ static void
 					 /* XXX */ 1);
 
     if (sf->x_scale != 0 && sf->y_scale != 0) {
 	cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
 
 	_cairo_matrix_get_affine (&normalized,
 				  &sf->shape[0][0], &sf->shape[0][1],
 				  &sf->shape[1][0], &sf->shape[1][1],
-				  &tx, &ty);
+				  NULL, NULL);
     } else {
 	sf->shape[0][0] = sf->shape[1][1] = 1.0;
 	sf->shape[0][1] = sf->shape[1][0] = 0.0;
     }
 }
 
 /* Temporarily scales an unscaled font to the give scale. We catch
  * scaling to the same size, since changing a FT_Face is expensive.
@@ -743,16 +743,22 @@ static cairo_status_t
     int width, height, stride;
     unsigned char *data;
     int format = CAIRO_FORMAT_A8;
     cairo_bool_t subpixel = FALSE;
 
     width = bitmap->width;
     height = bitmap->rows;
 
+    if (width == 0 || height == 0) {
+	*surface = (cairo_image_surface_t *)
+	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
+	return (*surface)->base.status;
+    }
+
     switch (bitmap->pixel_mode) {
     case FT_PIXEL_MODE_MONO:
 	stride = (((width + 31) & ~31) >> 3);
 	if (own_buffer) {
 	    data = bitmap->buffer;
 	    assert (stride == bitmap->pitch);
 	} else {
 	    data = _cairo_malloc_ab (height, stride);
@@ -1065,21 +1071,23 @@ static cairo_status_t
 
 	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
 	if (status)
 	    return status;
     }
 
     /*
      * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinate of the control box needs to be negated.
+     * Y coordinate of the control box needs to be negated.  Moreover, device
+     * offsets are position of glyph origin relative to top left while xMin
+     * and yMax are offsets of top left relative to origin.  Another negation.
      */
     cairo_surface_set_device_offset (&(*surface)->base,
-				     floor ((double) cbox.xMin / 64.0),
-				     floor (-(double) cbox.yMax / 64.0));
+				     floor (-(double) cbox.xMin / 64.0),
+				     floor (+(double) cbox.yMax / 64.0));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
 static cairo_status_t
 _render_glyph_bitmap (FT_Face		      face,
 		      cairo_font_options_t   *font_options,
@@ -1092,89 +1100,94 @@ static cairo_status_t
     /* According to the FreeType docs, glyphslot->format could be
      * something other than FT_GLYPH_FORMAT_OUTLINE or
      * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
      * the opportunity to convert such to
      * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
      * we avoid the FT_LOAD_NO_RECURSE flag.
      */
     error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
-    if (error) {
+    /* XXX ignoring all other errors for now.  They are not fatal, typically
+     * just a glyph-not-found. */
+    if (error == FT_Err_Out_Of_Memory) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
     status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
     if (status)
 	return status;
 
     /*
      * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinate of the control box needs to be negated.
+     * Y coordinate of the control box needs to be negated.  Moreover, device
+     * offsets are position of glyph origin relative to top left while
+     * bitmap_left and bitmap_top are offsets of top left relative to origin.
+     * Another negation.
      */
     cairo_surface_set_device_offset (&(*surface)->base,
-				     glyphslot->bitmap_left,
-				     -glyphslot->bitmap_top);
+				     -glyphslot->bitmap_left,
+				     +glyphslot->bitmap_top);
 
     return status;
 }
 
 static cairo_status_t
 _transform_glyph_bitmap (cairo_matrix_t         * shape,
 			 cairo_image_surface_t ** surface)
 {
     cairo_matrix_t original_to_transformed;
     cairo_matrix_t transformed_to_original;
     cairo_image_surface_t *old_image;
     cairo_surface_t *image;
     double x[4], y[4];
     double origin_x, origin_y;
-    int origin_width, origin_height;
+    int orig_width, orig_height;
     int i;
     int x_min, y_min, x_max, y_max;
     int width, height;
     cairo_status_t status;
     cairo_surface_pattern_t pattern;
 
     /* We want to compute a transform that takes the origin
      * (device_x_offset, device_y_offset) to 0,0, then applies
      * the "shape" portion of the font transform
      */
     original_to_transformed = *shape;
     
     cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
-    origin_width = cairo_image_surface_get_width (&(*surface)->base);
-    origin_height = cairo_image_surface_get_height (&(*surface)->base);
+    orig_width = cairo_image_surface_get_width (&(*surface)->base);
+    orig_height = cairo_image_surface_get_height (&(*surface)->base);
 
     cairo_matrix_translate (&original_to_transformed,
-			    origin_x, origin_y);
+			    -origin_x, -origin_y);
 
     /* Find the bounding box of the original bitmap under that
      * transform
      */
-    x[0] = 0;            y[0] = 0;
-    x[1] = origin_width; y[1] = 0;
-    x[2] = origin_width; y[2] = origin_height;
-    x[3] = 0;            y[3] = origin_height;
+    x[0] = 0;          y[0] = 0;
+    x[1] = orig_width; y[1] = 0;
+    x[2] = orig_width; y[2] = orig_height;
+    x[3] = 0;          y[3] = orig_height;
 
     for (i = 0; i < 4; i++)
       cairo_matrix_transform_point (&original_to_transformed,
 				    &x[i], &y[i]);
 
     x_min = floor (x[0]);   y_min = floor (y[0]);
     x_max =  ceil (x[0]);   y_max =  ceil (y[0]);
 
     for (i = 1; i < 4; i++) {
 	if (x[i] < x_min)
 	    x_min = floor (x[i]);
-	if (x[i] > x_max)
+	else if (x[i] > x_max)
 	    x_max = ceil (x[i]);
 	if (y[i] < y_min)
 	    y_min = floor (y[i]);
-	if (y[i] > y_max)
+	else if (y[i] > y_max)
 	    y_max = ceil (y[i]);
     }
 
     /* Adjust the transform so that the bounding box starts at 0,0 ...
      * this gives our final transform from original bitmap to transformed
      * bitmap.
      */
     original_to_transformed.x0 -= x_min;
@@ -1223,28 +1236,26 @@ static cairo_status_t
     if (status) {
 	cairo_surface_destroy (image);
 	return status;
     }
 
     /* Now update the cache entry for the new bitmap, recomputing
      * the origin based on the final transform.
      */
-    origin_x = - origin_x;
-    origin_y = - origin_y;
     cairo_matrix_transform_point (&original_to_transformed,
 				  &origin_x, &origin_y);
 
     old_image = (*surface);
     (*surface) = (cairo_image_surface_t *)image;
     cairo_surface_destroy (&old_image->base);
 
     cairo_surface_set_device_offset (&(*surface)->base,
-				     - _cairo_lround (origin_x),
-				     - _cairo_lround (origin_y));
+				     _cairo_lround (origin_x),
+				     _cairo_lround (origin_y));
     return status;
 }
 
 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
     _cairo_ft_unscaled_font_destroy,
 #if 0
     _cairo_ft_unscaled_font_create_glyph
 #endif
@@ -1886,18 +1897,19 @@ static cairo_int_status_t
     if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
 	load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
 	vertical_layout = TRUE;
     }
 
     error = FT_Load_Glyph (scaled_font->unscaled->face,
 			   _cairo_scaled_glyph_index(scaled_glyph),
 			   load_flags);
-
-    if (error) {
+    /* XXX ignoring all other errors for now.  They are not fatal, typically
+     * just a glyph-not-found. */
+    if (error == FT_Err_Out_Of_Memory) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto FAIL;
     }
 
     glyph = face->glyph;
 
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
     /*
@@ -2037,18 +2049,19 @@ static cairo_int_status_t
 	/*
 	 * A kludge -- the above code will trash the outline,
 	 * 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) {
+	    /* XXX ignoring all other errors for now.  They are not fatal, typically
+	     * just a glyph-not-found. */
+	    if (error == FT_Err_Out_Of_Memory) {
 		_cairo_ft_unscaled_font_unlock_face (unscaled);
 		_cairo_error (CAIRO_STATUS_NO_MEMORY);
 		return CAIRO_STATUS_NO_MEMORY;
 	    }
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 	    /*
 	     * embolden glyphs if requested
 	     */
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -152,17 +152,17 @@ static cairo_bool_t
 
 static glitz_box_t *
 _cairo_glitz_get_boxes_from_region (cairo_region_t *region, int *nboxes)
 {
     cairo_box_int_t *cboxes;
     glitz_box_t *gboxes;
     int n, i;
 
-    if (_cairo_region_get_boxes (&surface->clip, &n, &cboxes) != CAIRO_STATUS_SUCCESS)
+    if (_cairo_region_get_boxes (region, &n, &cboxes) != CAIRO_STATUS_SUCCESS)
         return NULL;
 
     *nboxes = n;
     if (n == 0)
         return NULL;
 
     gboxes = _cairo_malloc_ab (n, sizeof(glitz_box_t));
     if (gboxes == NULL)
@@ -171,17 +171,17 @@ static glitz_box_t *
     for (i = 0; i < n; i++) {
         gboxes[i].x1 = cboxes[i].p1.x;
         gboxes[i].y1 = cboxes[i].p1.y;
         gboxes[i].x2 = cboxes[i].p2.x;
         gboxes[i].y2 = cboxes[i].p2.y;
     }
 
 done:
-    _cairo_region_boxes_fini (&sruface->clip, &cboxes);
+    _cairo_region_boxes_fini (region, cboxes);
     return gboxes;
 }
 
 static cairo_status_t
 _cairo_glitz_surface_get_image (cairo_glitz_surface_t   *surface,
 				cairo_rectangle_int_t   *interest,
 				cairo_image_surface_t  **image_out,
 				cairo_rectangle_int_t   *rect_out)
@@ -798,20 +798,20 @@ static cairo_int_status_t
 	    glitz_buffer_destroy (buffer);
 	    free (data);
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
 
 	for (i = 0; i < gradient->n_stops; i++)
 	{
 	    pixels[i] =
-		(((int) (gradient->stops[i].color.alpha >> 8)) << 24) |
-		(((int) (gradient->stops[i].color.red   >> 8)) << 16) |
-		(((int) (gradient->stops[i].color.green >> 8)) << 8)  |
-		(((int) (gradient->stops[i].color.blue  >> 8)));
+		(((int) (gradient->stops[i].color.alpha_short >> 8)) << 24) |
+		(((int) (gradient->stops[i].color.red_short   >> 8)) << 16) |
+		(((int) (gradient->stops[i].color.green_short >> 8)) << 8)  |
+		(((int) (gradient->stops[i].color.blue_short  >> 8)));
 
 	    params[n_base_params + 3 * i + 0] = gradient->stops[i].x;
 	    params[n_base_params + 3 * i + 1] = i << 16;
 	    params[n_base_params + 3 * i + 2] = 0;
 	}
 
 	glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
 			  (glitz_pixel_format_t *)&format, buffer);
@@ -829,20 +829,20 @@ static cairo_int_status_t
 	    attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
 	}
 	else
 	{
 	    cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
 
 	    params[0] = grad->c1.x;
 	    params[1] = grad->c1.y;
-	    params[2] = grad->radius1;
+	    params[2] = grad->r1;
 	    params[3] = grad->c2.x;
 	    params[4] = grad->c2.y;
-	    params[5] = grad->radius2;
+	    params[5] = grad->r2;
 	    attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
 	}
 
 	switch (pattern->extend) {
 	case CAIRO_EXTEND_NONE:
 	    attr->fill = GLITZ_FILL_TRANSPARENT;
 	    break;
 	case CAIRO_EXTEND_REPEAT:
@@ -1425,22 +1425,21 @@ static cairo_int_status_t
     if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_glitz_surface_set_clip_region (void		*abstract_surface,
-                                      cairo_region_t	*region);
+                                      cairo_region_t	*region)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
 
     if (region)
-
     {
 	glitz_box_t *box;
 	int	    n;
 
 	if (!surface->has_clip) {
             _cairo_region_init (&surface->clip);
             surface->has_clip = TRUE;
         }
@@ -2198,18 +2197,18 @@ static cairo_int_status_t
 	{
 	    remaining_glyps--;
 
 	    if (glyph_private->area->width)
 	    {
 		x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
 		y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
 
-		x1 = _cairo_lround (glyphs[i].x) + x_offset;
-		y1 = _cairo_lround (glyphs[i].y) + y_offset;
+		x1 = _cairo_lround (glyphs[i].x - x_offset);
+		y1 = _cairo_lround (glyphs[i].y - y_offset);
 		x2 = x1 + glyph_private->area->width;
 		y2 = y1 + glyph_private->area->height;
 
 		WRITE_BOX (vertices, x1, y1, x2, y2,
 			   &glyph_private->p1, &glyph_private->p2);
 
 		glyph_private->locked = TRUE;
 
@@ -2242,18 +2241,18 @@ static cairo_int_status_t
 							glyph_height,
 							(cairo_surface_t **)
 							&clone);
 		if (status)
 		    goto UNLOCK;
 
 		x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
 		y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
-		x1 = _cairo_lround (glyphs[i].x) + x_offset;
-		y1 = _cairo_lround (glyphs[i].y) + y_offset;
+		x1 = _cairo_lround (glyphs[i].x - x_offset);
+		y1 = _cairo_lround (glyphs[i].y - y_offset);
 
 		glitz_composite (_glitz_operator (op),
 				 src->surface,
 				 clone->surface,
 				 dst->surface,
 				 src_x + attributes.base.x_offset + x1,
 				 src_y + attributes.base.y_offset + y1,
 				 0, 0,
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -742,18 +742,19 @@ void
 void
 _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
                                          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_multiply (&matrix_inverse,
+                           &gstate->target->device_transform_inverse,
+			   &gstate->ctm_inverse);
     _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)
 {
@@ -1081,23 +1082,23 @@ BAIL:
     _cairo_traps_fini (&traps);
 
     return status;
 }
 
 cairo_status_t
 _cairo_gstate_copy_page (cairo_gstate_t *gstate)
 {
-    return _cairo_surface_copy_page (gstate->target);
+    return cairo_surface_copy_page (gstate->target);
 }
 
 cairo_status_t
 _cairo_gstate_show_page (cairo_gstate_t *gstate)
 {
-    return _cairo_surface_show_page (gstate->target);
+    return cairo_surface_show_page (gstate->target);
 }
 
 static void
 _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t	  *gstate,
                                                cairo_traps_t      *traps,
                                                double *x1, double *y1,
                                                double *x2, double *y2)
 {
@@ -1391,23 +1392,24 @@ cairo_status_t
  * called the "font matrix" which describes the user's most recent
  * font-scaling or font-transforming request. This is kept in terms of an
  * abstract scale factor, composed with the CTM and used to set the font's
  * pixel size. So if the user asks to "scale the font by 12", the matrix
  * is:
  *
  *   [ 12.0, 0.0, 0.0, 12.0, 0.0, 0.0 ]
  *
- * It is an affine matrix, like all cairo matrices, but its tx and ty
- * components are always set to zero; we don't permit "nudging" fonts
- * around.
+ * It is an affine matrix, like all cairo matrices, where its tx and ty
+ * components are used to "nudging" fonts around and are handled in gstate
+ * and then ignored by the "scaled-font" layer.
  *
  * In order to perform any action on a font, we must build an object
  * called a cairo_font_scale_t; this contains the central 2x2 matrix
- * resulting from "font matrix * CTM".
+ * resulting from "font matrix * CTM" (sans the font matrix translation
+ * components as stated in the previous paragraph).
  *
  * We pass this to the font when making requests of it, which causes it to
  * reply for a particular [user request, device] combination, under the CTM
  * (to accommodate the "zoom in" == "bigger fonts" issue above).
  *
  * The other terms in our communication with the font are therefore in
  * device space. When we ask it to perform text->glyph conversion, it will
  * produce a glyph string in device space. Glyph vectors we pass to it for
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -53,137 +53,305 @@ static const cairo_image_surface_t _cair
 	{ 1.0, 0.0,
 	  0.0, 1.0,
 	  0.0, 0.0
 	},				/* device_transform */
 	{ 1.0, 0.0,
 	  0.0, 1.0,
 	  0.0, 0.0
 	},				/* device_transform_inverse */
+	0.0,				/* x_resolution */
+	0.0,				/* y_resolution */
 	0.0,				/* x_fallback_resolution */
 	0.0,				/* y_fallback_resolution */
 	NULL,				/* clip */
 	0,				/* next_clip_serial */
 	0,				/* current_clip_serial */
 	FALSE,				/* is_snapshot */
 	FALSE,				/* has_font_options */
 	{ CAIRO_ANTIALIAS_DEFAULT,
 	  CAIRO_SUBPIXEL_ORDER_DEFAULT,
 	  CAIRO_HINT_STYLE_DEFAULT,
 	  CAIRO_HINT_METRICS_DEFAULT
 	}				/* font_options */
     },					/* base */
+    PIXMAN_a8r8g8b8,			/* pixman_format */
     CAIRO_FORMAT_ARGB32,		/* format */
     NULL,				/* data */
     FALSE,				/* owns_data */
     FALSE,				/* has_clip */
     0,					/* width */
     0,					/* height */
     0,					/* stride */
     0,					/* depth */
     NULL				/* pixman_image */
 };
 
+static cairo_format_t
+_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
+{
+    switch (pixman_format) {
+    case PIXMAN_a8r8g8b8:
+	return CAIRO_FORMAT_ARGB32;
+    case PIXMAN_x8r8g8b8:
+	return CAIRO_FORMAT_RGB24;
+    case PIXMAN_a8:
+	return CAIRO_FORMAT_A8;
+    case PIXMAN_a1:
+	return CAIRO_FORMAT_A1;
+    case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
+    case PIXMAN_b8g8r8:   case PIXMAN_r5g6b5:   case PIXMAN_b5g6r5:
+    case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
+    case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
+    case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
+    case PIXMAN_b2g3r3:   case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2:
+    case PIXMAN_c8:       case PIXMAN_g8:       case PIXMAN_x4a4:
+    case PIXMAN_a4:       case PIXMAN_r1g2b1:   case PIXMAN_b1g2r1:
+    case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
+    case PIXMAN_g4:       case PIXMAN_g1:
+    default:
+	return CAIRO_FORMAT_INVALID;
+    }
+
+    return CAIRO_FORMAT_INVALID;
+}
+
+static cairo_content_t
+_cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
+{
+    switch (pixman_format) {
+    case PIXMAN_a8r8g8b8:
+    case PIXMAN_a8b8g8r8:
+    case PIXMAN_a1r5g5b5:
+    case PIXMAN_a1b5g5r5:
+    case PIXMAN_a4r4g4b4:
+    case PIXMAN_a4b4g4r4:
+    case PIXMAN_a2r2g2b2:
+    case PIXMAN_a2b2g2r2:
+    case PIXMAN_a1r1g1b1:
+    case PIXMAN_a1b1g1r1:
+	return CAIRO_CONTENT_COLOR_ALPHA;
+    case PIXMAN_x8r8g8b8:
+    case PIXMAN_x8b8g8r8:
+    case PIXMAN_r8g8b8:
+    case PIXMAN_b8g8r8:
+    case PIXMAN_r5g6b5:
+    case PIXMAN_b5g6r5:
+    case PIXMAN_x1r5g5b5:
+    case PIXMAN_x1b5g5r5:
+    case PIXMAN_x4r4g4b4:
+    case PIXMAN_x4b4g4r4:
+    case PIXMAN_r3g3b2:
+    case PIXMAN_b2g3r3:
+    case PIXMAN_c8:
+    case PIXMAN_g8:
+    case PIXMAN_r1g2b1:
+    case PIXMAN_b1g2r1:
+    case PIXMAN_c4:
+    case PIXMAN_g4:
+    case PIXMAN_g1:
+	return CAIRO_CONTENT_COLOR;
+    case PIXMAN_a8:
+    case PIXMAN_a1:
+    case PIXMAN_x4a4:
+    case PIXMAN_a4:
+	return CAIRO_CONTENT_ALPHA;
+    }
+
+    return CAIRO_CONTENT_COLOR_ALPHA;
+}
 
 cairo_surface_t *
-_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
-					      cairo_format_t  format)
+_cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
+					      pixman_format_code_t	 pixman_format)
 {
     cairo_image_surface_t *surface;
 
     surface = malloc (sizeof (cairo_image_surface_t));
     if (surface == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     _cairo_surface_init (&surface->base, &cairo_image_surface_backend,
-			 _cairo_content_from_format (format));
+			 _cairo_content_from_pixman_format (pixman_format));
 
     surface->pixman_image = pixman_image;
 
-    surface->format = format;
+    surface->pixman_format = pixman_format;
+    surface->format = _cairo_format_from_pixman_format (pixman_format);
     surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
     surface->owns_data = FALSE;
     surface->has_clip = FALSE;
 
     surface->width = pixman_image_get_width (pixman_image);
     surface->height = pixman_image_get_height (pixman_image);
     surface->stride = pixman_image_get_stride (pixman_image);
     surface->depth = pixman_image_get_depth (pixman_image);
 
     return &surface->base;
 }
 
-static cairo_bool_t
-_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
+/* XXX: This function should really live inside pixman. */
+pixman_format_code_t
+_pixman_format_from_masks (cairo_format_masks_t *masks)
 {
-    /* XXX: many formats are simply not supported by pixman, so this function
-     * converts the masks into something we know will be supported.
-     */
     switch (masks->bpp) {
     case 32:
 	if (masks->alpha_mask == 0xff000000 &&
-	    masks->red_mask == 0x00ff0000 &&
+	    masks->red_mask   == 0x00ff0000 &&
+	    masks->green_mask == 0x0000ff00 &&
+	    masks->blue_mask  == 0x000000ff)
+	{
+	    return PIXMAN_a8r8g8b8;
+	}
+	if (masks->alpha_mask == 0x00000000 &&
+	    masks->red_mask   == 0x00ff0000 &&
 	    masks->green_mask == 0x0000ff00 &&
-	    masks->blue_mask == 0x000000ff)
+	    masks->blue_mask  == 0x000000ff)
 	{
-	    *format = CAIRO_FORMAT_ARGB32;
-	    return TRUE;
+	    return PIXMAN_x8r8g8b8;
+	}
+	if (masks->alpha_mask == 0xff000000 &&
+	    masks->red_mask   == 0x000000ff &&
+	    masks->green_mask == 0x0000ff00 &&
+	    masks->blue_mask  == 0x00ff0000)
+	{
+	    return PIXMAN_a8b8g8r8;
 	}
 	if (masks->alpha_mask == 0x00000000 &&
-	    masks->red_mask == 0x00ff0000 &&
+	    masks->red_mask   == 0x000000ff &&
 	    masks->green_mask == 0x0000ff00 &&
-	    masks->blue_mask == 0x000000ff)
+	    masks->blue_mask  == 0x00ff0000)
 	{
-	    *format = CAIRO_FORMAT_RGB24;
-	    return TRUE;
+	    return PIXMAN_x8b8g8r8;
+	}
+	break;
+    case 16:
+	if (masks->alpha_mask == 0x0000 &&
+	    masks->red_mask   == 0xf800 &&
+	    masks->green_mask == 0x07e0 &&
+	    masks->blue_mask  == 0x001f)
+	{
+	    return PIXMAN_r5g6b5;
+	}
+	if (masks->alpha_mask == 0x0000 &&
+	    masks->red_mask   == 0x7c00 &&
+	    masks->green_mask == 0x03e0 &&
+	    masks->blue_mask  == 0x001f)
+	{
+	    return PIXMAN_x1r5g5b5;
 	}
 	break;
     case 8:
 	if (masks->alpha_mask == 0xff)
 	{
-	    *format = CAIRO_FORMAT_A8;
-	    return TRUE;
+	    return PIXMAN_a8;
 	}
 	break;
     case 1:
 	if (masks->alpha_mask == 0x1)
 	{
-	    *format = CAIRO_FORMAT_A1;
-	    return TRUE;
+	    return PIXMAN_a1;
 	}
 	break;
     }
-    return FALSE;
+
+    fprintf (stderr,
+	     "Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
+	     "\tDepth: %d\n"
+	     "\tAlpha mask: 0x%08lx\n"
+	     "\tRed   mask: 0x%08lx\n"
+	     "\tGreen mask: 0x%08lx\n"
+	     "\tBlue  mask: 0x%08lx\n"
+	     "Please file an enhancement request (quoting the above) at:\n"
+	     PACKAGE_BUGREPORT "\n",
+	     masks->bpp, masks->alpha_mask,
+	     masks->red_mask, masks->green_mask, masks->blue_mask);
+
+    ASSERT_NOT_REACHED;
+    return 0;
 }
 
+/* XXX: This function should really live inside pixman. */
+void
+_pixman_format_to_masks (pixman_format_code_t	 pixman_format,
+			 uint32_t		*bpp,
+			 uint32_t		*red,
+			 uint32_t		*green,
+			 uint32_t		*blue)
+{
+    *red = 0x0;
+    *green = 0x0;
+    *blue = 0x0;
+
+    switch (pixman_format)
+    {
+    case PIXMAN_a8r8g8b8:
+    case PIXMAN_x8r8g8b8:
+    default:
+	*bpp   = 32;
+	*red   = 0x00ff0000;
+	*green = 0x0000ff00;
+	*blue  = 0x000000ff;
+	break;
+
+    case PIXMAN_a8b8g8r8:
+    case PIXMAN_x8b8g8r8:
+	*bpp   = 32;
+	*red   = 0x000000ff;
+	*green = 0x0000ff00;
+	*blue  = 0x00ff0000;
+	break;
+
+    case PIXMAN_r5g6b5:
+	*bpp   = 16;
+	*red   = 0xf800;
+	*green = 0x07e0;
+	*blue  = 0x001f;
+	break;
+
+    case PIXMAN_x1r5g5b5:
+	*bpp   = 16;
+	*red   = 0x7c00;
+	*green = 0x03e0;
+	*blue  = 0x001f;
+	break;
+
+    case PIXMAN_a8:
+	*bpp = 8;
+	break;
+
+    case PIXMAN_a1:
+	*bpp = 1;
+	break;
+    }
+}
+
+
 /* XXX: This function really should be eliminated. We don't really
  * want to advertise a cairo image surface that supports any possible
  * format. A minimal step would be to replace this function with one
  * that accepts a cairo_internal_format_t rather than mask values. */
 cairo_surface_t *
 _cairo_image_surface_create_with_masks (unsigned char	       *data,
 					cairo_format_masks_t   *masks,
 					int			width,
 					int			height,
 					int			stride)
 {
-    cairo_format_t format;
+    pixman_format_code_t pixman_format;
     
-    if (!_CAIRO_MASK_FORMAT (masks, &format)) {
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    pixman_format = _pixman_format_from_masks (masks);
 
-    return cairo_image_surface_create_for_data (data,
-						format,
-						width,
-						height,
-						stride);
+    return _cairo_image_surface_create_with_pixman_format (data,
+							   pixman_format,
+							   width,
+							   height,
+							   stride);
 }
 
 static pixman_format_code_t 
 _cairo_format_to_pixman_format_code (cairo_format_t format)
 {
     int ret = 0;
     switch (format) {
     case CAIRO_FORMAT_A1:
@@ -199,16 +367,43 @@ static pixman_format_code_t
     default:
 	ret = PIXMAN_a8r8g8b8;
 	break;
     }
     assert (ret);
     return ret;
 }
 
+cairo_surface_t *
+_cairo_image_surface_create_with_pixman_format (unsigned char		*data,
+						pixman_format_code_t	 pixman_format,
+						int			 width,
+						int			 height,
+						int			 stride)
+{
+    cairo_surface_t *surface;
+    pixman_image_t *pixman_image;
+
+    pixman_image = pixman_image_create_bits (pixman_format, width, height,
+					     (uint32_t *) data, stride);
+
+    if (pixman_image == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
+							    pixman_format);
+    if (cairo_surface_status (surface)) {
+	pixman_image_unref (pixman_image);
+    }
+
+    return surface;
+}
+
 /**
  * cairo_image_surface_create:
  * @format: format of pixels in the surface to create
  * @width: width of the surface, in pixels
  * @height: height of the surface, in pixels
  *
  * Creates an image surface of the specified format and
  * dimensions. Initially the surface contents are all
@@ -226,36 +421,26 @@ static pixman_format_code_t
  **/
 cairo_surface_t *
 cairo_image_surface_create (cairo_format_t	format,
 			    int			width,
 			    int			height)
 {
     cairo_surface_t	*surface;
     pixman_format_code_t pixman_format;
-    pixman_image_t	*pixman_image;
 
     if (! CAIRO_FORMAT_VALID (format)) {
 	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
 	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
     }
 
     pixman_format = _cairo_format_to_pixman_format_code (format);
-    
-    pixman_image = pixman_image_create_bits (pixman_format, width, height,
-					     NULL, -1);
-    if (pixman_image == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
 
-    surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
-    if (cairo_surface_status (surface)) {
-	pixman_image_unref (pixman_image);
-    }
+    return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format,
+							   width, height, -1);
 
     return surface;
 }
 slim_hidden_def (cairo_image_surface_create);
 
 cairo_surface_t *
 _cairo_image_surface_create_with_content (cairo_content_t	content,
 					  int			width,
@@ -300,39 +485,25 @@ cairo_surface_t *
  **/
 cairo_surface_t *
 cairo_image_surface_create_for_data (unsigned char     *data,
 				     cairo_format_t	format,
 				     int		width,
 				     int		height,
 				     int		stride)
 {
-    cairo_surface_t	*surface;
     pixman_format_code_t pixman_format;
-    pixman_image_t	*pixman_image;
 
     if (! CAIRO_FORMAT_VALID (format))
 	return (cairo_surface_t*) &_cairo_surface_nil;
 
     pixman_format = _cairo_format_to_pixman_format_code (format);
 
-    pixman_image = pixman_image_create_bits (pixman_format, width, height,
-					     (uint32_t *) data, stride);
-    
-    if (pixman_image == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
-    if (cairo_surface_status (surface)) {
-	pixman_image_unref (pixman_image);
-    }
-
-    return surface;
+    return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
+							   width, height, stride);
 }
 slim_hidden_def (cairo_image_surface_create_for_data);
 
 cairo_surface_t *
 _cairo_image_surface_create_for_data_with_content (unsigned char	*data,
 						   cairo_content_t	 content,
 						   int			 width,
 						   int			 height,
@@ -481,30 +652,20 @@ cairo_format_t
 
     ASSERT_NOT_REACHED;
     return CAIRO_FORMAT_ARGB32;
 }
 
 cairo_content_t
 _cairo_content_from_format (cairo_format_t format)
 {
-    /* XXX: Use an int to avoid the warnings from mixed cairo_format_t
-     * and cairo_internal_format_t values. The warnings are extremely
-     * valuable since mixing enums can lead to subtle bugs. It's just
-     * that cairo_internal_format_t is an interim approach to getting
-     * bug #7294 fixed so we can release cairo 1.2.2 . */
-    int f = format;
-
-    switch (f) {
+    switch (format) {
     case CAIRO_FORMAT_ARGB32:
-    case CAIRO_INTERNAL_FORMAT_ABGR32:
 	return CAIRO_CONTENT_COLOR_ALPHA;
     case CAIRO_FORMAT_RGB24:
-    case CAIRO_INTERNAL_FORMAT_RGB16_565:
-    case CAIRO_INTERNAL_FORMAT_BGR24:
 	return CAIRO_CONTENT_COLOR;
     case CAIRO_FORMAT_A8:
     case CAIRO_FORMAT_A1:
 	return CAIRO_CONTENT_ALPHA;
     }
 
     ASSERT_NOT_REACHED;
     return CAIRO_CONTENT_COLOR_ALPHA;
@@ -622,17 +783,17 @@ static cairo_status_t
     _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
 
     if (!pixman_image_set_transform (surface->pixman_image, &pixman_transform))
 	return CAIRO_STATUS_NO_MEMORY;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+static void
 _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter)
 {
     pixman_filter_t pixman_filter;
 
     switch (filter) {
     case CAIRO_FILTER_FAST:
 	pixman_filter = PIXMAN_FILTER_FAST;
 	break;
@@ -654,21 +815,19 @@ static cairo_status_t
 	 * API. We could fix this by officially deprecating it, or
 	 * else inventing semantics and providing an actual
 	 * implementation for it. */
     default:
 	pixman_filter = PIXMAN_FILTER_BEST;
     }
 
     pixman_image_set_filter (surface->pixman_image, pixman_filter, NULL, 0);
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_int_status_t
+static cairo_status_t
 _cairo_image_surface_set_attributes (cairo_image_surface_t      *surface,
 				     cairo_surface_attributes_t *attributes)
 {
     cairo_int_status_t status;
 
     status = _cairo_image_surface_set_matrix (surface, &attributes->matrix);
     if (status)
 	return status;
@@ -683,19 +842,19 @@ static cairo_int_status_t
     case CAIRO_EXTEND_REFLECT:
         pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT);
 	break;
     case CAIRO_EXTEND_PAD:
         pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD);
 	break;
     }
 
-    status = _cairo_image_surface_set_filter (surface, attributes->filter);
+    _cairo_image_surface_set_filter (surface, attributes->filter);
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 /* XXX: I think we should fix pixman to match the names/order of the
  * cairo operators, but that will likely be better done at the same
  * time the X server is ported to pixman, (which will change a lot of
  * things in pixman I think).
  */
 static pixman_op_t
@@ -898,16 +1057,19 @@ static cairo_int_status_t
     pixman_format_code_t	 format;
     uint32_t			*mask_data;
     pixman_trapezoid_t		 stack_traps[STACK_TRAPS_LEN];
     pixman_trapezoid_t		*pixman_traps = stack_traps;
     int				 mask_stride;
     int				 mask_bpp;
     int				 ret, i;
 
+    if (height == 0 || width == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     /* Convert traps to pixman traps */
     if (num_traps > ARRAY_LENGTH(stack_traps)) {
 	pixman_traps = _cairo_malloc_ab (num_traps, sizeof(pixman_trapezoid_t));
 	if (pixman_traps == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
     }
 
     for (i = 0; i < num_traps; i++) {
@@ -919,17 +1081,17 @@ static cairo_int_status_t
 	pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
 	pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
 	pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
 	pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
 	pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
     }
 
     /* Special case adding trapezoids onto a mask surface; we want to avoid
-     * creating an intermediate temporary mask unecessarily.
+     * creating an intermediate temporary mask unnecessarily.
      *
      * We make the assumption here that the portion of the trapezoids
      * contained within the surface is bounded by [dst_x,dst_y,width,height];
      * the Cairo core code passes bounds based on the trapezoid extents.
      *
      * Currently the check surface->has_clip is needed for correct
      * functioning, since pixman_add_trapezoids() doesn't obey the
      * surface clip, which is a libpixman bug , but there's no harm in
@@ -1069,18 +1231,17 @@ static void
 
 static cairo_status_t
 _cairo_image_surface_reset (void *abstract_surface)
 {
     cairo_image_surface_t *surface = abstract_surface;
     cairo_status_t status;
 
     status = _cairo_image_surface_set_clip_region (surface, NULL);
-    if (status)
-	return status;
+    assert (status == CAIRO_STATUS_SUCCESS);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_surface_is_image:
  * @surface: a #cairo_surface_t
  *
@@ -1110,25 +1271,25 @@ const cairo_surface_backend_t cairo_imag
     NULL, /* show_page */
     _cairo_image_surface_set_clip_region,
     NULL, /* intersect_clip_path */
     _cairo_image_surface_get_extents,
     NULL, /* old_show_glyphs */
     _cairo_image_surface_get_font_options,
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
-    NULL, //* font_fini */
-    NULL, //* glyph_fini */
+    NULL, /* font_fini */
+    NULL, /* glyph_fini */
 
     NULL, /* paint */
     NULL, /* mask */
     NULL, /* stroke */
     NULL, /* fill */
     NULL, /* show_glyphs */
-    NULL,  /* snapshot */
+    NULL, /* snapshot */
     NULL, /* is_similar */
 
     _cairo_image_surface_reset
 };
 
 /* A convenience function for when one needs to coerce an image
  * surface to an alternate format. */
 cairo_image_surface_t *
@@ -1138,20 +1299,20 @@ 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 */
+    cairo_surface_get_device_offset (&surface->base, &x, &y);
+    cairo_surface_set_device_offset (&clone->base, x, y);
+
+    /* XXX 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_source_surface (cr, &surface->base, 0, 0);
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
     cairo_paint (cr);
     cairo_destroy (cr);
 
-    cairo_surface_set_device_offset (&clone->base, x, y);
-
     return clone;
 }
--- a/gfx/cairo/cairo/src/cairo-malloc-private.h
+++ b/gfx/cairo/cairo/src/cairo-malloc-private.h
@@ -35,85 +35,70 @@
  */
 
 #ifndef CAIRO_MALLOC_PRIVATE_H
 #define CAIRO_MALLOC_PRIVATE_H
 
 #include "cairo-wideint-private.h"
 
 /**
- * _cairo_malloc:
- * @size: size in bytes
- *
- * Allocate @size memory using malloc().
- * The memory should be freed using free().
- * malloc is skipped, if 0 bytes are requested, and %NULL will be returned.
- *
- * Return value: A pointer to the newly allocated memory, or %NULL in
- * case of malloc() failure or size is 0.
- */
-
-#define _cairo_malloc(size) \
-   ((size) ? malloc((unsigned) (size)) : NULL)
-
-/**
  * _cairo_malloc_ab:
  * @n: number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@size memory using _cairo_malloc(), taking care to not
+ * Allocates @a*@size memory using malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves much like
  * calloc(), except that the returned memory is not set to zero.
  * The memory should be freed using free().
  *
  * @size should be a constant so that the compiler can optimize
  * out a constant division.
  *
  * Return value: A pointer to the newly allocated memory, or %NULL in
  * case of malloc() failure or overflow.
  */
 
 #define _cairo_malloc_ab(a, size) \
-  ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
-   _cairo_malloc((unsigned) (a) * (unsigned) (size)))
+  ((unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (a) * (unsigned) (size)))
 
 /**
  * _cairo_malloc_abc:
  * @a: first factor of number of elements to allocate
  * @b: second factor of number of elements to allocate
  * @size: size of each element
  *
- * Allocates @a*@b*@size memory using _cairo_malloc(), taking care to not
+ * Allocates @a*@b*@size memory using malloc(), taking care to not
  * overflow when doing the multiplication.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
  * @size should be a constant so that the compiler can optimize
  * out a constant division.
  *
  * Return value: A pointer to the newly allocated memory, or %NULL in
  * case of malloc() failure or overflow.
  */
 
 #define _cairo_malloc_abc(a, b, size) \
-  ((b) && (unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
-   (size) && (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
-   _cairo_malloc((unsigned) (a) * (unsigned) (b) * (unsigned) (size)))
+  ((unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
+   (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (a) * (unsigned) (b) * (unsigned) size))
 
 /**
  * _cairo_malloc_ab_plus_c:
  * @n: number of elements to allocate
  * @size: size of each element
  * @k: additional size to allocate
  *
- * Allocates @a*@ksize+@k memory using _cairo_malloc(), taking care to not
+ * Allocates @a*@ksize+@k memory using malloc(), taking care to not
  * overflow when doing the arithmetic.  Behaves like
  * _cairo_malloc_ab().  The memory should be freed using free().
  *
  * Return value: A pointer to the newly allocated memory, or %NULL in
  * case of malloc() failure or overflow.
  */
 
 #define _cairo_malloc_ab_plus_c(n, size, k) \
-  ((size) && (unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
+  ((unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
    (unsigned) (k) >= INT32_MAX - (unsigned) (n) * (unsigned) (size) ? NULL : \
-   _cairo_malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
+   malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
 
 #endif /* CAIRO_MALLOC_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h
@@ -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 Red Hat, Inc.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
+ *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_META_SURFACE_H
 #define CAIRO_META_SURFACE_H
 
 #include "cairoint.h"
 #include "cairo-path-fixed-private.h"
 
@@ -52,71 +53,82 @@ typedef enum {
      * basic drawing operations (which we implement already so the
      * fallbacks should never get triggered). So the plan is to
      * eliminate as many of these as possible. */
 
     CAIRO_COMMAND_INTERSECT_CLIP_PATH
 
 } cairo_command_type_t;
 
+typedef enum {
+    CAIRO_META_REGION_ALL,
+    CAIRO_META_REGION_NATIVE,
+    CAIRO_META_REGION_IMAGE_FALLBACK,
+} cairo_meta_region_type_t;
+
+typedef struct _cairo_command_header {
+    cairo_command_type_t	 type;
+    cairo_meta_region_type_t     region;
+} cairo_command_header_t;
+
 typedef struct _cairo_command_paint {
-    cairo_command_type_t	 type;
+    cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
 } cairo_command_paint_t;
 
 typedef struct _cairo_command_mask {
-    cairo_command_type_t	 type;
+    cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
     cairo_pattern_union_t	 mask;
 } cairo_command_mask_t;
 
 typedef struct _cairo_command_stroke {
-    cairo_command_type_t	 type;
+    cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_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_command_stroke_t;
 
 typedef struct _cairo_command_fill {
-    cairo_command_type_t	 type;
+    cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
     cairo_path_fixed_t		 path;
     cairo_fill_rule_t		 fill_rule;
     double			 tolerance;
     cairo_antialias_t		 antialias;
 } cairo_command_fill_t;
 
 typedef struct _cairo_command_show_glyphs {
-    cairo_command_type_t	 type;
+    cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
     cairo_glyph_t		*glyphs;
     unsigned int		 num_glyphs;
     cairo_scaled_font_t		*scaled_font;
 } cairo_command_show_glyphs_t;
 
 typedef struct _cairo_command_intersect_clip_path {
-    cairo_command_type_t	type;
+    cairo_command_header_t      header;
     cairo_path_fixed_t	       *path_pointer;
     cairo_path_fixed_t		path;
     cairo_fill_rule_t		fill_rule;
     double			tolerance;
     cairo_antialias_t		antialias;
 } cairo_command_intersect_clip_path_t;
 
 typedef union _cairo_command {
-    cairo_command_type_t			type;
+    cairo_command_header_t      header;
 
     /* The 5 basic drawing operations. */
     cairo_command_paint_t			paint;
     cairo_command_mask_t			mask;
     cairo_command_stroke_t			stroke;
     cairo_command_fill_t			fill;
     cairo_command_show_glyphs_t			show_glyphs;
 
@@ -146,12 +158,24 @@ cairo_private cairo_surface_t *
 _cairo_meta_surface_create (cairo_content_t	content,
 			    int			width_pixels,
 			    int			height_pixels);
 
 cairo_private cairo_status_t
 _cairo_meta_surface_replay (cairo_surface_t *surface,
 			    cairo_surface_t *target);
 
+cairo_private cairo_status_t
+_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
+						 cairo_surface_t *target);
+
+cairo_private cairo_status_t
+_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface,
+					       cairo_surface_t *target);
+cairo_private cairo_status_t
+_cairo_meta_surface_replay_region (cairo_surface_t          *surface,
+				   cairo_surface_t          *target,
+				   cairo_meta_region_type_t  region);
+
 cairo_private cairo_bool_t
 _cairo_surface_is_meta (const cairo_surface_t *surface);
 
 #endif /* CAIRO_META_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c
+++ b/gfx/cairo/cairo/src/cairo-meta-surface.c
@@ -1,11 +1,12 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
  *
  * 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.
@@ -27,16 +28,17 @@
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
+ *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 /* A meta surface is a surface that records all drawing operations at
  * the highest level of the surface backend interface, (that is, the
  * level of paint, mask, stroke, fill, and show_glyphs). The meta
  * surface can then be "replayed" against any target surface with:
  *
  *	_cairo_meta_surface_replay (meta, target);
@@ -52,16 +54,22 @@
  * various objects. For example, it would be nice to have a
  * copy-on-write implementation for _cairo_surface_snapshot.
  */
 
 #include "cairoint.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-clip-private.h"
 
+typedef enum {
+    CAIRO_META_REPLAY,
+    CAIRO_META_CREATE_REGIONS,
+    CAIRO_META_ANALYZE_META_PATTERN
+} cairo_meta_replay_type_t;
+
 static const cairo_surface_backend_t cairo_meta_surface_backend;
 
 /* Currently all meta surfaces do have a size which should be passed
  * in as the maximum size of any target surface against which the
  * meta-surface will ever be replayed.
  *
  * XXX: The naming of "pixels" in the size here is a misnomer. It's
  * actually a size in whatever device-space units are desired (again,
@@ -118,17 +126,17 @@ static cairo_status_t
 	cairo_surface_destroy (meta->commands_owner);
 	return CAIRO_STATUS_SUCCESS;
     }
 
     num_elements = meta->commands.num_elements;
     elements = _cairo_array_index (&meta->commands, 0);
     for (i = 0; i < num_elements; i++) {
 	command = elements[i];
-	switch (command->type) {
+	switch (command->header.type) {
 
 	/* 5 basic drawing operations */
 
 	case CAIRO_COMMAND_PAINT:
 	    _cairo_pattern_fini (&command->paint.source.base);
 	    free (command);
 	    break;
 
@@ -179,19 +187,19 @@ static cairo_status_t
 _cairo_meta_surface_acquire_source_image (void			 *abstract_surface,
 					  cairo_image_surface_t	**image_out,
 					  void			**image_extra)
 {
     cairo_status_t status;
     cairo_meta_surface_t *surface = abstract_surface;
     cairo_surface_t *image;
 
-    image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-					surface->width_pixels,
-					surface->height_pixels);
+    image = _cairo_image_surface_create_with_content (surface->content,
+						      surface->width_pixels,
+						      surface->height_pixels);
 
     status = _cairo_meta_surface_replay (&surface->base, image);
     if (status) {
 	cairo_surface_destroy (image);
 	return status;
     }
 
     *image_out = (cairo_image_surface_t *) image;
@@ -238,37 +246,38 @@ static cairo_int_status_t
 _cairo_meta_surface_paint (void			*abstract_surface,
 			   cairo_operator_t	 op,
 			   cairo_pattern_t	*source)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_paint_t *command;
 
-    /* An optimisation that takes care to not replay what was done
-     * before surface is cleared. We don't erase recorded commands
-     * since we may have earlier snapshots of this surface. */
-    if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
-	meta->replay_start_idx = meta->commands.num_elements;
-
     command = malloc (sizeof (cairo_command_paint_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_PAINT;
+    command->header.type = CAIRO_COMMAND_PAINT;
+    command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_array_append (&meta->commands, &command);
     if (status)
 	goto CLEANUP_SOURCE;
 
+    /* An optimisation that takes care to not replay what was done
+     * before surface is cleared. We don't erase recorded commands
+     * since we may have earlier snapshots of this surface. */
+    if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
+	meta->replay_start_idx = meta->commands.num_elements;
+
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_SOURCE:
     _cairo_pattern_fini (&command->source.base);
   CLEANUP_COMMAND:
     free (command);
     return status;
 }
@@ -282,17 +291,18 @@ static cairo_int_status_t
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_mask_t *command;
 
     command = malloc (sizeof (cairo_command_mask_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_MASK;
+    command->header.type = CAIRO_COMMAND_MASK;
+    command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _init_pattern_with_snapshot (&command->mask.base, mask);
     if (status)
@@ -327,17 +337,18 @@ static cairo_int_status_t
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_stroke_t *command;
 
     command = malloc (sizeof (cairo_command_stroke_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_STROKE;
+    command->header.type = CAIRO_COMMAND_STROKE;
+    command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_path_fixed_init_copy (&command->path, path);
     if (status)
@@ -381,17 +392,18 @@ static cairo_int_status_t
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_fill_t *command;
 
     command = malloc (sizeof (cairo_command_fill_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_FILL;
+    command->header.type = CAIRO_COMMAND_FILL;
+    command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_path_fixed_init_copy (&command->path, path);
     if (status)
@@ -427,17 +439,18 @@ static cairo_int_status_t
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_show_glyphs_t *command;
 
     command = malloc (sizeof (cairo_command_show_glyphs_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_SHOW_GLYPHS;
+    command->header.type = CAIRO_COMMAND_SHOW_GLYPHS;
+    command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
     if (command->glyphs == NULL) {
@@ -516,17 +529,18 @@ static cairo_int_status_t
     cairo_meta_surface_t *meta = dst;
     cairo_command_intersect_clip_path_t *command;
     cairo_status_t status;
 
     command = malloc (sizeof (cairo_command_intersect_clip_path_t));
     if (command == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    command->type = CAIRO_COMMAND_INTERSECT_CLIP_PATH;
+    command->header.type = CAIRO_COMMAND_INTERSECT_CLIP_PATH;
+    command->header.region = CAIRO_META_REGION_ALL;
 
     if (path) {
 	status = _cairo_path_fixed_init_copy (&command->path, path);
 	if (status) {
 	    free (command);
 	    return status;
 	}
 	command->path_pointer = &command->path;
@@ -617,36 +631,38 @@ static const cairo_surface_backend_t cai
     _cairo_meta_surface_show_glyphs,
 
     _cairo_meta_surface_snapshot
 };
 
 static cairo_path_fixed_t *
 _cairo_command_get_path (cairo_command_t *command)
 {
-    switch (command->type) {
+    switch (command->header.type) {
     case CAIRO_COMMAND_PAINT:
     case CAIRO_COMMAND_MASK:
     case CAIRO_COMMAND_SHOW_GLYPHS:
 	return NULL;
     case CAIRO_COMMAND_STROKE:
 	return &command->stroke.path;
     case CAIRO_COMMAND_FILL:
 	return &command->fill.path;
     case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	return command->intersect_clip_path.path_pointer;
     }
 
     ASSERT_NOT_REACHED;
     return NULL;
 }
 
-cairo_status_t
-_cairo_meta_surface_replay (cairo_surface_t *surface,
-			    cairo_surface_t *target)
+static cairo_status_t
+_cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
+				     cairo_surface_t	     *target,
+				     cairo_meta_replay_type_t type,
+				     cairo_meta_region_type_t region)
 {
     cairo_meta_surface_t *meta;
     cairo_command_t *command, **elements;
     int i, num_elements;
     cairo_int_status_t status;
     cairo_clip_t clip;
     cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
     cairo_matrix_t *device_transform = &target->device_transform;
@@ -660,34 +676,39 @@ cairo_status_t
 
     _cairo_clip_init (&clip, target);
 
     num_elements = meta->commands.num_elements;
     elements = _cairo_array_index (&meta->commands, 0);
     for (i = meta->replay_start_idx; i < num_elements; i++) {
 	command = elements[i];
 
+	if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) {
+	    if (command->header.region != region)
+		continue;
+        }
+
 	/* For all commands except intersect_clip_path, we have to
 	 * ensure the current clip gets set on the surface. */
-	if (command->type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
+	if (command->header.type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
 	    status = _cairo_surface_set_clip (target, &clip);
 	    if (status)
 		break;
 	}
 
 	dev_path = _cairo_command_get_path (command);
 	if (dev_path && has_device_transform) {
 	    status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
 	    if (status)
 		break;
 	    _cairo_path_fixed_device_transform (&path_copy, device_transform);
 	    dev_path = &path_copy;
 	}
 
-	switch (command->type) {
+	switch (command->header.type) {
 	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_paint (target,
 					   command->paint.op,
 					   &command->paint.source.base);
 	    break;
 	case CAIRO_COMMAND_MASK:
 	    status = _cairo_surface_mask (target,
 					  command->mask.op,
@@ -715,24 +736,64 @@ cairo_status_t
 					    &command->stroke.style,
 					    &dev_ctm,
 					    &dev_ctm_inverse,
 					    command->stroke.tolerance,
 					    command->stroke.antialias);
 	    break;
 	}
 	case CAIRO_COMMAND_FILL:
-	    status = _cairo_surface_fill (target,
-					  command->fill.op,
-					  &command->fill.source.base,
-					  dev_path,
-					  command->fill.fill_rule,
-					  command->fill.tolerance,
-					  command->fill.antialias);
+	{
+	    cairo_command_t *stroke_command;
+
+	    stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
+
+	    if (stroke_command != NULL &&
+		stroke_command->header.type == CAIRO_COMMAND_STROKE &&
+		_cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) {
+		cairo_matrix_t dev_ctm;
+		cairo_matrix_t dev_ctm_inverse;
+		cairo_matrix_t tmp;
+
+		dev_ctm = stroke_command->stroke.ctm;
+		dev_ctm_inverse = stroke_command->stroke.ctm_inverse;
+
+		if (has_device_transform) {
+		    cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
+		    tmp = surface->device_transform;
+		    status = cairo_matrix_invert (&tmp);
+		    assert (status == CAIRO_STATUS_SUCCESS);
+		    cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse);
+		}
+
+		status = _cairo_surface_fill_stroke (target,
+						     command->fill.op,
+						     &command->fill.source.base,
+						     command->fill.fill_rule,
+						     command->fill.tolerance,
+						     command->fill.antialias,
+						     dev_path,
+						     stroke_command->stroke.op,
+						     &stroke_command->stroke.source.base,
+						     &stroke_command->stroke.style,
+						     &dev_ctm,
+						     &dev_ctm_inverse,
+						     stroke_command->stroke.tolerance,
+						     stroke_command->stroke.antialias);
+		i++;
+	    } else
+		status = _cairo_surface_fill (target,
+					      command->fill.op,
+					      &command->fill.source.base,
+					      dev_path,
+					      command->fill.fill_rule,
+					      command->fill.tolerance,
+					      command->fill.antialias);
 	    break;
+	}
 	case CAIRO_COMMAND_SHOW_GLYPHS:
 	{
 	    cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
 	    cairo_glyph_t *dev_glyphs = glyphs;
 	    int i, num_glyphs = command->show_glyphs.num_glyphs;
 
 	    if (has_device_transform) {
 		dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
@@ -765,24 +826,86 @@ cairo_status_t
 	    if (dev_path == NULL)
 		_cairo_clip_reset (&clip);
 	    else
 		status = _cairo_clip_clip (&clip, dev_path,
 					   command->intersect_clip_path.fill_rule,
 					   command->intersect_clip_path.tolerance,
 					   command->intersect_clip_path.antialias,
 					   target);
+            assert (status == 0);
 	    break;
 	default:
 	    ASSERT_NOT_REACHED;
 	}
 
 	if (dev_path == &path_copy)
 	    _cairo_path_fixed_fini (&path_copy);
 
+	if (type == CAIRO_META_CREATE_REGIONS) {
+	    if (status == CAIRO_STATUS_SUCCESS) {
+		command->header.region = CAIRO_META_REGION_NATIVE;
+	    } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
+		command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK;
+		status = CAIRO_STATUS_SUCCESS;
+	    }
+	}
+
+	if (type == CAIRO_META_ANALYZE_META_PATTERN) {
+	    if (status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
+		status = CAIRO_STATUS_SUCCESS;
+	}
+
 	if (status)
 	    break;
     }
 
     _cairo_clip_reset (&clip);
 
     return status;
 }
+
+cairo_status_t
+_cairo_meta_surface_replay (cairo_surface_t *surface,
+			    cairo_surface_t *target)
+{
+    return _cairo_meta_surface_replay_internal (surface,
+						target,
+						CAIRO_META_REPLAY,
+						CAIRO_META_REGION_ALL);
+}
+
+cairo_status_t
+_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
+						 cairo_surface_t *target)
+{
+    return _cairo_meta_surface_replay_internal (surface,
+						target,
+						CAIRO_META_ANALYZE_META_PATTERN,
+						CAIRO_META_REGION_ALL);
+}
+
+/* Replay meta to surface. When the return status of each operation is
+ * one of CAIRO_STATUS_SUCCESS, CAIRO_INT_STATUS_UNSUPPORTED, or
+ * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
+ * will be stored in the meta surface. Any other status will abort the
+ * replay and return the status.
+ */
+cairo_status_t
+_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface,
+					       cairo_surface_t *target)
+{
+    return _cairo_meta_surface_replay_internal (surface,
+						target,
+						CAIRO_META_CREATE_REGIONS,
+						CAIRO_META_REGION_ALL);
+}
+
+cairo_status_t
+_cairo_meta_surface_replay_region (cairo_surface_t          *surface,
+				   cairo_surface_t          *target,
+				   cairo_meta_region_type_t  region)
+{
+    return _cairo_meta_surface_replay_internal (surface,
+						target,
+						CAIRO_META_REPLAY,
+						region);
+}
--- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h
@@ -44,19 +44,16 @@
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <cairo-features.h>
 
 CAIRO_BEGIN_DECLS
 
-#ifndef MOZILLA_CAIRO_NOT_DEFINED
-#define CAIRO_NO_MUTEX 1
-#endif
 
 /* A fully qualified no-operation statement */
 #define CAIRO_MUTEX_NOOP	do {/*no-op*/} while (0)
 /* And one that evaluates it's argument once */
 #define CAIRO_MUTEX_NOOP1(expr)        do { if (expr) ; } while (0)
 
 
 /* Cairo mutex implementation:
@@ -139,34 +136,23 @@ CAIRO_BEGIN_DECLS
  * - That is all.  If for any reason you think the above API is
  *   not enough to implement cairo_mutex_t on your system, please
  *   stop and write to the cairo mailing list about it.  DO NOT
  *   poke around cairo-mutex-private.h for possible solutions.
  */
 
 #if CAIRO_NO_MUTEX
 
-/* No mutex at all */
+/* No mutexes */
 
   typedef int cairo_mutex_t;
 
 # define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_NIL_INITIALIZER 0
-
-#elif CAIRO_POOR_MAN_MUTEX
-
-/* A poor man's mutex */
-
-  typedef int cairo_mutex_t;
-
-# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_LOCK(mutex) do { while (mutex) ; (mutex) = 1; } while (0)
-# define CAIRO_MUTEX_UNLOCK(mutex) (mutex) = 0
+# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
+# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
 # define CAIRO_MUTEX_NIL_INITIALIZER 0
 
 #elif HAVE_PTHREAD_H /*******************************************************/
 
 # include <pthread.h>
 
   typedef pthread_mutex_t cairo_mutex_t;
 
--- a/gfx/cairo/cairo/src/cairo-os2-private.h
+++ b/gfx/cairo/cairo/src/cairo-os2-private.h
@@ -45,17 +45,17 @@
 #define INCL_GPI
 #ifdef __WATCOMC__
 # include <os2.h>
 #else
 # include <os2emx.h>
 #endif
 
 #include <cairo-os2.h>
-#include <cairoint.h>
+#include "cairoint.h"
 
 typedef struct _cairo_os2_surface
 {
     cairo_surface_t        base;
 
     /* Mutex semaphore to protect private fields from concurrent access */
     HMTX                   hmtx_use_private_fields;
     /* Private fields: */
--- a/gfx/cairo/cairo/src/cairo-paginated-private.h
+++ b/gfx/cairo/cairo/src/cairo-paginated-private.h
@@ -128,9 +128,14 @@ cairo_private cairo_surface_t *
 				 const cairo_paginated_surface_backend_t	*backend);
 
 cairo_private cairo_surface_t *
 _cairo_paginated_surface_get_target (cairo_surface_t *surface);
 
 cairo_private cairo_bool_t
 _cairo_surface_is_paginated (cairo_surface_t *surface);
 
+cairo_private cairo_status_t
+_cairo_paginated_surface_set_size (cairo_surface_t 	*surface,
+				   int			 width,
+				   int			 height);
+
 #endif /* CAIRO_PAGINATED_H */
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -1,11 +1,12 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
  *
  * 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.
@@ -27,16 +28,17 @@
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Contributor(s):
  *	Carl Worth <cworth@cworth.org>
  *	Keith Packard <keithp@keithp.com>
+ *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 /* The paginated surface layer exists to provide as much code sharing
  * as possible for the various paginated surface backends in cairo
  * (PostScript, PDF, etc.). See cairo-paginated-private.h for
  * more details on how it works and how to use it.
  */
 
@@ -58,16 +60,17 @@ static cairo_surface_t *
 					 int			 width,
 					 int			 height)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
     return cairo_surface_create_similar (surface->target, content,
 					 width, height);
 }
 
+/* XXX The integer width,height here should be doubles and all uses updated */
 cairo_surface_t *
 _cairo_paginated_surface_create (cairo_surface_t				*target,
 				 cairo_content_t				 content,
 				 int						 width,
 				 int						 height,
 				 const cairo_paginated_surface_backend_t	*backend)
 {
     cairo_paginated_surface_t *surface;
@@ -120,16 +123,39 @@ cairo_surface_t *
 
     assert (_cairo_surface_is_paginated (surface));
 
     paginated_surface = (cairo_paginated_surface_t *) surface;
 
     return paginated_surface->target;
 }
 
+cairo_status_t
+_cairo_paginated_surface_set_size (cairo_surface_t 	*surface,
+				   int			 width,
+				   int			 height)
+{
+    cairo_paginated_surface_t *paginated_surface;
+
+    assert (_cairo_surface_is_paginated (surface));
+
+    paginated_surface = (cairo_paginated_surface_t *) surface;
+
+    paginated_surface->width = width;
+    paginated_surface->height = height;
+
+    cairo_surface_destroy (paginated_surface->meta);
+    paginated_surface->meta = _cairo_meta_surface_create (paginated_surface->content,
+							  width, height);
+    if (cairo_surface_status (paginated_surface->meta))
+	return cairo_surface_status (paginated_surface->meta);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 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);
@@ -204,68 +230,152 @@ static void
 _cairo_paginated_surface_release_source_image (void	  *abstract_surface,
 					       cairo_image_surface_t *image,
 					       void	       *image_extra)
 {
     cairo_surface_destroy (&image->base);
 }
 
 static cairo_int_status_t
+_paint_fallback_image (cairo_paginated_surface_t *surface,
+		       cairo_box_int_t           *box)
+{
+    double x_scale = surface->base.x_fallback_resolution / surface->base.x_resolution;
+    double y_scale = surface->base.y_fallback_resolution / surface->base.y_resolution;
+    cairo_matrix_t matrix;
+    int x, y, width, height;
+    cairo_status_t status;
+    cairo_surface_t *image;
+    cairo_pattern_t *pattern;
+
+    x = box->p1.x;
+    y = box->p1.y;
+    width = box->p2.x - x;
+    height = box->p2.y - y;
+    image = _cairo_paginated_surface_create_image_surface (surface,
+							   width  * x_scale,
+							   height * y_scale);
+    _cairo_surface_set_device_scale (image, x_scale, y_scale);
+    /* set_device_offset just sets the x0/y0 components of the matrix;
+     * so we have to do the scaling manually. */
+    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
+
+    status = _cairo_meta_surface_replay (surface->meta, image);
+    if (status)
+	goto CLEANUP_IMAGE;
+
+    pattern = cairo_pattern_create_for_surface (image);
+    cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
+    cairo_pattern_set_matrix (pattern, &matrix);
+
+    status = _cairo_surface_paint (surface->target,
+				   CAIRO_OPERATOR_SOURCE,
+				   pattern);
+
+    cairo_pattern_destroy (pattern);
+CLEANUP_IMAGE:
+    cairo_surface_destroy (image);
+
+    return status;
+}
+
+static cairo_int_status_t
 _paint_page (cairo_paginated_surface_t *surface)
 {
     cairo_surface_t *analysis;
-    cairo_surface_t *image;
-    cairo_pattern_t *pattern;
     cairo_status_t status;
+    cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;
 
     analysis = _cairo_analysis_surface_create (surface->target,
 					       surface->width, surface->height);
     if (analysis == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
     surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
-    status = _cairo_meta_surface_replay (surface->meta, analysis);
+    status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
     surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
 
     if (status || analysis->status) {
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = analysis->status;
 	cairo_surface_destroy (analysis);
 	return status;
     }
 
-    if (_cairo_analysis_surface_has_unsupported (analysis))
-    {
-	double x_scale = surface->base.x_fallback_resolution / 72.0;
-	double y_scale = surface->base.y_fallback_resolution / 72.0;
-	cairo_matrix_t matrix;
+    /* Finer grained fallbacks are currently only supported for some
+     * surface types */
+    switch (surface->target->type) {
+        case CAIRO_SURFACE_TYPE_PDF:
+        case CAIRO_SURFACE_TYPE_PS:
+        case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
+            has_supported = _cairo_analysis_surface_has_supported (analysis);
+            has_page_fallback = FALSE;
+            has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
+            break;
 
-	image = _cairo_paginated_surface_create_image_surface (surface,
-							       surface->width  * x_scale,
-							       surface->height * y_scale);
-	_cairo_surface_set_device_scale (image, x_scale, y_scale);
+        default:
+            if (_cairo_analysis_surface_has_unsupported (analysis)) {
+                has_supported = FALSE;
+                has_page_fallback = TRUE;
+            } else {
+                has_supported = TRUE;
+                has_page_fallback = FALSE;
+            }
+            has_finegrained_fallback = FALSE;
+            break;
+    }
 
-	status = _cairo_meta_surface_replay (surface->meta, image);
+    if (has_supported) {
+	status = _cairo_meta_surface_replay_region (surface->meta,
+						    surface->target,
+						    CAIRO_META_REGION_NATIVE);
 	if (status)
-	    goto CLEANUP_IMAGE;
+	    return status;
+    }
+
+    if (has_page_fallback)
+    {
+	cairo_box_int_t box;
 
-	pattern = cairo_pattern_create_for_surface (image);
-	cairo_matrix_init_scale (&matrix, x_scale, y_scale);
-	cairo_pattern_set_matrix (pattern, &matrix);
+	box.p1.x = 0;
+	box.p1.y = 0;
+	box.p2.x = surface->width;
+	box.p2.y = surface->height;
+	status = _paint_fallback_image (surface, &box);
+	if (status)
+	    return status;
+    }
 
-	status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
+    if (has_finegrained_fallback)
+    {
+        cairo_region_t *region;
+        cairo_box_int_t *boxes;
+        int num_boxes, i;
 
-	cairo_pattern_destroy (pattern);
+	/* Reset clip region before drawing the fall back images */
+	status = _cairo_surface_intersect_clip_path (surface->target,
+						     NULL,
+						     CAIRO_FILL_RULE_WINDING,
+						     CAIRO_GSTATE_TOLERANCE_DEFAULT,
+						     CAIRO_ANTIALIAS_DEFAULT);
+	if (status)
+	    return status;
 
-     CLEANUP_IMAGE:
-	cairo_surface_destroy (image);
-    }
-    else
-    {
-	status = _cairo_meta_surface_replay (surface->meta, surface->target);
+	region = _cairo_analysis_surface_get_unsupported (analysis);
+	status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
+	if (status)
+	    return status;
+	for (i = 0; i < num_boxes; i++) {
+	    status = _paint_fallback_image (surface, &boxes[i]);
+	    if (status) {
+                _cairo_region_boxes_fini (region, boxes);
+		return status;
+            }
+	}
+        _cairo_region_boxes_fini (region, boxes);
     }
 
     cairo_surface_destroy (analysis);
 
     return status;
 }
 
 static cairo_status_t
@@ -289,41 +399,40 @@ static cairo_int_status_t
 
     status = _paint_page (surface);
     if (status)
 	return status;
 
     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
+     * cairo_surface_copy_page on the target surface. It would be an
+     * optimization for the output, 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. */
 
-    return _cairo_surface_show_page (surface->target);
+    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;
 
     status = _start_page (surface);
     if (status)
 	return status;
 
     status = _paint_page (surface);
     if (status)
 	return status;
 
-    status = _cairo_surface_show_page (surface->target);
+    status = cairo_surface_show_page (surface->target);
     if (status)
 	return status;
 
     if (cairo_surface_status (surface->meta))
 	return cairo_surface_status (surface->meta);
 
     cairo_surface_destroy (surface->meta);
 
--- a/gfx/cairo/cairo/src/cairo-path-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-path-fixed-private.h
@@ -31,23 +31,24 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@redhat.com>
  */
 
 #ifndef CAIRO_PATH_FIXED_PRIVATE_H
 #define CAIRO_PATH_FIXED_PRIVATE_H
 
-typedef enum cairo_path_op {
+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? */
+};
+/* we want to make sure a single byte is used for thie enum */
+typedef char cairo_path_op_t;
 
 /* 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_buf {
     struct _cairo_path_buf *next, *prev;
     int num_ops;
--- a/gfx/cairo/cairo/src/cairo-path-fixed.c
+++ b/gfx/cairo/cairo/src/cairo-path-fixed.c
@@ -508,27 +508,23 @@ static void
 				    cairo_fixed_t scalex,
 				    cairo_fixed_t scaley)
 {
     cairo_path_buf_t *buf = path->buf_head;
     int i;
 
     while (buf) {
 	 for (i = 0; i < buf->num_points; i++) {
-	     if (scalex == CAIRO_FIXED_ONE) {
-		 buf->points[i].x += offx;
-	     } else {
-		 buf->points[i].x = _cairo_fixed_mul (buf->points[i].x + offx, scalex);
-	     }
+	     if (scalex != CAIRO_FIXED_ONE)
+		 buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex);
+	     buf->points[i].x += offx;
 
-	     if (scaley == CAIRO_FIXED_ONE) {
-		 buf->points[i].y += offy;
-	     } else {
-		 buf->points[i].y = _cairo_fixed_mul (buf->points[i].y + offy, scaley);
-	     }
+	     if (scaley != CAIRO_FIXED_ONE)
+		 buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley);
+	     buf->points[i].y += offy;
 	 }
 
 	 buf = buf->next;
     }
 }
 
 
 /**
@@ -541,18 +537,43 @@ static void
  * given matrix has no rotation or shear elements, (that is, xy and yx
  * are 0.0).
  **/
 void
 _cairo_path_fixed_device_transform (cairo_path_fixed_t	*path,
 				    cairo_matrix_t	*device_transform)
 {
     assert (device_transform->yx == 0.0 && device_transform->xy == 0.0);
-    /* XXX: FRAGILE: I'm not really sure whether we're doing the
-     * "right" thing here if there is both scaling and translation in
-     * the matrix. But for now, the internals guarantee that we won't
-     * really ever have both going on. */
+    /* XXX: Support freeform matrices someday (right now, only translation and scale
+     * work. */
     _cairo_path_fixed_offset_and_scale (path,
 					_cairo_fixed_from_double (device_transform->x0),
 					_cairo_fixed_from_double (device_transform->y0),
 					_cairo_fixed_from_double (device_transform->xx),
 					_cairo_fixed_from_double (device_transform->yy));
 }
+
+cairo_bool_t
+_cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
+			    cairo_path_fixed_t *other)
+{
+    cairo_path_buf_t *path_buf, *other_buf;
+
+    if (path->current_point.x != other->current_point.x ||
+	path->current_point.y != other->current_point.y ||
+	path->has_current_point != other->has_current_point ||
+	path->has_curve_to != other->has_curve_to ||
+	path->last_move_point.x != other->last_move_point.x ||
+	path->last_move_point.y != other->last_move_point.y)
+	return FALSE;
+
+    other_buf = other->buf_head;
+    for (path_buf = path->buf_head; path_buf != NULL; path_buf = path_buf->next) {
+	if (other_buf == NULL ||
+	    path_buf->num_ops != other_buf->num_ops ||
+	    path_buf->num_points != other_buf->num_points ||
+	    memcmp (path_buf->op, other_buf->op, path_buf->num_ops) != 0 ||
+	    memcmp (path_buf->points, other_buf->points, path_buf->num_points != 0))
+	    return FALSE;
+	other_buf = other_buf->next;
+    }
+    return TRUE;
+}
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -232,31 +232,23 @@ static cairo_status_t
     case CAIRO_LINE_JOIN_ROUND: {
 	int i;
 	int start, step, stop;
 	cairo_point_t tri[3];
 	cairo_pen_t *pen = &stroker->pen;
 
 	tri[0] = in->point;
 	if (clockwise) {
-	    status = _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
-	    if (status)
-		return status;
+	    _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
 	    step = -1;
-	    status = _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
-	    if (status)
-		return status;
+	    _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
 	} else {
-	    status = _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
-	    if (status)
-		return status;
+	    _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
 	    step = +1;
-	    status = _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
-	    if (status)
-		return status;
+	    _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
 	}
 
 	i = start;
 	tri[1] = *inpt;
 	while (i != stop) {
 	    tri[2] = in->point;
 	    _translate_point (&tri[2], &pen->vertices[i].point);
 	    status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
@@ -389,24 +381,20 @@ static cairo_status_t
     case CAIRO_LINE_CAP_ROUND: {
 	int i;
 	int start, stop;
 	cairo_slope_t slope;
 	cairo_point_t tri[3];
 	cairo_pen_t *pen = &stroker->pen;
 
 	slope = f->dev_vector;
-	status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
-	if (status)
-	    return status;
+	_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
 	slope.dx = -slope.dx;
 	slope.dy = -slope.dy;
-	status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
-	if (status)
-	    return status;
+	_cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
 
 	tri[0] = f->point;
 	tri[1] = f->cw;
 	for (i=start; i != stop; i = (i+1) % pen->num_vertices) {
 	    tri[2] = f->point;
 	    _translate_point (&tri[2], &pen->vertices[i].point);
 	    status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
 	    if (status)
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -180,17 +180,19 @@ cairo_status_t
 
 	status = _cairo_gradient_pattern_init_copy (dst, src);
 	if (status)
 	    return status;
 
     } break;
     }
 
+    /* The reference count and user_data array are unique to the copy. */
     pattern->ref_count = 1;
+    _cairo_user_data_array_init (&pattern->user_data);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_pattern_fini (cairo_pattern_t *pattern)
 {
     _cairo_user_data_array_fini (&pattern->user_data);
@@ -1205,17 +1207,17 @@ static cairo_int_status_t
 
     if (pixman_image == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
     if (_cairo_surface_is_image (dst))
     {
 	image = (cairo_image_surface_t *)
 	    _cairo_image_surface_create_for_pixman_image (pixman_image,
-							  CAIRO_FORMAT_ARGB32);
+							  PIXMAN_a8r8g8b8);
 	if (image->base.status)
 	{
 	    pixman_image_unref (pixman_image);
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
 
 	attr->x_offset = attr->y_offset = 0;
 	attr->matrix = pattern->base.matrix;
@@ -1670,48 +1672,16 @@ static cairo_int_status_t
 		height = MIN (extents.height, ceil (y2) + 1) - 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);
-	    status = cairo_surface_status (*out);
-	    if (status) {
-		cairo_surface_destroy (*out);
-		*out = NULL;
-		return status;
-	    }
-
-	    (*out)->device_transform = pattern->surface->device_transform;
-	    (*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
-
-	    /* XXX Use _cairo_surface_composite directly */
-	    cr = cairo_create (*out);
-
-	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-	    cairo_set_source_surface (cr, pattern->surface, -x, -y);
-	    cairo_paint (cr);
-
-	    status = cairo_status (cr);
-	    cairo_destroy (cr);
-
-	    if (status) {
-		cairo_surface_destroy (*out);
-		*out = NULL;
-	    }
-	}
     }
 
     return status;
 }
 
 /**
  * _cairo_pattern_acquire_surface:
  * @pattern: a #cairo_pattern_t
@@ -1972,18 +1942,18 @@ cairo_status_t
 	cairo_bool_t set = FALSE;
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
 	if (status)
 	    return status;
 
 	imatrix = pattern->matrix;
 	status = cairo_matrix_invert (&imatrix);
-	if (status)
-	    return status;
+	/* cairo_pattern_set_matrix ensures the matrix is invertible */
+	assert (status == CAIRO_STATUS_SUCCESS);
 
 	/* 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;
--- a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h
@@ -1,12 +1,13 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Red Hat, Inc
  * Copyright © 2006 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
  *
  * 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.
@@ -29,77 +30,102 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
+ *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_PDF_SURFACE_PRIVATE_H
 #define CAIRO_PDF_SURFACE_PRIVATE_H
 
 #include "cairo-pdf.h"
 
 #include "cairo-surface-private.h"
 
 typedef struct _cairo_pdf_resource {
     unsigned int id;
 } cairo_pdf_resource_t;
 
+typedef struct _cairo_pdf_group_resources {
+    cairo_array_t alphas;
+    cairo_array_t smasks;
+    cairo_array_t patterns;
+    cairo_array_t xobjects;
+    cairo_array_t fonts;
+} cairo_pdf_group_resources_t;
+
 typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
 
 struct _cairo_pdf_surface {
     cairo_surface_t base;
 
     /* Prefer the name "output" here to avoid confusion over the
      * structure within a PDF document known as a "stream". */
     cairo_output_stream_t *output;
 
     double width;
     double height;
     cairo_matrix_t cairo_to_pdf;
 
     cairo_array_t objects;
     cairo_array_t pages;
-    cairo_array_t patterns;
-    cairo_array_t xobjects;
-    cairo_array_t streams;
-    cairo_array_t alphas;
-    cairo_array_t smasks;
     cairo_array_t rgb_linear_functions;
     cairo_array_t alpha_linear_functions;
+    cairo_array_t knockout_group;
+    cairo_array_t content_group;
 
     cairo_scaled_font_subsets_t *font_subsets;
     cairo_array_t fonts;
 
     cairo_pdf_resource_t next_available_resource;
     cairo_pdf_resource_t pages_resource;
 
     struct {
 	cairo_bool_t active;
 	cairo_pdf_resource_t self;
 	cairo_pdf_resource_t length;
 	long start_offset;
-        cairo_bool_t compressed;
-        cairo_output_stream_t *old_output;
-    } current_stream;
+	cairo_bool_t compressed;
+	cairo_output_stream_t *old_output;
+    } pdf_stream;
+
+    struct {
+	cairo_bool_t active;
+	cairo_output_stream_t *stream;
+	cairo_output_stream_t *old_output;
+	cairo_pdf_group_resources_t resources;
+	cairo_bool_t is_knockout;
+	cairo_pdf_resource_t first_object;
+    } group_stream;
 
     struct {
-        cairo_pattern_type_t type;
-        double red;
-        double green;
-        double blue;
-        int alpha;
-        cairo_pdf_resource_t smask;
-        cairo_pdf_resource_t pattern;
+	cairo_bool_t active;
+	cairo_output_stream_t *stream;
+	cairo_output_stream_t *old_output;
+	cairo_pdf_group_resources_t resources;
+    } content_stream;
+
+    struct {
+	cairo_pattern_type_t type;
+	double red;
+	double green;
+	double blue;
+	double alpha;
+	cairo_pdf_resource_t smask;
+	cairo_pdf_resource_t pattern;
     } emitted_pattern;
 
-    cairo_bool_t has_clip;
+    cairo_array_t *current_group;
+    cairo_pdf_group_resources_t *current_resources;
 
     cairo_paginated_mode_t paginated_mode;
 
     cairo_bool_t force_fallbacks;
+
+    cairo_surface_t *paginated_surface;
 };
 
 #endif /* CAIRO_PDF_SURFACE_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-pdf-surface.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c
@@ -1,12 +1,13 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Red Hat, Inc
  * Copyright © 2006 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
  *
  * 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.
@@ -29,67 +30,162 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
+ *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
 #include "cairo-pdf.h"
 #include "cairo-pdf-surface-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-path-fixed-private.h"
 #include "cairo-output-stream-private.h"
+#include "cairo-meta-surface-private.h"
 
 #include <time.h>
 #include <zlib.h>
 
 /* Issues:
  *
- * - Why doesn't pages inherit /alpha%d GS dictionaries from the Pages
- *   object?
- *
  * - We embed an image in the stream each time it's composited.  We
  *   could add generation counters to surfaces and remember the stream
  *   ID for a particular generation for a particular surface.
  *
- * - Clipping: must be able to reset clipping
- *
  * - Images of other formats than 8 bit RGBA.
  *
  * - Backend specific meta data.
  *
  * - Surface patterns.
  *
  * - Should/does cairo support drawing into a scratch surface and then
  *   using that as a fill pattern?  For this backend, that would involve
  *   using a tiling pattern (4.6.2).  How do you create such a scratch
  *   surface?  cairo_surface_create_similar() ?
  *
  * - What if you create a similar surface and does show_page and then
  *   does show_surface on another surface?
  *
- * - Output TM so page scales to the right size - PDF default user
- *   space has 1 unit = 1 / 72 inch.
- *
  * - Add test case for RGBA images.
  *
  * - Add test case for RGBA gradients.
  *
  * - Coordinate space for create_similar() args?
+ */
+
+/*
+ * Page Structure of the Generated PDF:
  *
- * - Investigate /Matrix entry in content stream dicts for pages
- *   instead of outputting the cm operator in every page.
+ * Each page requiring fallbacks images contains a knockout group at
+ * the top level. The first operation of the knockout group paints a
+ * group containing all the supported drawing operations. Fallback
+ * images (if any) are painted in the knockout group. This ensures
+ * that fallback images do not composite with any content under the
+ * fallback images.
+ *
+ * The group containing the supported operations (content_group_list
+ * in the example below) does not do any drawing directly. Instead it
+ * paints groups containing the drawing operations and performs
+ * clipping. The reason for this is that clipping operations performed
+ * in a group do not affect the parent group.
+ *
+ * Example PDF Page Structure:
+ *
+ *   Page Content
+ *   ------------
+ *     /knockout_group Do
+ *
+ *   knockout_group
+ *   --------------
+ *     /content_group_list Do
+ *     /fallback_image_1 Do
+ *     /fallback_image_2 Do
+ *     ...
+ *
+ *   content_group_list
+ *   ------------------
+ *     q
+ *     /content_group_1 Do
+ *     /content_group_2 Do
+ *     10 10 m 10 20 l 20 20 l 20 10 l h W  # clip
+ *     /content_group_3 Do
+ *     Q q                                  # reset clip
+ *     /content_group_4 Do
+ *     Q
+ *
+ *
+ * Streams:
+ *
+ * This PDF surface has three types of streams:
+ *  - PDF Stream
+ *  - Content Stream
+ *  - Group Stream
+ *
+ * Calling _cairo_output_stream_printf (surface->output, ...) will
+ * write to the currently open stream.
+ *
+ * PDF Stream:
+ *   A PDF Stream may be opened and closed with the following functions:
+ *     _cairo_pdf_surface_open_stream ()
+ *     _cairo_pdf_surface_close_stream ()
+ *
+ *   PDF Streams are written directly to the PDF file. They are used for
+ *   fonts, images and patterns.
+ *
+ * Content Stream:
+ *   The Content Stream is opened and closed with the following functions:
+ *     _cairo_pdf_surface_start_content_stream ()
+ *     _cairo_pdf_surface_stop_content_stream ()
+ *
+ *   The Content Stream is written to content_group_n groups (as shown
+ *   in the page structure example). The Content Stream may be paused
+ *   and resumed with the following functions:
+ *     _cairo_pdf_surface_pause_content_stream ()
+ *     _cairo_pdf_surface_resume_content_stream ()
+ *
+ *   When the Content Stream is paused, a PDF Stream or Group Stream
+ *   may be opened. After closing the PDF Stream or Group Stream the
+ *   Content Stream may be resumed.
+ *
+ *   The Content Stream contains the text and graphics operators. When
+ *   a pattern is required the Content Stream is paused, a PDF Stream
+ *   is opened, the pattern is written to a PDF Stream, the PDF Stream
+ *   is closed, then the Content Stream is resumed.
+ *
+ *   Each group comprising the Content Stream is stored in memory
+ *   until the stream is closed or the maximum group size is
+ *   exceeded. This is due to the need to list all resources used in
+ *   the group in the group's stream dictionary.
+ *
+ * Group Stream:
+ *   A Group Stream may be opened and closed with the following functions:
+ *     _cairo_pdf_surface_open_group ()
+ *     _cairo_pdf_surface_close_group ()
+ *
+ *   A Group Stream is written to a separate group in the PDF file
+ *   that is not part of the Content Stream. Group Streams are also
+ *   stored in memory until the stream is closed due to the need to
+ *   list the resources used in the group in the group's stream
+ *   dictionary.
+ *
+ *   Group Streams are used for short sequences of graphics operations
+ *   that need to be in a separate group from the Content Stream.
  */
 
+/* The group stream length is checked after each operation. When this
+ * limit is exceeded the group is written out to the pdf stream and a
+ * new group is created. */
+#define GROUP_STREAM_LIMIT 65536
+
 typedef struct _cairo_pdf_object {
     long offset;
 } cairo_pdf_object_t;
 
 typedef struct _cairo_pdf_font {
     unsigned int font_id;
     unsigned int subset_id;
     cairo_pdf_resource_t subset_resource;
@@ -102,47 +198,70 @@ typedef struct _cairo_pdf_rgb_linear_fun
 } cairo_pdf_rgb_linear_function_t;
 
 typedef struct _cairo_pdf_alpha_linear_function {
     cairo_pdf_resource_t resource;
     double               alpha1;
     double               alpha2;
 } cairo_pdf_alpha_linear_function_t;
 
+typedef enum group_element_type {
+    ELEM_GROUP,
+    ELEM_CLIP
+} group_element_type_t;
+
+typedef struct _cairo_pdf_group_element {
+    group_element_type_t  type;
+    cairo_pdf_resource_t  group;
+    cairo_path_fixed_t   *clip_path;
+    cairo_fill_rule_t     fill_rule;
+} cairo_pdf_group_element_t;
+
+
 static cairo_pdf_resource_t
 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
 
 static void
+_cairo_pdf_group_element_array_finish (cairo_array_t *array);
+
+static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
 
+static void
+_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
+
 static cairo_pdf_resource_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
                                 cairo_bool_t             compressed,
 				const char		*fmt,
 				...) CAIRO_PRINTF_FORMAT(3, 4);
 static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t	*surface);
 
 static cairo_status_t
-_cairo_pdf_surface_add_stream (cairo_pdf_surface_t	*surface,
-			       cairo_pdf_resource_t	 stream);
+_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
 
 static void
 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
 
 static cairo_pdf_resource_t
 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
 
 static cairo_pdf_resource_t
 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
 
 static long
 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
 
 static cairo_status_t
+_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t  *surface,
+			      cairo_path_fixed_t   *path,
+			      cairo_fill_rule_t	    fill_rule);
+
+static cairo_status_t
 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
 
 static cairo_status_t
 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
 
 static const cairo_surface_backend_t cairo_pdf_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
 
@@ -172,70 +291,22 @@ static void
 				  cairo_pdf_resource_t	 resource)
 {
     cairo_pdf_object_t *object;
 
     object = _cairo_array_index (&surface->objects, resource.id - 1);
     object->offset = _cairo_output_stream_get_position (surface->output);
 }
 
-static cairo_status_t
-_cairo_pdf_surface_add_stream (cairo_pdf_surface_t	*surface,
-			       cairo_pdf_resource_t	 stream)
-{
-    return _cairo_array_append (&surface->streams, &stream);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t	*surface,
-				cairo_pdf_resource_t	 pattern)
-{
-    return _cairo_array_append (&surface->patterns, &pattern);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
-                              cairo_pdf_resource_t  smask)
-{
-    return _cairo_array_append (&surface->smasks, &smask);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, double alpha, int *index)
-{
-    int num_alphas, i;
-    double other;
-    cairo_status_t status;
-
-    num_alphas = _cairo_array_num_elements (&surface->alphas);
-    for (i = 0; i < num_alphas; i++) {
-        _cairo_array_copy_element (&surface->alphas, i, &other);
-        if (alpha == other) {
-            *index = i;
-            return CAIRO_STATUS_SUCCESS;
-        }
-    }
-
-    status = _cairo_array_append (&surface->alphas, &alpha);
-    if (status)
-	return status;
-
-    *index = _cairo_array_num_elements (&surface->alphas) - 1;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_surface_t *
 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					       double			 width,
 					       double			 height)
 {
     cairo_pdf_surface_t *surface;
-    cairo_status_t status;
-    int alpha;
 
     surface = malloc (sizeof (cairo_pdf_surface_t));
     if (surface == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
@@ -244,67 +315,63 @@ static cairo_surface_t *
     surface->output = output;
 
     surface->width = width;
     surface->height = height;
     cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
 
     _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));
-    _cairo_array_init (&surface->smasks, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
     _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
-
-
-    /* Add alpha=1 as the first element in the list of alpha values as
-     * this is the most frequently referenced value. */
-    status = _cairo_pdf_surface_add_alpha (surface, 1, &alpha);
-    if (status) {
-	_cairo_error (status);
-        goto fail1;
-    }
+    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
+    _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_group_element_t));
+    _cairo_array_init (&surface->content_group, sizeof (cairo_pdf_group_element_t));
+
+    _cairo_pdf_group_resources_init (&surface->group_stream.resources);
+    _cairo_pdf_group_resources_init (&surface->content_stream.resources);
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
     if (! surface->font_subsets) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-        goto fail2;
+	goto fail;
     }
 
-    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
-
     surface->next_available_resource.id = 1;
     surface->pages_resource = _cairo_pdf_surface_new_object (surface);
 
-    surface->current_stream.active = FALSE;
-
-    surface->has_clip = FALSE;
+    surface->pdf_stream.active = FALSE;
+    surface->content_stream.active = FALSE;
+    surface->content_stream.stream = NULL;
+    surface->group_stream.active = FALSE;
+    surface->group_stream.stream = NULL;
+
+    surface->current_group = NULL;
+    surface->current_resources = NULL;
 
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
 
     surface->force_fallbacks = FALSE;
 
     /* Document header */
     _cairo_output_stream_printf (surface->output,
 				 "%%PDF-1.4\r\n");
     _cairo_output_stream_printf (surface->output,
 				 "%%%c%c%c%c\r\n", 181, 237, 174, 251);
 
-    return _cairo_paginated_surface_create (&surface->base,
-					    CAIRO_CONTENT_COLOR_ALPHA,
-					    width, height,
-					    &cairo_pdf_surface_paginated_backend);
-
-fail1:
+    surface->paginated_surface = _cairo_paginated_surface_create (&surface->base,
+								  CAIRO_CONTENT_COLOR_ALPHA,
+								  width, height,
+								  &cairo_pdf_surface_paginated_backend);
+    return surface->paginated_surface;
+
+fail:
     free (surface);
-fail2:
-	return (cairo_surface_t*) &_cairo_surface_nil;
+
+    return (cairo_surface_t*) &_cairo_surface_nil;
 }
 
 /**
  * cairo_pdf_surface_create_for_stream:
  * @write_func: a #cairo_write_func_t to accept the output data
  * @closure: the closure argument for @write_func
  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
@@ -441,113 +508,567 @@ cairo_pdf_surface_set_size (cairo_surfac
     status = _extract_pdf_surface (surface, &pdf_surface);
     if (status) {
 	_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
     }
 
     pdf_surface->width = width_in_points;
     pdf_surface->height = height_in_points;
+    cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points);
+    status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
+						width_in_points,
+						height_in_points);
+    if (status)
+	_cairo_surface_set_error (surface, status);
 }
 
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
 {
-    _cairo_array_truncate (&surface->streams, 0);
+    _cairo_pdf_group_element_array_finish (&surface->content_group);
+    _cairo_pdf_group_element_array_finish (&surface->knockout_group);
+    _cairo_array_truncate (&surface->content_group, 0);
+    _cairo_array_truncate (&surface->knockout_group, 0);
+}
+
+static void
+_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
+{
+    _cairo_array_init (&res->alphas, sizeof (double));
+    _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
+    _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
+}
+
+static void
+_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
+{
+    _cairo_array_fini (&res->alphas);
+    _cairo_array_fini (&res->smasks);
+    _cairo_array_fini (&res->patterns);
+    _cairo_array_fini (&res->xobjects);
+    _cairo_array_fini (&res->fonts);
+}
+
+static void
+_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
+{
+    _cairo_array_truncate (&res->alphas, 0);
+    _cairo_array_truncate (&res->smasks, 0);
+    _cairo_array_truncate (&res->patterns, 0);
+    _cairo_array_truncate (&res->xobjects, 0);
+    _cairo_array_truncate (&res->fonts, 0);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
+			      double               alpha,
+			      int                 *index)
+{
+    int num_alphas, i;
+    double other;
+    cairo_status_t status;
+    cairo_pdf_group_resources_t *res = surface->current_resources;
+
+    num_alphas = _cairo_array_num_elements (&res->alphas);
+    for (i = 0; i < num_alphas; i++) {
+	_cairo_array_copy_element (&res->alphas, i, &other);
+	if (alpha == other) {
+	    *index = i;
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    }
+
+    status = _cairo_array_append (&res->alphas, &alpha);
+    if (status)
+	return status;
+
+    *index = _cairo_array_num_elements (&res->alphas) - 1;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
+			      cairo_pdf_resource_t  smask)
+{
+    return _cairo_array_append (&surface->current_resources->smasks, &smask);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
+				cairo_pdf_resource_t  pattern)
+{
+    return _cairo_array_append (&surface->current_resources->patterns, &pattern);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
+				cairo_pdf_resource_t  xobject)
+{
+    return _cairo_array_append (&surface->current_resources->xobjects, &xobject);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface,
+			     unsigned int         font_id,
+			     unsigned int         subset_id)
+{
+    cairo_pdf_font_t font;
+    int num_fonts, i;
+    cairo_status_t status;
+    cairo_pdf_group_resources_t *res = surface->current_resources;
+
+    num_fonts = _cairo_array_num_elements (&surface->fonts);
+    for (i = 0; i < num_fonts; i++) {
+	_cairo_array_copy_element (&surface->fonts, i, &font);
+	if (font.font_id == font_id &&
+	    font.subset_id == subset_id) {
+	    status = _cairo_array_append (&res->fonts, &font);
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    }
+
+    font.font_id = font_id;
+    font.subset_id = subset_id;
+    font.subset_resource = _cairo_pdf_surface_new_object (surface);
+
+    status = _cairo_array_append (&res->fonts, &font);
+    if (status)
+	return status;
+
+    status = _cairo_array_append (&surface->fonts, &font);
+
+    return status;
+}
+
+static cairo_pdf_resource_t
+_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
+				      unsigned int         font_id,
+				      unsigned int         subset_id)
+{
+    cairo_pdf_font_t font;
+    int num_fonts, i;
+    cairo_pdf_resource_t resource;
+
+    num_fonts = _cairo_array_num_elements (&surface->fonts);
+    for (i = 0; i < num_fonts; i++) {
+	_cairo_array_copy_element (&surface->fonts, i, &font);
+	if (font.font_id == font_id && font.subset_id == subset_id)
+	    return font.subset_resource;
+    }
+    resource.id = 0;
+
+    return resource;
+}
+
+static void
+_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
+					 cairo_pdf_group_resources_t *res)
+{
+    int num_alphas, num_smasks, num_resources, i;
+    double alpha;
+    cairo_pdf_resource_t *smask, *pattern, *xobject;
+    cairo_pdf_font_t *font;
+
+    _cairo_output_stream_printf (surface->output, "   /Resources <<\r\n");
+
+    num_alphas = _cairo_array_num_elements (&res->alphas);
+    num_smasks = _cairo_array_num_elements (&res->smasks);
+    if (num_alphas > 0 || num_smasks > 0) {
+	_cairo_output_stream_printf (surface->output,
+				     "      /ExtGState <<\r\n");
+
+	for (i = 0; i < num_alphas; i++) {
+	    _cairo_array_copy_element (&res->alphas, i, &alpha);
+	    _cairo_output_stream_printf (surface->output,
+					 "         /a%d << /CA %f /ca %f >>\r\n",
+					 i, alpha, alpha);
+	}
+
+	for (i = 0; i < num_smasks; i++) {
+	    smask = _cairo_array_index (&res->smasks, i);
+	    _cairo_output_stream_printf (surface->output,
+					 "         /s%d %d 0 R\r\n",
+					 smask->id, smask->id);
+	}
+
+	_cairo_output_stream_printf (surface->output,
+				     "      >>\r\n");
+    }
+
+    num_resources = _cairo_array_num_elements (&res->patterns);
+    if (num_resources > 0) {
+	_cairo_output_stream_printf (surface->output,
+				     "      /Pattern <<");
+	for (i = 0; i < num_resources; i++) {
+	    pattern = _cairo_array_index (&res->patterns, i);
+	    _cairo_output_stream_printf (surface->output,
+					 " /p%d %d 0 R",
+					 pattern->id, pattern->id);
+	}
+
+	_cairo_output_stream_printf (surface->output,
+				     " >>\r\n");
+    }
+
+    num_resources = _cairo_array_num_elements (&res->xobjects);
+    if (num_resources > 0) {
+	_cairo_output_stream_printf (surface->output,
+				     "      /XObject <<");
+
+	for (i = 0; i < num_resources; i++) {
+	    xobject = _cairo_array_index (&res->xobjects, i);
+	    _cairo_output_stream_printf (surface->output,
+					 " /x%d %d 0 R",
+					 xobject->id, xobject->id);
+	}
+
+	_cairo_output_stream_printf (surface->output,
+				     " >>\r\n");
+    }
+
+    num_resources = _cairo_array_num_elements (&res->fonts);
+    if (num_resources > 0) {
+	_cairo_output_stream_printf (surface->output,"      /Font <<\r\n");
+	for (i = 0; i < num_resources; i++) {
+	    font = _cairo_array_index (&res->fonts, i);
+	    _cairo_output_stream_printf (surface->output,
+					 "         /f-%d-%d %d 0 R\r\n",
+					 font->font_id,
+					 font->subset_id,
+					 font->subset_resource.id);
+	}
+	_cairo_output_stream_printf (surface->output, "      >>\r\n");
+    }
+
+    _cairo_output_stream_printf (surface->output,
+				 "   >>\r\n");
 }
 
 static cairo_pdf_resource_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
-                                cairo_bool_t             compressed,
+				cairo_bool_t             compressed,
 				const char		*fmt,
 				...)
 {
     va_list ap;
 
-    surface->current_stream.active = TRUE;
-    surface->current_stream.self = _cairo_pdf_surface_new_object (surface);
-    surface->current_stream.length = _cairo_pdf_surface_new_object (surface);
-    surface->current_stream.compressed = compressed;
+    surface->pdf_stream.active = TRUE;
+    surface->pdf_stream.self = _cairo_pdf_surface_new_object (surface);
+    surface->pdf_stream.length = _cairo_pdf_surface_new_object (surface);
+    surface->pdf_stream.compressed = compressed;
 
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Length %d 0 R\r\n",
-				 surface->current_stream.self.id,
-				 surface->current_stream.length.id);
+				 surface->pdf_stream.self.id,
+				 surface->pdf_stream.length.id);
     if (compressed)
-        _cairo_output_stream_printf (surface->output,
-                                     "   /Filter /FlateDecode\r\n");
+	_cairo_output_stream_printf (surface->output,
+				     "   /Filter /FlateDecode\r\n");
 
     if (fmt != NULL) {
 	va_start (ap, fmt);
 	_cairo_output_stream_vprintf (surface->output, fmt, ap);
 	va_end (ap);
     }
 
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "stream\r\n");
 
-    surface->current_stream.start_offset = _cairo_output_stream_get_position (surface->output);
+    surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
 
     if (compressed) {
-        surface->current_stream.old_output = surface->output;
-        surface->output = _cairo_deflate_stream_create (surface->output);
+	surface->pdf_stream.old_output = surface->output;
+	surface->output = _cairo_deflate_stream_create (surface->output);
     }
 
-    return surface->current_stream.self;
+    return surface->pdf_stream.self;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     long length;
 
-    if (! surface->current_stream.active)
+    if (! surface->pdf_stream.active)
 	return CAIRO_STATUS_SUCCESS;
 
-    if (surface->current_stream.compressed) {
-        status = _cairo_output_stream_destroy (surface->output);
-        surface->output = surface->current_stream.old_output;
-        _cairo_output_stream_printf (surface->output,
-                                     "\r\n");
+    if (surface->pdf_stream.compressed) {
+	status = _cairo_output_stream_destroy (surface->output);
+	surface->output = surface->pdf_stream.old_output;
+	_cairo_output_stream_printf (surface->output,
+				     "\r\n");
     }
 
     length = _cairo_output_stream_get_position (surface->output) -
-	surface->current_stream.start_offset;
+	surface->pdf_stream.start_offset;
     _cairo_output_stream_printf (surface->output,
 				 "endstream\r\n"
 				 "endobj\r\n");
 
     _cairo_pdf_surface_update_object (surface,
-				      surface->current_stream.length);
+				      surface->pdf_stream.length);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "   %ld\r\n"
 				 "endobj\r\n",
-				 surface->current_stream.length.id,
+				 surface->pdf_stream.length.id,
 				 length);
 
-    surface->current_stream.active = FALSE;
+    surface->pdf_stream.active = FALSE;
 
     return status;
 }
 
+static cairo_pdf_resource_t
+_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t         *surface,
+					cairo_output_stream_t       *mem_stream,
+					cairo_pdf_group_resources_t *resources,
+					cairo_bool_t                 is_knockout_group)
+{
+    cairo_pdf_resource_t group;
+
+    group = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /XObject\r\n"
+				 "   /Length %d\r\n"
+				 "   /Subtype /Form\r\n"
+				 "   /BBox [ 0 0 %f %f ]\r\n"
+				 "   /Group <<\r\n"
+				 "      /Type /Group\r\n"
+				 "      /S /Transparency\r\n"
+				 "      /CS /DeviceRGB\r\n",
+				 group.id,
+				 _cairo_memory_stream_length (mem_stream),
+				 surface->width,
+				 surface->height);
+
+    if (is_knockout_group)
+	_cairo_output_stream_printf (surface->output,
+				     "      /K true\r\n");
+
+    _cairo_output_stream_printf (surface->output,
+				 "   >>\r\n");
+    _cairo_pdf_surface_emit_group_resources (surface, resources);
+    _cairo_output_stream_printf (surface->output,
+				 ">>\r\n"
+				 "stream\r\n");
+    _cairo_memory_stream_copy (mem_stream, surface->output);
+    _cairo_output_stream_printf (surface->output,
+				 "endstream\r\n"
+				 "endobj\r\n");
+
+    return group;
+}
+
+static void
+_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
+{
+    assert (surface->pdf_stream.active == FALSE);
+    assert (surface->content_stream.active == FALSE);
+    assert (surface->group_stream.active == FALSE);
+
+    surface->group_stream.active = TRUE;
+    surface->group_stream.stream = _cairo_memory_stream_create ();
+    surface->group_stream.old_output = surface->output;
+    surface->output = surface->group_stream.stream;
+    _cairo_pdf_group_resources_clear (&surface->group_stream.resources);
+    surface->current_resources = &surface->group_stream.resources;
+    surface->group_stream.is_knockout = FALSE;
+}
+
+static void
+_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t  *surface,
+					cairo_pdf_resource_t *first_object)
+{
+    _cairo_pdf_surface_open_group (surface);
+    surface->group_stream.is_knockout = TRUE;
+    surface->group_stream.first_object = *first_object;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
+				cairo_pdf_resource_t *group)
+{
+    assert (surface->pdf_stream.active == FALSE);
+    assert (surface->group_stream.active == TRUE);
+
+    surface->output = surface->group_stream.old_output;
+    surface->group_stream.active = FALSE;
+    *group = _cairo_pdf_surface_write_memory_stream (surface,
+						     surface->group_stream.stream,
+						     &surface->group_stream.resources,
+						     surface->group_stream.is_knockout);
+    return _cairo_output_stream_close (surface->group_stream.stream);
+}
+
+static void
+_cairo_pdf_surface_write_group_list (cairo_pdf_surface_t  *surface,
+				     cairo_array_t        *group_list)
+{
+    int i, len;
+    cairo_pdf_group_element_t *elem;
+
+    _cairo_output_stream_printf (surface->output, "q\r\n");
+    if (surface->group_stream.is_knockout) {
+	_cairo_output_stream_printf (surface->output,
+				     "/x%d Do\r\n",
+				     surface->group_stream.first_object.id);
+	_cairo_pdf_surface_add_xobject (surface, surface->group_stream.first_object);
+    }
+    len = _cairo_array_num_elements (group_list);
+    for (i = 0; i < len; i++) {
+	elem = _cairo_array_index (group_list, i);
+	if (elem->type == ELEM_GROUP) {
+	    _cairo_output_stream_printf (surface->output,
+					 "/x%d Do\r\n",
+					 elem->group.id);
+	    _cairo_pdf_surface_add_xobject (surface, elem->group);
+	} else if (elem->type == ELEM_CLIP) {
+	    _cairo_pdf_surface_emit_clip (surface, elem->clip_path, elem->fill_rule);
+	}
+    }
+    _cairo_output_stream_printf (surface->output, "Q\r\n");
+}
+
+static void
+_cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
+{
+    if (surface->content_stream.active) {
+        return;
+    }
+    assert (surface->pdf_stream.active == FALSE);
+    assert (surface->content_stream.active == FALSE);
+    assert (surface->group_stream.active == FALSE);
+
+    surface->content_stream.active = TRUE;
+    surface->content_stream.stream = _cairo_memory_stream_create ();
+    surface->content_stream.old_output = surface->output;
+    surface->output = surface->content_stream.stream;
+    _cairo_pdf_group_resources_clear (&surface->content_stream.resources);
+    surface->current_resources = &surface->content_stream.resources;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_group_to_content_stream (cairo_pdf_surface_t   *surface,
+                                                cairo_pdf_resource_t   group)
+{
+    cairo_pdf_group_element_t elem;
+
+    memset (&elem, 0, sizeof elem);
+    elem.type = ELEM_GROUP;
+    elem.group = group;
+
+    return _cairo_array_append (surface->current_group, &elem);
+}
+
+static void
+_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
+{
+    assert (surface->pdf_stream.active == FALSE);
+
+    if (surface->content_stream.active == FALSE)
+	return;
+
+    surface->output = surface->content_stream.old_output;
+    surface->content_stream.active = FALSE;
+}
+
+static void
+_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
+{
+    assert (surface->pdf_stream.active == FALSE);
+
+    if (surface->content_stream.active == TRUE)
+	return;
+
+    surface->output = surface->content_stream.stream;
+    surface->current_resources = &surface->content_stream.resources;
+    surface->content_stream.active = TRUE;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
+{
+    cairo_pdf_resource_t group;
+
+    assert (surface->pdf_stream.active == FALSE);
+    assert (surface->content_stream.active == TRUE);
+
+    surface->output = surface->content_stream.old_output;
+    surface->content_stream.active = FALSE;
+    if (_cairo_memory_stream_length (surface->content_stream.stream) > 0) {
+	group = _cairo_pdf_surface_write_memory_stream (surface,
+							surface->content_stream.stream,
+							&surface->content_stream.resources,
+							FALSE);
+	_cairo_pdf_surface_add_group_to_content_stream (surface, group);
+    }
+    surface->content_stream.active = FALSE;
+
+    return _cairo_output_stream_close (surface->content_stream.stream);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface)
+{
+    cairo_status_t status;
+
+    if (surface->content_stream.active == FALSE)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (_cairo_memory_stream_length (surface->content_stream.stream) > GROUP_STREAM_LIMIT) {
+	status = _cairo_pdf_surface_stop_content_stream (surface);
+	if (status)
+	    return status;
+	_cairo_pdf_surface_start_content_stream (surface);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_pdf_group_element_array_finish (cairo_array_t *array)
+{
+    int i, len;
+    cairo_pdf_group_element_t *elem;
+
+    len = _cairo_array_num_elements (array);
+    for (i = 0; i < len; i++) {
+	elem = _cairo_array_index (array, i);
+	if (elem->type == ELEM_CLIP && elem->clip_path)
+	    _cairo_path_fixed_destroy (elem->clip_path);
+    }
+}
+
+static cairo_surface_t *
+_cairo_pdf_surface_create_similar (void			*abstract_surface,
+				   cairo_content_t	 content,
+				   int			 width,
+				   int			 height)
+{
+    return _cairo_meta_surface_create (content, width, height);
+}
+
 static cairo_status_t
 _cairo_pdf_surface_finish (void *abstract_surface)
 {
     cairo_status_t status, status2;
     cairo_pdf_surface_t *surface = abstract_surface;
     long offset;
     cairo_pdf_resource_t info, catalog;
 
-    status = _cairo_pdf_surface_close_stream (surface);
-
-    _cairo_pdf_surface_emit_font_subsets (surface);
+    status = _cairo_pdf_surface_emit_font_subsets (surface);
 
     _cairo_pdf_surface_write_pages (surface);
 
     info = _cairo_pdf_surface_write_info (surface);
     catalog = _cairo_pdf_surface_write_catalog (surface);
     offset = _cairo_pdf_surface_write_xref (surface);
 
     _cairo_output_stream_printf (surface->output,
@@ -567,138 +1088,78 @@ static cairo_status_t
 				 offset);
 
     status2 = _cairo_output_stream_destroy (surface->output);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
     _cairo_array_fini (&surface->objects);
     _cairo_array_fini (&surface->pages);
-    _cairo_array_fini (&surface->patterns);
-    _cairo_array_fini (&surface->xobjects);
-    _cairo_array_fini (&surface->streams);
-    _cairo_array_fini (&surface->alphas);
-    _cairo_array_fini (&surface->smasks);
     _cairo_array_fini (&surface->rgb_linear_functions);
     _cairo_array_fini (&surface->alpha_linear_functions);
+    _cairo_array_fini (&surface->fonts);
+
+    _cairo_pdf_group_resources_fini (&surface->group_stream.resources);
+    _cairo_pdf_group_resources_fini (&surface->content_stream.resources);
+
+    _cairo_pdf_group_element_array_finish (&surface->knockout_group);
+    _cairo_array_fini (&surface->knockout_group);
+
+    _cairo_pdf_group_element_array_finish (&surface->content_group);
+    _cairo_array_fini (&surface->content_group);
 
     if (surface->font_subsets) {
 	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
 	surface->font_subsets = NULL;
     }
 
-    _cairo_array_fini (&surface->fonts);
-
     return status;
 }
 
-static cairo_status_t
-_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
-{
-    return _cairo_pdf_surface_close_stream (surface);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
-{
-    cairo_pdf_resource_t stream;
-
-    stream = _cairo_pdf_surface_open_stream (surface,
-                                             TRUE,
-					     "   /Type /XObject\r\n"
-					     "   /Subtype /Form\r\n"
-					     "   /BBox [ 0 0 %f %f ]\r\n",
-					     surface->width,
-					     surface->height);
-
-    return _cairo_pdf_surface_add_stream (surface, stream);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_begin_group (cairo_pdf_surface_t *surface, cairo_pdf_resource_t *group)
-{
-    cairo_pdf_resource_t g;
-    cairo_status_t status;
-
-    _cairo_pdf_surface_pause_content_stream (surface);
-    g = _cairo_pdf_surface_open_stream (surface,
-                                        TRUE,
-                                        "   /Type /XObject\r\n"
-                                        "   /Subtype /Form\r\n"
-                                        "   /BBox [ 0 0 %f %f ]\r\n"
-                                        "   /Group <<\r\n"
-                                        "      /Type /Group\r\n"
-                                        "      /S /Transparency\r\n"
-                                        "      /CS /DeviceRGB\r\n"
-                                        "   >>\r\n",
-                                        surface->width,
-                                        surface->height);
-
-    status = _cairo_array_append (&surface->xobjects, &g);
-    *group = g;
-
-    return status;
-}
-
-static void
-_cairo_pdf_surface_end_group (cairo_pdf_surface_t *surface)
-{
-    _cairo_pdf_surface_close_stream (surface);
-    _cairo_pdf_surface_resume_content_stream (surface);
-}
-
 static cairo_int_status_t
 _cairo_pdf_surface_start_page (void *abstract_surface)
 {
-    cairo_status_t status;
     cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_resource_t stream;
-
-    stream = _cairo_pdf_surface_open_stream (surface,
-                                             TRUE,
-					     "   /Type /XObject\r\n"
-					     "   /Subtype /Form\r\n"
-					     "   /BBox [ 0 0 %f %f ]\r\n",
-					     surface->width,
-					     surface->height);
-
-    status = _cairo_pdf_surface_add_stream (surface, stream);
-    if (status)
-	return status;
+
+    surface->current_group = &surface->content_group;
+    _cairo_pdf_surface_start_content_stream (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void *
 compress_dup (const void *data, unsigned long data_size,
 	      unsigned long *compressed_size)
 {
     void *compressed;
 
     /* Bound calculation taken from zlib. */
     *compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;
     compressed = malloc (*compressed_size);
     if (compressed == NULL)
 	return NULL;
 
-    compress (compressed, compressed_size, data, data_size);
+    if (compress (compressed, compressed_size, data, data_size) != Z_OK) {
+	free (compressed);
+	compressed = NULL;
+    }
 
     return compressed;
 }
 
 /* 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
-_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t		*surface,
-	    cairo_image_surface_t	*image,
-	    cairo_pdf_resource_t	*stream_ret)
+_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;
     uint32_t *pixel;
     int i, x, y;
     cairo_bool_t opaque;
     uint8_t a;
@@ -861,141 +1322,239 @@ static cairo_status_t
 						     image->width, image->height);
 
 #undef IMAGE_DICTIONARY
 
     _cairo_output_stream_write (surface->output, compressed, compressed_size);
     _cairo_output_stream_printf (surface->output, "\r\n");
     status = _cairo_pdf_surface_close_stream (surface);
 
- CLEANUP_COMPRESSED:
+CLEANUP_COMPRESSED:
     free (compressed);
- CLEANUP_RGB:
+CLEANUP_RGB:
     free (rgb);
- CLEANUP:
+CLEANUP:
     return status;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t   *surface,
-                                       cairo_solid_pattern_t *pattern)
+_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
+				       cairo_surface_pattern_t *pattern,
+				       cairo_pdf_resource_t    *resource,
+				       int                     *width,
+				       int                     *height)
 {
-    int alpha;
-    cairo_status_t status;
-
-    status = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha, &alpha);
-    if (status)
-	return status;
-
-    surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SOLID;
-    surface->emitted_pattern.red = pattern->color.red;
-    surface->emitted_pattern.green = pattern->color.green;
-    surface->emitted_pattern.blue = pattern->color.blue;
-    surface->emitted_pattern.alpha = alpha;
-    surface->emitted_pattern.smask.id = 0;
-    surface->emitted_pattern.pattern.id = 0;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_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 image_resource = {0}; /* squelch bogus compiler warning */
-    cairo_matrix_t cairo_p2d, pdf_p2d;
-    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
-    double xstep, ystep;
-    cairo_rectangle_int_t surface_extents;
-
-    /* XXX: Should do something clever here for PDF source surfaces ? */
-
-    status = _cairo_pdf_surface_pause_content_stream (surface);
-    if (status)
-	return status;
 
     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 = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
     if (status)
 	goto BAIL2;
 
-    status = _cairo_pdf_surface_emit_image (surface, image, &image_resource);
+    status = _cairo_pdf_surface_emit_image (surface, image, resource);
     if (status)
 	goto BAIL;
 
+    *width = image->width;
+    *height = image->height;
+
+BAIL:
+    _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;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t  *surface,
+				      cairo_surface_t      *meta_surface,
+				      cairo_pdf_resource_t *resource)
+{
+    cairo_array_t group;
+    cairo_array_t *old_group;
+    double old_width, old_height;
+    cairo_matrix_t old_cairo_to_pdf;
+    cairo_rectangle_int16_t meta_extents;
+    cairo_status_t status;
+    int alpha = 0;
+
+    status = _cairo_surface_get_extents (meta_surface, &meta_extents);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_resume_content_stream (surface);
+    _cairo_pdf_surface_stop_content_stream (surface);
+
+    _cairo_array_init (&group, sizeof (cairo_pdf_group_element_t));
+    old_group = surface->current_group;
+    old_width = surface->width;
+    old_height = surface->height;
+    old_cairo_to_pdf = surface->cairo_to_pdf;
+    surface->current_group = &group;
+    surface->width = meta_extents.width;
+    surface->height = meta_extents.height;
+    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
+
+    _cairo_pdf_surface_start_content_stream (surface);
+
+    if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
+	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+	if (status)
+	    return status;
+	_cairo_output_stream_printf (surface->output,
+				     "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\r\n",
+				     alpha,
+				     surface->width,
+				     surface->height);
+    }
+
+    status = _cairo_meta_surface_replay (meta_surface, &surface->base);
+    if (status)
+	return status;
+    _cairo_pdf_surface_stop_content_stream (surface);
+
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_write_group_list (surface, &group);
+    _cairo_pdf_surface_close_group (surface, resource);
+
+    surface->current_group = old_group;
+    surface->width = old_width;
+    surface->height = old_height;
+    surface->cairo_to_pdf = old_cairo_to_pdf;
+
+    _cairo_pdf_surface_start_content_stream (surface);
+
+    _cairo_pdf_group_element_array_finish (&group);
+    _cairo_array_fini (&group);
+
+    _cairo_pdf_surface_pause_content_stream (surface);
+
+    return 0;
+}
+
+static void
+_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t   *surface,
+				       cairo_solid_pattern_t *pattern)
+{
+    surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SOLID;
+    surface->emitted_pattern.red = pattern->color.red;
+    surface->emitted_pattern.green = pattern->color.green;
+    surface->emitted_pattern.blue = pattern->color.blue;
+    surface->emitted_pattern.alpha = pattern->color.alpha;
+    surface->emitted_pattern.smask.id = 0;
+    surface->emitted_pattern.pattern.id = 0;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	 *surface,
+					 cairo_surface_pattern_t *pattern)
+{
+    cairo_pdf_resource_t stream;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
+    cairo_matrix_t cairo_p2d, pdf_p2d;
+    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
+    double xstep, ystep;
+    cairo_rectangle_int16_t surface_extents;
+    int pattern_width = 0; /* squelch bogus compiler warning */
+    int pattern_height = 0; /* squelch bogus compiler warning */
+
+    _cairo_pdf_surface_pause_content_stream (surface);
+
+    if (_cairo_surface_is_meta (pattern->surface)) {
+	cairo_surface_t *meta_surface = pattern->surface;
+	cairo_rectangle_int16_t pattern_extents;
+
+	status = _cairo_pdf_surface_emit_meta_surface (surface,
+						       meta_surface,
+						       &pattern_resource);
+	status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
+	if (status)
+	    return status;
+	pattern_width = pattern_extents.width;
+	pattern_height = pattern_extents.height;
+    } else {
+	status = _cairo_pdf_surface_emit_image_surface (surface,
+							pattern,
+							&pattern_resource,
+							&pattern_width,
+							&pattern_height);
+    }
+    if (status)
+	return status;
+
     status = _cairo_surface_get_extents (&surface->base, &surface_extents);
     if (status)
-	goto BAIL;
+	return status;
 
     switch (extend) {
-    /* We implement EXTEND_PAD like EXTEND_NONE for now */
+	/* We implement EXTEND_PAD like EXTEND_NONE for now */
     case CAIRO_EXTEND_PAD:
     case CAIRO_EXTEND_NONE:
-        {
-	    /* 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;
+    {
+	/* 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) +
+			      pattern_width + pattern_height);
+    }
+    break;
     case CAIRO_EXTEND_REPEAT:
     case CAIRO_EXTEND_REFLECT:
-	xstep = image->width;
-	ystep = image->height;
+	xstep = pattern_width;
+	ystep = pattern_height;
 	break;
-    /* All the rest (if any) should have been analyzed away, so this
-     * case should be unreachable. */
+	/* 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
      * pattern space, (both with their origin at the upper-left, and
      * cairo's pattern space of size width,height).
      *
      * Then, we must emit a PDF pattern object that maps from its own
      * pattern space, (which has a size that we establish in the BBox
      * dictionary entry), to the PDF page's *initial* space, (which
      * does not benefit from the Y-axis flipping matrix that we emit
-     * on each page). So the PDF patterns patrix maps from a
+     * on each page). So the PDF patterns matrix maps from a
      * (width,height) pattern space to a device space with the origin
      * in the lower-left corner.
      *
      * So to handle all of that, we start with an identity matrix for
      * the PDF pattern to device matrix. We translate it up by the
      * image height then flip it in the Y direction, (moving us from
      * the PDF origin to cairo's origin). We then multiply in the
      * inverse of the cairo pattern matrix, (since it maps from device
@@ -1012,65 +1571,58 @@ static cairo_status_t
     status = cairo_matrix_invert (&cairo_p2d);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_init_identity (&pdf_p2d);
     cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
     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_translate (&pdf_p2d, 0.0, pattern_height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
     stream = _cairo_pdf_surface_open_stream (surface,
-                                             FALSE,
+					     FALSE,
 					     "   /BBox [0 0 %d %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,
+					     "   /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
+					     pattern_width, pattern_height,
 					     xstep, ystep,
 					     pdf_p2d.xx, pdf_p2d.yx,
 					     pdf_p2d.xy, pdf_p2d.yy,
 					     pdf_p2d.x0, pdf_p2d.y0,
-					     image_resource.id,
-					     image_resource.id);
-
-    _cairo_output_stream_printf (surface->output,
-				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
-				 image->width, image->height,
-				 image_resource.id);
+					     pattern_resource.id,
+					     pattern_resource.id);
+
+    if (_cairo_surface_is_meta (pattern->surface)) {
+	_cairo_output_stream_printf (surface->output,
+				     "/x%d Do\r\n",
+				     pattern_resource.id);
+    } else {
+	_cairo_output_stream_printf (surface->output,
+				     "q %d 0 0 %d 0 0 cm /x%d Do Q\r\n",
+				     pattern_width, pattern_height,
+				     pattern_resource.id);
+    }
 
     status = _cairo_pdf_surface_close_stream (surface);
     if (status)
-	goto BAIL;
-
-    status = _cairo_pdf_surface_resume_content_stream (surface);
-    if (status)
-	goto BAIL;
-
-    status = _cairo_pdf_surface_add_pattern (surface, stream);
-    if (status)
-	goto BAIL;
-
-    status = _cairo_pdf_surface_add_alpha (surface, 1.0, &surface->emitted_pattern.alpha);
-    if (status)
-	goto BAIL;
+	return status;
+
+    _cairo_pdf_surface_resume_content_stream (surface);
+
     surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SURFACE;
     surface->emitted_pattern.smask.id = 0;
     surface->emitted_pattern.pattern = stream;
-
- BAIL:
-    _cairo_surface_release_source_image (pat_surface, image, image_extra);
- BAIL2:
-    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
+    surface->emitted_pattern.alpha = 1.0;
 
     return status;
 }
 
 typedef struct _cairo_pdf_color_stop {
     double offset;
     double color[4];
     cairo_pdf_resource_t resource;
@@ -1184,19 +1736,19 @@ static cairo_status_t
     cairo_pdf_resource_t res;
     unsigned int i;
     cairo_status_t status;
 
     /* emit linear gradients between pairs of subsequent stops... */
     for (i = 0; i < n_stops-1; i++) {
         if (is_alpha) {
             status = cairo_pdf_surface_emit_alpha_linear_function (surface,
-                                                             &stops[i],
-                                                             &stops[i+1],
-                                                             &stops[i].resource);
+                                                                   &stops[i],
+                                                                   &stops[i+1],
+                                                                   &stops[i].resource);
             if (status)
                 return status;
         } else {
             status = cairo_pdf_surface_emit_rgb_linear_function (surface,
                                                                  &stops[i],
                                                                  &stops[i+1],
                                                                  &stops[i].resource);
             if (status)
@@ -1204,18 +1756,20 @@ static cairo_status_t
         }
     }
 
     /* ... and stitch them together */
     res = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 3\r\n"
-				 "   /Domain [ 0 1 ]\r\n",
-				 res.id);
+				 "   /Domain [ %f %f ]\r\n",
+				 res.id,
+                                 stops[0].offset,
+                                 stops[n_stops - 1].offset);
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Functions [ ");
     for (i = 0; i < n_stops-1; i++)
         _cairo_output_stream_printf (surface->output,
                                      "%d 0 R ", stops[i].resource.id);
     _cairo_output_stream_printf (surface->output,
 		    		 "]\r\n");
@@ -1265,42 +1819,25 @@ static cairo_status_t
     allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
     if (allstops == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
     stops = &allstops[1];
     n_stops = pattern->n_stops;
 
     for (i = 0; i < n_stops; i++) {
-	stops[i].color[0] = pattern->stops[i].color.red / 65535.0;
-	stops[i].color[1] = pattern->stops[i].color.green / 65535.0;
-	stops[i].color[2] = pattern->stops[i].color.blue / 65535.0;
-	stops[i].color[3] = pattern->stops[i].color.alpha / 65535.0;
+	stops[i].color[0] = pattern->stops[i].color.red;
+	stops[i].color[1] = pattern->stops[i].color.green;
+	stops[i].color[2] = pattern->stops[i].color.blue;
+	stops[i].color[3] = pattern->stops[i].color.alpha;
         if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
             emit_alpha = TRUE;
 	stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
     }
 
-    /* make sure first offset is 0.0 and last offset is 1.0. (Otherwise Acrobat
-     * Reader chokes.) */
-    if (stops[0].offset > COLOR_STOP_EPSILON) {
-	    memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
-	    stops = allstops;
-	    n_stops++;
-    }
-    stops[0].offset = 0.0;
-
-    if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
-	    memcpy (&stops[n_stops],
-		    &stops[n_stops - 1],
-		    sizeof (cairo_pdf_color_stop_t));
-	    n_stops++;
-    }
-    stops[n_stops-1].offset = 1.0;
-
     if (n_stops == 2) {
         /* no need for stitched function */
         status = cairo_pdf_surface_emit_rgb_linear_function (surface,
                                                              &stops[0],
                                                              &stops[1],
                                                              color_function);
         if (status)
             goto BAIL;
@@ -1352,48 +1889,47 @@ cairo_pdf_surface_emit_transparency_grou
                                                     "   /Subtype /Form\r\n"
                                                     "   /FormType 1\r\n"
                                                     "   /BBox [ 0 0 %f %f ]\r\n"
                                                     "   /Resources\r\n"
                                                     "      << /ExtGState\r\n"
                                                     "            << /a0 << /ca 1 /CA 1 >>"
                                                     "      >>\r\n"
                                                     "         /Pattern\r\n"
-                                                    "            << /res%d %d 0 R >>\r\n"
+                                                    "            << /p%d %d 0 R >>\r\n"
                                                     "      >>\r\n"
                                                     "   /Group\r\n"
                                                     "      << /Type /Group\r\n"
                                                     "         /S /Transparency\r\n"
                                                     "         /CS /DeviceGray\r\n"
                                                     "      >>\r\n",
                                                     surface->width,
                                                     surface->height,
                                                     gradient_mask.id,
                                                     gradient_mask.id);
 
     _cairo_output_stream_printf (surface->output,
                                  "q\r\n"
                                  "/a0 gs\r\n"
-                                 "/Pattern cs /res%d scn\r\n"
+                                 "/Pattern cs /p%d scn\r\n"
                                  "0 0 %f %f re\r\n"
                                  "f\r\n"
                                  "Q\r\n",
                                  gradient_mask.id,
                                  surface->width,
                                  surface->height);
 
     _cairo_pdf_surface_close_stream (surface);
 
     smask_resource = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
                                  "%d 0 obj\r\n"
                                  "<< /Type /Mask\r\n"
                                  "   /S /Luminosity\r\n"
                                  "   /G %d 0 R\r\n"
-                                 "   /BC [ 0.0 ]\r\n"
                                  ">>\r\n"
                                  "endobj\r\n",
                                  smask_resource.id,
                                  xobj_resource.id);
 
     /* Create GState which uses the transparency group as an SMask. */
     gstate_resource = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
@@ -1403,71 +1939,100 @@ cairo_pdf_surface_emit_transparency_grou
                                  "   /ca 1\r\n"
                                  "   /CA 1\r\n"
                                  "   /AIS false\r\n"
                                  ">>\r\n"
                                  "endobj\r\n",
                                  gstate_resource.id,
                                  smask_resource.id);
 
-    _cairo_pdf_surface_add_smask (surface, gstate_resource);
-
     return gstate_resource;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
                                         cairo_linear_pattern_t *pattern)
 {
     cairo_pdf_resource_t pattern_resource, smask;
     cairo_pdf_resource_t color_function, alpha_function;
     double x1, y1, x2, y2;
     cairo_matrix_t pat_to_pdf;
     cairo_extend_t extend;
     cairo_status_t status;
+    cairo_gradient_pattern_t *gradient = &pattern->base;
+    double first_stop, last_stop;
 
     extend = cairo_pattern_get_extend (&pattern->base.base);
-    status = _cairo_pdf_surface_pause_content_stream (surface);
-    if (status)
-	return status;
-
+    _cairo_pdf_surface_pause_content_stream (surface);
     status = _cairo_pdf_surface_emit_pattern_stops (surface,
                                                     &pattern->base,
                                                     &color_function,
                                                     &alpha_function);
     if (status)
 	return status;
 
     pat_to_pdf = pattern->base.base.matrix;
     status = cairo_matrix_invert (&pat_to_pdf);
-    if (status)
-	return status;
+    /* cairo_pattern_set_matrix ensures the matrix is invertible */
+    assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
     x1 = _cairo_fixed_to_double (pattern->p1.x);
     y1 = _cairo_fixed_to_double (pattern->p1.y);
     x2 = _cairo_fixed_to_double (pattern->p2.x);
     y2 = _cairo_fixed_to_double (pattern->p2.y);
 
+    first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
+    last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
+
+    /* PDF requires the first and last stop to be the same as the line
+     * coordinates. If this is not a repeating pattern move the line
+     * coordinates to the location of first and last stop. */
+
+    if (pattern->base.base.extend == CAIRO_EXTEND_NONE ||
+	pattern->base.base.extend == CAIRO_EXTEND_PAD) {
+	double _x1, _y1, _x2, _y2;
+
+	_x1 = x1 + (x2 - x1)*first_stop;
+	_y1 = y1 + (y2 - y1)*first_stop;
+	_x2 = x1 + (x2 - x1)*last_stop;
+	_y2 = y1 + (y2 - y1)*last_stop;
+
+	x1 = _x1;
+	x2 = _x2;
+	y1 = _y1;
+	y2 = _y2;
+    }
+
+    if (gradient->n_stops == 2) {
+	/* If only two stops the Type 2 function is used by itself
+	 * without a Stitching function. Type 2 functions always have
+	 * the domain [0 1] */
+	first_stop = 0.0;
+	last_stop = 1.0;
+    }
+
     pattern_resource = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
                                  "%d 0 obj\r\n"
                                  "<< /Type /Pattern\r\n"
                                  "   /PatternType 2\r\n"
                                  "   /Matrix [ %f %f %f %f %f %f ]\r\n"
                                  "   /Shading\r\n"
                                  "      << /ShadingType 2\r\n"
                                  "         /ColorSpace /DeviceRGB\r\n"
                                  "         /Coords [ %f %f %f %f ]\r\n"
+                                 "         /Domain [ %f %f ]\r\n"
                                  "         /Function %d 0 R\r\n",
                                  pattern_resource.id,
                                  pat_to_pdf.xx, pat_to_pdf.yx,
                                  pat_to_pdf.xy, pat_to_pdf.yy,
                                  pat_to_pdf.x0, pat_to_pdf.y0,
                                  x1, y1, x2, y2,
+                                 first_stop, last_stop,
                                  color_function.id);
 
     if (extend == CAIRO_EXTEND_PAD) {
         _cairo_output_stream_printf (surface->output,
                                      "         /Extend [ true true ]\r\n");
     } else {
         _cairo_output_stream_printf (surface->output,
                                      "         /Extend [ false false ]\r\n");
@@ -1518,55 +2083,49 @@ static cairo_status_t
         if (status)
             return status;
 
         smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
         surface->emitted_pattern.smask = smask;
     }
 
     surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR;
-    status = _cairo_pdf_surface_add_alpha (surface, 1, &surface->emitted_pattern.alpha);
-    if (status)
-        return status;
-
     surface->emitted_pattern.pattern = pattern_resource;
-    status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
-    if (status)
-        return status;
-
-    return _cairo_pdf_surface_resume_content_stream (surface);
+    surface->emitted_pattern.alpha = 1.0;
+
+    _cairo_pdf_surface_resume_content_stream (surface);
+
+    return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t    *surface,
                                         cairo_radial_pattern_t *pattern)
 {
     cairo_pdf_resource_t pattern_resource, smask;
     cairo_pdf_resource_t color_function, alpha_function;
     double x1, y1, x2, y2, r1, r2;
     cairo_matrix_t pat_to_pdf;
     cairo_extend_t extend;
     cairo_status_t status;
 
     extend = cairo_pattern_get_extend (&pattern->base.base);
-    status = _cairo_pdf_surface_pause_content_stream (surface);
-    if (status)
-	return status;
+    _cairo_pdf_surface_pause_content_stream (surface);
 
     status = _cairo_pdf_surface_emit_pattern_stops (surface,
                                                     &pattern->base,
                                                     &color_function,
                                                     &alpha_function);
     if (status)
 	return status;
 
     pat_to_pdf = pattern->base.base.matrix;
     status = cairo_matrix_invert (&pat_to_pdf);
-    if (status)
-	return status;
+    /* cairo_pattern_set_matrix ensures the matrix is invertible */
+    assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
     x1 = _cairo_fixed_to_double (pattern->c1.x);
     y1 = _cairo_fixed_to_double (pattern->c1.y);
     r1 = _cairo_fixed_to_double (pattern->r1);
     x2 = _cairo_fixed_to_double (pattern->c2.x);
     y2 = _cairo_fixed_to_double (pattern->c2.y);
     r2 = _cairo_fixed_to_double (pattern->r2);
@@ -1639,36 +2198,31 @@ static cairo_status_t
                                      ">>\r\n"
                                      "endobj\r\n");
 
         smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
         surface->emitted_pattern.smask = smask;
     }
 
     surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL;
-
-    status = _cairo_pdf_surface_add_alpha (surface, 1.0, &surface->emitted_pattern.alpha);
-    if (status)
-	return status;
-
     surface->emitted_pattern.pattern = pattern_resource;
-
-    status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
-    if (status)
-	return status;
-
-    return _cairo_pdf_surface_resume_content_stream (surface);
+    surface->emitted_pattern.alpha = 1.0;
+
+     _cairo_pdf_surface_resume_content_stream (surface);
+
+     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
 {
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	return _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
+	_cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
+        return CAIRO_STATUS_SUCCESS;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
 	return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
 
     case CAIRO_PATTERN_TYPE_LINEAR:
 	return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
 
     case CAIRO_PATTERN_TYPE_RADIAL:
@@ -1678,66 +2232,77 @@ static cairo_status_t
     ASSERT_NOT_REACHED;
     return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
                                    cairo_bool_t         is_stroke)
 {
+    cairo_status_t status;
+    int alpha;
+
+    status = _cairo_pdf_surface_add_alpha (surface, surface->emitted_pattern.alpha, &alpha);
+    if (status)
+	return status;
     if (surface->emitted_pattern.type == CAIRO_PATTERN_TYPE_SOLID) {
 	_cairo_output_stream_printf (surface->output,
                                      "%f %f %f ",
                                      surface->emitted_pattern.red,
                                      surface->emitted_pattern.green,
                                      surface->emitted_pattern.blue);
 
         if (is_stroke)
             _cairo_output_stream_printf (surface->output, "RG ");
         else
             _cairo_output_stream_printf (surface->output, "rg ");
 
         _cairo_output_stream_printf (surface->output,
                                      "/a%d gs\r\n",
-                                     surface->emitted_pattern.alpha);
+                                     alpha);
     } else {
         if (is_stroke) {
             _cairo_output_stream_printf (surface->output,
-                                         "/Pattern CS /res%d SCN ",
-                                         surface->emitted_pattern.pattern);
+                                         "/Pattern CS /p%d SCN ",
+                                         surface->emitted_pattern.pattern.id);
         } else {
             _cairo_output_stream_printf (surface->output,
-                                         "/Pattern cs /res%d scn ",
-                                         surface->emitted_pattern.pattern);
+                                         "/Pattern cs /p%d scn ",
+                                         surface->emitted_pattern.pattern.id);
         }
+        _cairo_pdf_surface_add_pattern (surface, surface->emitted_pattern.pattern);
 
         _cairo_output_stream_printf (surface->output,
                                      "/a%d gs ",
-                                     surface->emitted_pattern.alpha );
+                                     alpha);
 
         _cairo_output_stream_printf (surface->output, "\r\n");
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_copy_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
 
+    _cairo_pdf_surface_stop_content_stream (surface);
+
     return _cairo_pdf_surface_write_page (surface);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_show_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
 
+    _cairo_pdf_surface_stop_content_stream (surface);
+
     status = _cairo_pdf_surface_write_page (surface);
     if (status)
 	return status;
 
     _cairo_pdf_surface_clear (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1839,68 +2404,62 @@ static cairo_status_t
     pdf_path_info_t *info = closure;
 
     _cairo_output_stream_printf (info->output,
 				 "h\r\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_cairo_pdf_surface_add_clip (cairo_pdf_surface_t  *surface,
+			     cairo_path_fixed_t	  *path,
+			     cairo_fill_rule_t     fill_rule)
+{
+    cairo_pdf_group_element_t elem;
+    cairo_status_t status;
+
+    memset (&elem, 0, sizeof elem);
+    elem.type = ELEM_CLIP;
+
+    if (path == NULL) {
+	elem.clip_path = NULL;
+    } else {
+	elem.clip_path = _cairo_path_fixed_create ();
+	if (elem.clip_path == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+	status = _cairo_path_fixed_init_copy (elem.clip_path, path);
+	if (status)
+	    return status;
+    }
+    elem.fill_rule = fill_rule;
+
+    status = _cairo_pdf_surface_stop_content_stream (surface);
+    if (status)
+	return status;
+
+    status = _cairo_array_append (surface->current_group, &elem);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_start_content_stream (surface);
+
+    return status;
+}
+
 static cairo_int_status_t
 _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
-    cairo_status_t status;
-    const char *pdf_operator;
-    pdf_path_info_t info;
-
-    if (path == NULL) {
-	if (surface->has_clip)
-	    _cairo_output_stream_printf (surface->output, "Q\r\n");
-	surface->has_clip = FALSE;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    if (!surface->has_clip) {
-	_cairo_output_stream_printf (surface->output, "q ");
-	surface->has_clip = TRUE;
-    }
-
-    info.output = surface->output;
-    info.cairo_to_pdf = &surface->cairo_to_pdf;
-    info.ctm_inverse = NULL;
-
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_pdf_path_move_to,
-					  _cairo_pdf_path_line_to,
-					  _cairo_pdf_path_curve_to,
-					  _cairo_pdf_path_close_path,
-					  &info);
-
-    switch (fill_rule) {
-    case CAIRO_FILL_RULE_WINDING:
-	pdf_operator = "W";
-	break;
-    case CAIRO_FILL_RULE_EVEN_ODD:
-	pdf_operator = "W*";
-	break;
-    default:
-	ASSERT_NOT_REACHED;
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 "%s n\r\n",
-				 pdf_operator);
-
-    return status;
+
+    return _cairo_pdf_surface_add_clip (surface, path, fill_rule);
 }
 
 static void
 _cairo_pdf_surface_get_font_options (void                  *abstract_surface,
 				     cairo_font_options_t  *options)
 {
     _cairo_font_options_init_default (options);
 
@@ -1926,21 +2485,18 @@ static cairo_pdf_resource_t
                                  cairo_version_string ());
 
     return info;
 }
 
 static void
 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
 {
-    cairo_pdf_resource_t page, *res, smask;
-    cairo_pdf_font_t font;
-    int num_pages, num_fonts, i;
-    int num_alphas, num_smasks, num_resources;
-    double alpha;
+    cairo_pdf_resource_t page;
+    int num_pages, i;
 
     _cairo_pdf_surface_update_object (surface, surface->pages_resource);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Pages\r\n"
 				 "   /Kids [ ",
 				 surface->pages_resource.id);
 
@@ -1948,90 +2504,16 @@ static void
     for (i = 0; i < num_pages; i++) {
 	_cairo_array_copy_element (&surface->pages, i, &page);
 	_cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
     }
 
     _cairo_output_stream_printf (surface->output, "]\r\n");
     _cairo_output_stream_printf (surface->output, "   /Count %d\r\n", num_pages);
 
-    _cairo_output_stream_printf (surface->output, "   /Resources <<\r\n");
-
-    num_alphas =  _cairo_array_num_elements (&surface->alphas);
-    num_smasks =  _cairo_array_num_elements (&surface->smasks);
-    if (num_alphas > 0 || num_smasks > 0) {
-	_cairo_output_stream_printf (surface->output,
-				     "      /ExtGState <<\r\n");
-
-	for (i = 0; i < num_alphas; i++) {
-	    _cairo_array_copy_element (&surface->alphas, i, &alpha);
-	    _cairo_output_stream_printf (surface->output,
-					 "         /a%d << /CA %f /ca %f >>\r\n",
-					 i, alpha, alpha);
-	}
-
-        for (i = 0; i < num_smasks; i++) {
-	    _cairo_array_copy_element (&surface->smasks, i, &smask);
-	    _cairo_output_stream_printf (surface->output,
-					 "         /sm%d %d 0 R\r\n",
-					 smask.id, smask.id);
-	}
-
-	_cairo_output_stream_printf (surface->output,
-				     "      >>\r\n");
-    }
-
-    num_resources = _cairo_array_num_elements (&surface->patterns);
-    if (num_resources > 0) {
-	_cairo_output_stream_printf (surface->output,
-				     "      /Pattern <<");
-	for (i = 0; i < num_resources; i++) {
-	    res = _cairo_array_index (&surface->patterns, i);
-	    _cairo_output_stream_printf (surface->output,
-					 " /res%d %d 0 R",
-					 res->id, res->id);
-	}
-
-	_cairo_output_stream_printf (surface->output,
-				     " >>\r\n");
-    }
-
-    num_resources = _cairo_array_num_elements (&surface->xobjects);
-    if (num_resources > 0) {
-	_cairo_output_stream_printf (surface->output,
-				     "      /XObject <<");
-
-	for (i = 0; i < num_resources; i++) {
-	    res = _cairo_array_index (&surface->xobjects, i);
-	    _cairo_output_stream_printf (surface->output,
-					 " /res%d %d 0 R",
-					 res->id, res->id);
-	}
-
-	_cairo_output_stream_printf (surface->output,
-				     " >>\r\n");
-    }
-
-    num_fonts = _cairo_array_num_elements (&surface->fonts);
-    if (num_fonts > 0) {
-        _cairo_output_stream_printf (surface->output,"      /Font <<\r\n");
-        num_fonts = _cairo_array_num_elements (&surface->fonts);
-        for (i = 0; i < num_fonts; i++) {
-            _cairo_array_copy_element (&surface->fonts, i, &font);
-            _cairo_output_stream_printf (surface->output,
-                                         "         /CairoFont-%d-%d %d 0 R\r\n",
-                                         font.font_id,
-                                         font.subset_id,
-                                         font.subset_resource.id);
-        }
-        _cairo_output_stream_printf (surface->output, "      >>\r\n");
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 "   >>\r\n");
 
     /* TODO: Figure out wich other defaults to be inherited by /Page
      * objects. */
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 }
 
@@ -2206,17 +2688,20 @@ static cairo_status_t
 				     " %d",
 				     subset->widths[i]);
 
     _cairo_output_stream_printf (surface->output,
                                  " ]]\r\n"
 				 ">>\r\n"
 				 "endobj\r\n");
 
-    subset_resource = _cairo_pdf_surface_new_object (surface);
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    _cairo_pdf_surface_update_object (surface, subset_resource);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type0\r\n"
 				 "   /BaseFont /%s\r\n"
                                  "   /Encoding /Identity-H\r\n"
 				 "   /DescendantFonts [ %d 0 R]\r\n",
 				 subset_resource.id,
@@ -2344,17 +2829,20 @@ static cairo_status_t
 				 subset->x_min,
 				 subset->y_min,
 				 subset->x_max,
 				 subset->y_max,
 				 subset->ascent,
 				 subset->descent,
 				 stream.id);
 
-    subset_resource = _cairo_pdf_surface_new_object (surface);
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    _cairo_pdf_surface_update_object (surface, subset_resource);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type1\r\n"
 				 "   /BaseFont /%s\r\n"
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n"
 				 "   /FontDescriptor %d 0 R\r\n"
@@ -2524,17 +3012,20 @@ static cairo_status_t
                                      " %ld",
                                      (long)(subset.widths[i]*PDF_UNITS_PER_EM));
 
     _cairo_output_stream_printf (surface->output,
                                  " ]]\r\n"
 				 ">>\r\n"
 				 "endobj\r\n");
 
-    subset_resource = _cairo_pdf_surface_new_object (surface);
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    _cairo_pdf_surface_update_object (surface, subset_resource);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type0\r\n"
 				 "   /BaseFont /%s\r\n"
                                  "   /Encoding /Identity-H\r\n"
 				 "   /DescendantFonts [ %d 0 R]\r\n",
 				 subset_resource.id,
@@ -2787,17 +3278,20 @@ static cairo_status_t
     _cairo_output_stream_printf (surface->output,
 				 ">>\r\n"
 				 "endobj\r\n");
 
     free (glyphs);
 
     to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset, FALSE);
 
-    subset_resource = _cairo_pdf_surface_new_object (surface);
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    _cairo_pdf_surface_update_object (surface, subset_resource);
     matrix = font_subset->scaled_font->scale;
     status = cairo_matrix_invert (&matrix);
     /* _cairo_scaled_font_init ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type3\r\n"
@@ -2949,76 +3443,137 @@ static long
 	_cairo_output_stream_printf (surface->output,
 				     "%s 00000 n\r\n", buffer);
     }
 
     return offset;
 }
 
 static cairo_status_t
+_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t  *surface,
+			      cairo_path_fixed_t   *path,
+			      cairo_fill_rule_t	    fill_rule)
+{
+    cairo_status_t status;
+    const char *pdf_operator;
+    pdf_path_info_t info;
+
+    if (path == NULL) {
+	_cairo_output_stream_printf (surface->output, "Q q\r\n");
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    info.output = surface->output;
+    info.cairo_to_pdf = &surface->cairo_to_pdf;
+    info.ctm_inverse = NULL;
+
+    status = _cairo_path_fixed_interpret (path,
+					  CAIRO_DIRECTION_FORWARD,
+					  _cairo_pdf_path_move_to,
+					  _cairo_pdf_path_line_to,
+					  _cairo_pdf_path_curve_to,
+					  _cairo_pdf_path_close_path,
+					  &info);
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	pdf_operator = "W";
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	pdf_operator = "W*";
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    _cairo_output_stream_printf (surface->output,
+				 "%s n\r\n",
+				 pdf_operator);
+
+    return status;
+}
+
+static cairo_status_t
 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status;
     cairo_pdf_resource_t page;
-    cairo_pdf_resource_t stream;
-    int num_streams, i;
-
-    if (surface->has_clip) {
-	_cairo_output_stream_printf (surface->output, "Q\r\n");
-	surface->has_clip = FALSE;
+    cairo_pdf_resource_t content_group, knockout_group, page_content;
+    cairo_bool_t has_fallback_images = FALSE;
+
+    if (_cairo_array_num_elements (&surface->knockout_group) > 0)
+	has_fallback_images = TRUE;
+
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_write_group_list (surface, &surface->content_group);
+    _cairo_pdf_surface_close_group (surface, &content_group);
+
+    if (has_fallback_images) {
+	_cairo_pdf_surface_open_knockout_group (surface, &content_group);
+	_cairo_pdf_surface_write_group_list (surface, &surface->knockout_group);
+	_cairo_pdf_surface_close_group (surface, &knockout_group);
     }
 
-    status = _cairo_pdf_surface_close_stream (surface);
-    if (status)
-	return status;
+    page_content = _cairo_pdf_surface_open_stream (surface,
+						   TRUE,
+						   "   /Type /XObject\r\n"
+						   "   /Subtype /Form\r\n"
+						   "   /BBox [ 0 0 %f %f ]\r\n"
+						   "   /Group <<\r\n"
+						   "      /Type /Group\r\n"
+						   "      /S /Transparency\r\n"
+						   "      /CS /DeviceRGB\r\n"
+						   "   >>\r\n",
+						   surface->width,
+						   surface->height);
+    _cairo_output_stream_printf (surface->output,
+				 "/x%d Do\r\n",
+				 has_fallback_images ? knockout_group.id : content_group.id);
+    _cairo_pdf_surface_close_stream (surface);
 
     page = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Page\r\n"
-				 "   /Parent %d 0 R\r\n",
+				 "   /Parent %d 0 R\r\n"
+				 "   /MediaBox [ 0 0 %f %f ]\r\n"
+				 "   /Contents [ %d 0 R ]\r\n"
+				 "   /Group <<\r\n"
+				 "      /Type /Group\r\n"
+				 "      /S /Transparency\r\n"
+				 "      /CS /DeviceRGB\r\n"
+				 "   >>\r\n"
+				 "   /Resources <<\r\n"
+				 "      /XObject << /x%d %d 0 R >>\r\n"
+				 "   >>\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
 				 page.id,
-				 surface->pages_resource.id);
-
-    _cairo_output_stream_printf (surface->output,
-				 "   /MediaBox [ 0 0 %f %f ]\r\n",
+				 surface->pages_resource.id,
 				 surface->width,
-				 surface->height);
-
-    _cairo_output_stream_printf (surface->output,
-				 "   /Contents [");
-    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"
-                                 "   /Group <<\r\n"
-                                 "      /Type /Group\r\n"
-                                 "      /S /Transparency\r\n"
-                                 "      /CS /DeviceRGB\r\n"
-                                 "   >>\r\n"
-				 ">>\r\n"
-				 "endobj\r\n");
+				 surface->height,
+				 page_content.id,
+				 has_fallback_images ? knockout_group.id : content_group.id,
+				 has_fallback_images ? knockout_group.id : content_group.id);
 
     status = _cairo_array_append (&surface->pages, &page);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
 {
     cairo_extend_t extend;
 
+    if (_cairo_surface_is_meta (pattern->surface))
+	return TRUE;
+
     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);
@@ -3087,113 +3642,264 @@ static cairo_bool_t
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
 	return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
 
     return FALSE;
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
-		      cairo_operator_t op,
-		      cairo_pattern_t *pattern)
+_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
+				      cairo_operator_t      op,
+				      cairo_pattern_t      *pattern)
 {
-    if (surface->force_fallbacks)
-	return FALSE;
+    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (! _pattern_supported (pattern))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op == CAIRO_OPERATOR_OVER) {
+	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+	    if ( _cairo_surface_is_meta (surface_pattern->surface))
+	    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+	}
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    /* The SOURCE operator is only supported for the fallback images. */
+    if (op == CAIRO_OPERATOR_SOURCE &&
+	surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER)
+	return CAIRO_STATUS_SUCCESS;
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_bool_t
+_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t  *surface,
+					cairo_operator_t      op,
+					cairo_pattern_t      *pattern)
+{
+    if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
+	return TRUE;
+    else
 	return FALSE;
-
-    /* XXX: We can probably support a fair amount more than just OVER,
-     * but this should cover many common cases at least. */
-    if (op == CAIRO_OPERATOR_OVER)
-	return TRUE;
-
-    return FALSE;
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
-		    cairo_operator_t op,
-		    cairo_pattern_t *pattern)
+_cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface,
+				 cairo_operator_t op)
 {
-    if (_cairo_pdf_surface_operation_supported (surface, op, pattern))
+    if (op == CAIRO_OPERATOR_OVER)
 	return CAIRO_STATUS_SUCCESS;
-    else
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op == CAIRO_OPERATOR_SOURCE) {
+	surface->current_group = &surface->knockout_group;
+	_cairo_pdf_surface_stop_content_stream (surface);
+	_cairo_pdf_surface_start_content_stream (surface);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    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_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	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 (_cairo_pdf_surface_operation_supported (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_set_operator (surface, op);
+    if (status)
+	return status;
+
     if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_begin_group (surface, &group);
-        if (status)
-            return status;
+	_cairo_pdf_surface_pause_content_stream (surface);
+	_cairo_pdf_surface_open_group (surface);
     } else {
-        _cairo_output_stream_printf (surface->output, "q ");
+	_cairo_output_stream_printf (surface->output, "q ");
     }
 
     _cairo_pdf_surface_select_pattern (surface, FALSE);
 
     _cairo_output_stream_printf (surface->output,
 				 "0 0 %f %f re f\r\n",
 				 surface->width, surface->height);
 
     if (surface->emitted_pattern.smask.id != 0) {
-        _cairo_pdf_surface_end_group (surface);
-
-        _cairo_output_stream_printf (surface->output,
-                                     "q /sm%d gs /res%d Do Q\r\n",
-                                     surface->emitted_pattern.smask,
-                                     group.id);
+	_cairo_pdf_surface_close_group (surface, &smask_group);
+	_cairo_pdf_surface_resume_content_stream (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     surface->emitted_pattern.smask,
+				     smask_group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+	if (status)
+	    return status;
     } else {
-        _cairo_output_stream_printf (surface->output, "Q\r\n");
+	_cairo_output_stream_printf (surface->output, "Q\r\n");
     }
 
-    return _cairo_output_stream_get_status (surface->output);
+    status = _cairo_output_stream_get_status (surface->output);
+    if (status)
+        return status;
+
+    return _cairo_pdf_surface_check_content_stream_size (surface);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_mask	(void			*abstract_surface,
 			 cairo_operator_t	 op,
 			 cairo_pattern_t	*source,
 			 cairo_pattern_t	*mask)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    ASSERT_NOT_REACHED;
-
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    cairo_pdf_resource_t mask_group;
+    cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t source_group;
+    cairo_pdf_resource_t smask;
+    cairo_pdf_resource_t gstate;
+    cairo_status_t status, status2;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	status = _cairo_pdf_surface_analyze_operation (surface, op, source);
+	if (status != CAIRO_STATUS_SUCCESS &&
+	    status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	    return status;
+
+	status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask);
+	if (status2 != CAIRO_STATUS_SUCCESS)
+	    return status2;
+
+	return status;
+    }
+
+    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
+    assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
+
+    status = _cairo_pdf_surface_set_operator (surface, op);
+    if (status)
+	return status;
+
+    /* Create mask group */
+    status = _cairo_pdf_surface_emit_pattern (surface, mask);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_pause_content_stream (surface);
+
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_select_pattern (surface, FALSE);
+    _cairo_output_stream_printf (surface->output,
+				 "0 0 %f %f re f\r\n",
+				 surface->width, surface->height);
+    _cairo_pdf_surface_close_group (surface, &mask_group);
+
+    if (surface->emitted_pattern.smask.id != 0) {
+	group = mask_group;
+	_cairo_pdf_surface_open_group (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "/s%d gs /x%d Do\r\n",
+				     surface->emitted_pattern.smask,
+				     group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, group);
+	if (status)
+	    return status;
+	_cairo_pdf_surface_close_group (surface, &mask_group);
+    }
+
+    /* Create source group */
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_pause_content_stream (surface);
+
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_select_pattern (surface, FALSE);
+    _cairo_output_stream_printf (surface->output,
+				 "0 0 %f %f re f\r\n",
+				 surface->width, surface->height);
+    _cairo_pdf_surface_close_group (surface, &source_group);
+
+    if (surface->emitted_pattern.smask.id != 0) {
+	group = source_group;
+	_cairo_pdf_surface_open_group (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "/s%d gs /x%d Do\r\n",
+				     surface->emitted_pattern.smask,
+				     group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, group);
+	if (status)
+	    return status;
+	_cairo_pdf_surface_close_group (surface, &source_group);
+    }
+
+    /* Create an smask based on the alpha component of mask_group */
+    smask = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Mask\r\n"
+				 "   /S /Alpha\r\n"
+				 "   /G %d 0 R\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 smask.id,
+				 mask_group.id);
+
+    /* Create a GState that uses the smask */
+    gstate = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /ExtGState\r\n"
+				 "   /SMask %d 0 R\r\n"
+				 "   /ca 1\r\n"
+				 "   /CA 1\r\n"
+				 "   /AIS false\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 gstate.id,
+				 smask.id);
+
+    /* Select the GState then draw the source */
+    _cairo_pdf_surface_resume_content_stream (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "q /s%d gs /x%d Do Q\r\n",
+				 gstate.id,
+				 source_group.id);
+    status = _cairo_pdf_surface_add_smask (surface, gstate);
+    if (status)
+	return status;
+    status = _cairo_pdf_surface_add_xobject (surface, source_group);
+    if (status)
+	return status;
+
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static int
 _cairo_pdf_line_cap (cairo_line_cap_t cap)
 {
     switch (cap) {
     case CAIRO_LINE_CAP_BUTT:
 	return 0;
@@ -3264,36 +3970,35 @@ static cairo_int_status_t
 			   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_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
     pdf_path_info_t info;
     cairo_status_t status;
     cairo_matrix_t m;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	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;
 
     if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_begin_group (surface, &group);
-        if (status)
-            return status;
+	_cairo_pdf_surface_pause_content_stream (surface);
+	_cairo_pdf_surface_open_group (surface);
     } else {
-        _cairo_output_stream_printf (surface->output, "q ");
+	_cairo_output_stream_printf (surface->output, "q ");
     }
 
     _cairo_pdf_surface_select_pattern (surface, TRUE);
 
     status = _cairo_pdf_surface_emit_stroke_style (surface,
 						   style);
     if (status)
 	return status;
@@ -3314,59 +4019,72 @@ static cairo_int_status_t
 					  _cairo_pdf_path_line_to,
 					  _cairo_pdf_path_curve_to,
 					  _cairo_pdf_path_close_path,
 					  &info);
 
     _cairo_output_stream_printf (surface->output, "S Q\r\n");
 
     if (surface->emitted_pattern.smask.id != 0) {
-        _cairo_pdf_surface_end_group (surface);
-
-        _cairo_output_stream_printf (surface->output,
-                                     "q /sm%d gs /res%d Do Q\r\n",
-                                     surface->emitted_pattern.smask,
-                                     group.id);
+	_cairo_pdf_surface_close_group (surface, &smask_group);
+	_cairo_pdf_surface_resume_content_stream (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     surface->emitted_pattern.smask,
+				     smask_group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+	if (status)
+	    return status;
     } else {
-        _cairo_output_stream_printf (surface->output, "Q\r\n");
+	_cairo_output_stream_printf (surface->output, "Q\r\n");
     }
 
-    return status;
+    status = _cairo_output_stream_get_status (surface->output);
+    if (status)
+	return status;
+
+    return _cairo_pdf_surface_check_content_stream_size (surface);
 }
 
 static cairo_int_status_t
 _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
     const char *pdf_operator;
     cairo_status_t status;
     pdf_path_info_t info;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
+    status = _cairo_pdf_surface_set_operator (surface, op);
+    if (status)
+	return status;
+
     status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_begin_group (surface, &group);
-        if (status)
-            return status;
+	_cairo_pdf_surface_pause_content_stream (surface);
+	_cairo_pdf_surface_open_group (surface);
     } else {
-        _cairo_output_stream_printf (surface->output, "q ");
+	_cairo_output_stream_printf (surface->output, "q ");
     }
 
     _cairo_pdf_surface_select_pattern (surface, FALSE);
     info.output = surface->output;
     info.cairo_to_pdf = &surface->cairo_to_pdf;
     info.ctm_inverse = NULL;
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -3387,41 +4105,51 @@ static cairo_int_status_t
 	ASSERT_NOT_REACHED;
     }
 
     _cairo_output_stream_printf (surface->output,
 				 "%s\r\n",
 				 pdf_operator);
 
     if (surface->emitted_pattern.smask.id != 0) {
-        _cairo_pdf_surface_end_group (surface);
-
-        _cairo_output_stream_printf (surface->output,
-                                     "q /sm%d gs /res%d Do Q\r\n",
-                                     surface->emitted_pattern.smask,
-                                     group.id);
+	_cairo_pdf_surface_close_group (surface, &smask_group);
+	_cairo_pdf_surface_resume_content_stream (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     surface->emitted_pattern.smask,
+				     smask_group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+	if (status)
+	    return status;
     } else {
-        _cairo_output_stream_printf (surface->output, "Q\r\n");
+	_cairo_output_stream_printf (surface->output, "Q\r\n");
     }
 
-    return status;
+    status = _cairo_output_stream_get_status (surface->output);
+    if (status)
+	return status;
+
+    return _cairo_pdf_surface_check_content_stream_size (surface);
 }
 
 #define GLYPH_POSITION_TOLERANCE 0.001
 
 static cairo_int_status_t
 _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
     unsigned int current_subset_id = (unsigned int)-1;
     cairo_scaled_font_subsets_glyph_t subset_glyph;
     cairo_bool_t diagonal, in_TJ;
     cairo_status_t status;
     double Tlm_x = 0, Tlm_y = 0;
     double Tm_x = 0, y;
     int i, hex_width;
 
@@ -3430,21 +4158,20 @@ static cairo_int_status_t
 
     assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
     status = _cairo_pdf_surface_emit_pattern (surface, source);
     if (status)
 	return status;
 
     if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_begin_group (surface, &group);
-        if (status)
-            return status;
+	_cairo_pdf_surface_pause_content_stream (surface);
+	_cairo_pdf_surface_open_group (surface);
     } else {
-        _cairo_output_stream_printf (surface->output, "q ");
+	_cairo_output_stream_printf (surface->output, "q ");
     }
 
     _cairo_pdf_surface_select_pattern (surface, FALSE);
 
     _cairo_output_stream_printf (surface->output,
 				 "BT\r\n");
 
     if (scaled_font->scale.xy == 0.0 &&
@@ -3473,20 +4200,23 @@ static cairo_int_status_t
                                              &y);
         }
 
 	if (subset_glyph.subset_id != current_subset_id) {
             if (in_TJ) {
                 _cairo_output_stream_printf (surface->output, ">] TJ\r\n");
                 in_TJ = FALSE;
             }
-            _cairo_output_stream_printf (surface->output,
-                                         "/CairoFont-%d-%d 1 Tf\r\n",
-                                         subset_glyph.font_id,
-                                         subset_glyph.subset_id);
+	    _cairo_output_stream_printf (surface->output,
+					 "/f-%d-%d 1 Tf\r\n",
+					 subset_glyph.font_id,
+					 subset_glyph.subset_id);
+	    _cairo_pdf_surface_add_font (surface,
+					 subset_glyph.font_id,
+					 subset_glyph.subset_id);
         }
 
         if (subset_glyph.subset_id != current_subset_id || !diagonal) {
             _cairo_output_stream_printf (surface->output,
                                          "%f %f %f %f %f %f Tm\r\n",
                                          scaled_font->scale.xx,
                                          -scaled_font->scale.yx,
                                          -scaled_font->scale.xy,
@@ -3578,41 +4308,52 @@ static cairo_int_status_t
                                          subset_glyph.subset_glyph_index);
         }
     }
 
     _cairo_output_stream_printf (surface->output,
 				 "ET\r\n");
 
     if (surface->emitted_pattern.smask.id != 0) {
-        _cairo_pdf_surface_end_group (surface);
-
-        _cairo_output_stream_printf (surface->output,
-                                     "q /sm%d gs /res%d Do Q\r\n",
-                                     surface->emitted_pattern.smask,
-                                     group.id);
+	_cairo_pdf_surface_close_group (surface, &smask_group);
+	_cairo_pdf_surface_resume_content_stream (surface);
+
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     surface->emitted_pattern.smask,
+				     smask_group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+	if (status)
+	    return status;
     } else {
-        _cairo_output_stream_printf (surface->output, "Q\r\n");
+	_cairo_output_stream_printf (surface->output, "Q\r\n");
     }
 
-    return _cairo_output_stream_get_status (surface->output);
+    status = _cairo_output_stream_get_status (surface->output);
+    if (status)
+	return status;
+
+    return _cairo_pdf_surface_check_content_stream_size (surface);
 }
 
 static void
 _cairo_pdf_surface_set_paginated_mode (void			*abstract_surface,
 				       cairo_paginated_mode_t	 paginated_mode)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
 
     surface->paginated_mode = paginated_mode;
 }
 
 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
     CAIRO_SURFACE_TYPE_PDF,
-    NULL, /* create_similar */
+    _cairo_pdf_surface_create_similar,
     _cairo_pdf_surface_finish,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* acquire_dest_image */
     NULL, /* release_dest_image */
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
--- a/gfx/cairo/cairo/src/cairo-pen.c
+++ b/gfx/cairo/cairo/src/cairo-pen.c
@@ -37,17 +37,17 @@
 #include "cairoint.h"
 
 static int
 _cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix);
 
 static void
 _cairo_pen_compute_slopes (cairo_pen_t *pen);
 
-static cairo_status_t
+static void
 _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
 
 void
 _cairo_pen_init_empty (cairo_pen_t *pen)
 {
     pen->radius = 0;
     pen->tolerance = 0;
     pen->vertices = NULL;
@@ -303,42 +303,40 @@ static void
  * NOTE: The behavior of this function is sensitive to the sense of
  * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
  *
  * The issue is that the slope_ccw member of one pen vertex will be
  * equivalent to the slope_cw member of the next pen vertex in a
  * counterclockwise order. However, for this function, we care
  * strongly about which vertex is returned.
  */
-cairo_status_t
+void
 _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
 					cairo_slope_t *slope,
 					int *active)
 {
     int i;
 
     for (i=0; i < pen->num_vertices; i++) {
 	if (_cairo_slope_clockwise (slope, &pen->vertices[i].slope_ccw)
 	    && _cairo_slope_counter_clockwise (slope, &pen->vertices[i].slope_cw))
 	    break;
     }
 
     assert (i < pen->num_vertices);
 
     *active = i;
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
 /* Find active pen vertex for counterclockwise edge of stroke at the given slope.
  *
  * NOTE: The behavior of this function is sensitive to the sense of
  * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
  */
-cairo_status_t
+void
 _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
 					 cairo_slope_t *slope,
 					 int *active)
 {
     int i;
     cairo_slope_t slope_reverse;
 
     slope_reverse = *slope;
@@ -347,28 +345,25 @@ cairo_status_t
 
     for (i=pen->num_vertices-1; i >= 0; i--) {
 	if (_cairo_slope_counter_clockwise (&pen->vertices[i].slope_ccw, &slope_reverse)
 	    && _cairo_slope_clockwise (&pen->vertices[i].slope_cw, &slope_reverse))
 	    break;
     }
 
     *active = i;
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+static void
 _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
 			       cairo_spline_t *spline,
 			       cairo_direction_t dir,
 			       cairo_polygon_t *polygon)
 {
     int i;
-    cairo_status_t status;
     int start, stop, step;
     int active = 0;
     cairo_point_t hull_point;
     cairo_slope_t slope, initial_slope, final_slope;
     cairo_point_t *point = spline->points;
     int num_points = spline->num_points;
 
     if (dir == CAIRO_DIRECTION_FORWARD) {
@@ -384,21 +379,19 @@ static cairo_status_t
 	initial_slope = spline->final_slope;
 	initial_slope.dx = -initial_slope.dx;
 	initial_slope.dy = -initial_slope.dy;
 	final_slope = spline->initial_slope;
 	final_slope.dx = -final_slope.dx;
 	final_slope.dy = -final_slope.dy;
     }
 
-    status = _cairo_pen_find_active_cw_vertex_index (pen,
-	                                             &initial_slope,
-						     &active);
-    if (status)
-	return status;
+    _cairo_pen_find_active_cw_vertex_index (pen,
+	                                    &initial_slope,
+					    &active);
 
     i = start;
     while (i != stop) {
 	hull_point.x = point[i].x + pen->vertices[active].point.x;
 	hull_point.y = point[i].y + pen->vertices[active].point.y;
 
 	_cairo_polygon_line_to (polygon, &hull_point);
 
@@ -411,18 +404,16 @@ static cairo_status_t
 		active = 0;
 	} else if (_cairo_slope_clockwise (&slope, &pen->vertices[active].slope_cw)) {
 	    if (--active == -1)
 		active = pen->num_vertices - 1;
 	} else {
 	    i += step;
 	}
     }
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
 /* Compute outline of a given spline using the pen.
    The trapezoids needed to fill that outline will be added to traps
 */
 cairo_status_t
 _cairo_pen_stroke_spline (cairo_pen_t		*pen,
 			  cairo_spline_t	*spline,
@@ -438,23 +429,19 @@ cairo_status_t
 	return CAIRO_STATUS_SUCCESS;
 
     _cairo_polygon_init (&polygon);
 
     status = _cairo_spline_decompose (spline, tolerance);
     if (status)
 	goto BAIL;
 
-    status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
-    if (status)
-	goto BAIL;
+    _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
 
-    status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
-    if (status)
-	goto BAIL;
+    _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
 
     _cairo_polygon_close (&polygon);
     status = _cairo_polygon_status (&polygon);
     if (status)
 	goto BAIL;
 
     status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
 BAIL:
--- a/gfx/cairo/cairo/src/cairo-platform.h
+++ b/gfx/cairo/cairo/src/cairo-platform.h
@@ -88,9 +88,11 @@
 #include "cairo-rename.h"
 #endif
 
 #if defined(IS_BIG_ENDIAN)
 #define WORDS_BIGENDIAN
 #define FLOAT_WORDS_BIGENDIAN
 #endif
 
+#define CAIRO_NO_MUTEX 1
+
 #endif /* CAIRO_PLATFORM_H */
--- a/gfx/cairo/cairo/src/cairo-png.c
+++ b/gfx/cairo/cairo/src/cairo-png.c
@@ -109,39 +109,41 @@ write_png (cairo_surface_t	*surface,
 {
     int i;
     volatile cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_image_surface_t *image;
     void *image_extra;
     png_struct *png;
     png_info *info;
     png_time pt;
-    png_byte **rows;
+    png_byte **rows = NULL;
     png_color_16 white;
     int png_color_type;
     int depth;
 
     status = _cairo_surface_acquire_source_image (surface,
 						  &image,
 						  &image_extra);
 
     if (status == CAIRO_STATUS_NO_MEMORY)
         return CAIRO_STATUS_NO_MEMORY;
     else if (status != CAIRO_STATUS_SUCCESS)
 	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
 
-    rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
-    if (rows == NULL) {
-        status = CAIRO_STATUS_NO_MEMORY;
-	goto BAIL1;
+    if (image->height && image->width) {
+	rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
+	if (rows == NULL) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto BAIL1;
+	}
+
+	for (i = 0; i < image->height; i++)
+	    rows[i] = (png_byte *) image->data + i * image->stride;
     }
 
-    for (i = 0; i < image->height; i++)
-	rows[i] = (png_byte *) image->data + i * image->stride;
-
     png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
 	                           png_simple_error_callback,
 	                           png_simple_warning_callback);
     if (png == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto BAIL2;
     }
 
@@ -203,17 +205,18 @@ write_png (cairo_surface_t	*surface,
 
     if (image->format == CAIRO_FORMAT_ARGB32)
 	png_set_write_user_transform_fn (png, unpremultiply_data);
     else if (image->format == CAIRO_FORMAT_RGB24)
 	png_set_write_user_transform_fn (png, convert_data_to_bytes);
     if (image->format == CAIRO_FORMAT_RGB24)
 	png_set_filler (png, 0, PNG_FILLER_AFTER);
 
-    png_write_image (png, rows);
+    if (rows)
+	png_write_image (png, rows);
     png_write_end (png, info);
 
 BAIL3:
     png_destroy_write_struct (&png, &info);
 BAIL2:
     free (rows);
 BAIL1:
     _cairo_surface_release_source_image (surface, image, image_extra);
--- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h
@@ -70,11 +70,13 @@ typedef struct cairo_ps_surface {
 
     cairo_scaled_font_subsets_t *font_subsets;
 
     cairo_array_t dsc_header_comments;
     cairo_array_t dsc_setup_comments;
     cairo_array_t dsc_page_setup_comments;
 
     cairo_array_t *dsc_comment_target;
+
+    cairo_surface_t *paginated_surface;
 } cairo_ps_surface_t;
 
 #endif /* CAIRO_PS_SURFACE_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-ps-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ps-surface.c
@@ -44,16 +44,18 @@
 #include "cairo-paginated-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
 
 #include <ctype.h>
 #include <time.h>
 #include <zlib.h>
 
+#define DEBUG_PS 0
+
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 
 /* A word wrap stream can be used as a filter to do word wrapping on
  * top of an existing output stream. The word wrapping is quite
  * simple, using isspace to determine characters that separate
  * words. Any word that will cause the column count exceed the given
  * max_column will have a '\n' character emitted before it.
@@ -173,17 +175,17 @@ static cairo_status_t
 _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
 {
     ps_path_info_t *path_info = closure;
 
     path_info->last_move_to_point = *point;
     path_info->has_sub_path = FALSE;
 
     _cairo_output_stream_printf (path_info->stream,
-				 "%f %f moveto ",
+				 "%f %f M ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
@@ -196,17 +198,17 @@ static cairo_status_t
 	point->y == path_info->last_move_to_point.y)
     {
 	return CAIRO_STATUS_SUCCESS;
     }
 
     path_info->has_sub_path = TRUE;
 
     _cairo_output_stream_printf (path_info->stream,
-				 "%f %f lineto ",
+				 "%f %f L ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_surface_path_curve_to (void          *closure,
@@ -214,17 +216,17 @@ static cairo_status_t
 				 cairo_point_t *c,
 				 cairo_point_t *d)
 {
     ps_path_info_t *path_info = closure;
 
     path_info->has_sub_path = TRUE;
 
     _cairo_output_stream_printf (path_info->stream,
-				 "%f %f %f %f %f %f curveto ",
+				 "%f %f %f %f %f %f C ",
 				 _cairo_fixed_to_double (b->x),
 				 _cairo_fixed_to_double (b->y),
 				 _cairo_fixed_to_double (c->x),
 				 _cairo_fixed_to_double (c->y),
 				 _cairo_fixed_to_double (d->x),
 				 _cairo_fixed_to_double (d->y));
 
     return CAIRO_STATUS_SUCCESS;
@@ -237,17 +239,17 @@ static cairo_status_t
 
     if (path_info->line_cap != CAIRO_LINE_CAP_ROUND &&
 	! path_info->has_sub_path)
     {
 	return CAIRO_STATUS_SUCCESS;
     }
 
     _cairo_output_stream_printf (path_info->stream,
-				 "closepath\n");
+				 "P\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* The line cap value is needed to workaround the fact that PostScript
  * semantics for stroking degenerate sub-paths do not match cairo
  * semantics. (PostScript draws something for any line cap value,
  * while cairo draws something only for round caps).
@@ -374,18 +376,20 @@ static cairo_status_t
     snprintf (name, sizeof name, "CairoFont-%d-%d",
 	      font_subset->font_id, font_subset->subset_id);
     status = _cairo_type1_subset_init (&subset, name, font_subset, TRUE);
     if (status)
 	return status;
 
     /* FIXME: Figure out document structure convention for fonts */
 
+#if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_type1_font_subset\n");
+#endif
 
     length = subset.header_length + subset.data_length + subset.trailer_length;
     _cairo_output_stream_write (surface->final_stream, subset.data, length);
 
     _cairo_type1_subset_fini (&subset);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -403,18 +407,20 @@ static cairo_status_t
     snprintf (name, sizeof name, "CairoFont-%d-%d",
 	      font_subset->font_id, font_subset->subset_id);
     status = _cairo_type1_fallback_init_hex (&subset, name, font_subset);
     if (status)
 	return status;
 
     /* FIXME: Figure out document structure convention for fonts */
 
+#if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_type1_font_fallback\n");
+#endif
 
     length = subset.header_length + subset.data_length + subset.trailer_length;
     _cairo_output_stream_write (surface->final_stream, subset.data, length);
 
     _cairo_type1_fallback_fini (&subset);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -430,18 +436,20 @@ static cairo_status_t
     unsigned int i, begin, end;
 
     status = _cairo_truetype_subset_init (&subset, font_subset);
     if (status)
 	return status;
 
     /* FIXME: Figure out document structure convention for fonts */
 
+#if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_truetype_font_subset\n");
+#endif
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "11 dict begin\n"
 				 "/FontType 42 def\n"
 				 "/FontName /CairoFont-%d-%d def\n"
 				 "/PaintType 0 def\n"
 				 "/FontMatrix [ 1 0 0 1 0 0 ] def\n"
 				 "/FontBBox [ 0 0 0 0 ] def\n"
@@ -569,22 +577,22 @@ static cairo_int_status_t
 				 "   /ImageType 1\n"
 				 "   /Width %d\n"
 				 "   /Height %d\n"
 				 "   /ImageMatrix [%f %f %f %f %f %f]\n"
 				 "   /Decode [1 0]\n"
 				 "   /BitsPerComponent 1\n",
 				 image->width,
 				 image->height,
-				 image->base.device_transform_inverse.xx,
-				 image->base.device_transform_inverse.yx,
-				 image->base.device_transform_inverse.xy,
-				 image->base.device_transform_inverse.yy,
-				 image->base.device_transform_inverse.x0,
-				 image->base.device_transform_inverse.y0);
+				 image->base.device_transform.xx,
+				 image->base.device_transform.yx,
+				 image->base.device_transform.xy,
+				 image->base.device_transform.yy,
+				 image->base.device_transform.x0,
+				 image->base.device_transform.y0);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "   /DataSource   {<");
     for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
 	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
 	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
 	    _cairo_output_stream_printf (surface->final_stream, "%02x ", output_byte);
 	}
@@ -637,18 +645,20 @@ static cairo_status_t
 					  cairo_scaled_font_subset_t	*font_subset)
 
 
 {
     cairo_status_t status;
     cairo_matrix_t matrix;
     unsigned int i;
 
+#if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_type3_font_subset\n");
+#endif
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "/CairoFont-%d-%d <<\n",
 				 font_subset->font_id,
 				 font_subset->subset_id);
 
     matrix = font_subset->scaled_font->scale;
     status = cairo_matrix_invert (&matrix);
@@ -719,18 +729,20 @@ static void
 	return;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
 {
     cairo_status_t status;
 
+#if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_font_subsets\n");
+#endif
 
     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);
@@ -800,20 +812,21 @@ static cairo_surface_t *
     surface->num_pages = 0;
 
     _cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
     _cairo_array_init (&surface->dsc_setup_comments, sizeof (char *));
     _cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *));
 
     surface->dsc_comment_target = &surface->dsc_header_comments;
 
-    return _cairo_paginated_surface_create (&surface->base,
-					    CAIRO_CONTENT_COLOR_ALPHA,
-					    width, height,
-					    &cairo_ps_surface_paginated_backend);
+    surface->paginated_surface = _cairo_paginated_surface_create (&surface->base,
+								   CAIRO_CONTENT_COLOR_ALPHA,
+								   width, height,
+								   &cairo_ps_surface_paginated_backend);
+    return surface->paginated_surface;
 
  CLEANUP_OUTPUT_STREAM:
     status = _cairo_output_stream_destroy (surface->stream);
     /* Ignore status---we're already on a failure path. */
  CLEANUP_TMPFILE:
     fclose (surface->tmpfile);
  CLEANUP_SURFACE:
     free (surface);
@@ -971,16 +984,21 @@ cairo_ps_surface_set_size (cairo_surface
     status = _extract_ps_surface (surface, &ps_surface);
     if (status) {
 	_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
     }
 
     ps_surface->width = width_in_points;
     ps_surface->height = height_in_points;
+    status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface,
+						width_in_points,
+						height_in_points);
+    if (status)
+	_cairo_surface_set_error (surface, status);
 }
 
 /**
  * cairo_ps_surface_dsc_comment:
  * @surface: a PostScript cairo_surface_t
  * @comment: a comment string to be emitted into the PostScript output
  *
  * Emit a comment into the PostScript output for the given surface.
@@ -1250,17 +1268,17 @@ static cairo_int_status_t
 
     _cairo_output_stream_printf (surface->stream,
 				 "%%%%PageBoundingBox: %d %d %d %d\n",
 				 0, 0,
 				 (int) ceil (surface->width),
 				 (int) ceil (surface->height));
 
     _cairo_output_stream_printf (surface->stream,
-				 "gsave %f %f translate 1.0 -1.0 scale \n",
+				 "gsave %f %f translate 1.0 -1.0 scale gsave\n",
 				 0.0, surface->height);
 
     _cairo_output_stream_printf (surface->stream,
 				 "%%%%EndPageSetup\n");
 
     if (surface->width > surface->max_width)
 	surface->max_width = surface->width;
     if (surface->height > surface->max_height)
@@ -1268,29 +1286,17 @@ static cairo_int_status_t
 
     return _cairo_output_stream_get_status (surface->stream);
 }
 
 static void
 _cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
 {
     _cairo_output_stream_printf (surface->stream,
-				 "grestore\n");
-}
-
-static cairo_int_status_t
-_cairo_ps_surface_copy_page (void *abstract_surface)
-{
-    cairo_ps_surface_t *surface = abstract_surface;
-
-    _cairo_ps_surface_end_page (surface);
-
-    _cairo_output_stream_printf (surface->stream, "copypage\n");
-
-    return CAIRO_STATUS_SUCCESS;
+				 "grestore grestore\n");
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_show_page (void *abstract_surface)
 {
     cairo_ps_surface_t *surface = abstract_surface;
 
     _cairo_ps_surface_end_page (surface);
@@ -1354,44 +1360,63 @@ pattern_supported (const cairo_pattern_t
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
 	return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
 
     return FALSE;
 }
 
 static cairo_int_status_t
-_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
-		      cairo_operator_t op,
-		      const cairo_pattern_t *pattern)
+_cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
+				     cairo_operator_t       op,
+				     const cairo_pattern_t *pattern)
 {
-    if (surface->force_fallbacks)
-	return FALSE;
+    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (! pattern_supported (pattern))
-	return FALSE;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op == CAIRO_OPERATOR_SOURCE)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (op != CAIRO_OPERATOR_OVER)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
+     * the pattern contains transparency, we return
+     * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
+     * surface. If the analysis surface determines that there is
+     * anything drawn under this operation, a fallback image will be
+     * used. Otherwise the operation will be replayed during the
+     * render stage and we blend the transarency into the white
+     * background to convert the pattern to opaque.
+     */
 
     if (_cairo_operator_always_opaque (op))
-	return TRUE;
+	return CAIRO_STATUS_SUCCESS;
 
     if (_cairo_operator_always_translucent (op))
-	return FALSE;
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
-    return _cairo_pattern_is_opaque (pattern);
+    if (_cairo_pattern_is_opaque (pattern))
+	return CAIRO_STATUS_SUCCESS;
+    else
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 }
 
-static cairo_int_status_t
-_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
-		    cairo_operator_t op,
-		    const cairo_pattern_t *pattern)
+static cairo_bool_t
+_cairo_ps_surface_operation_supported (cairo_ps_surface_t    *surface,
+				       cairo_operator_t       op,
+				       const cairo_pattern_t *pattern)
 {
-    if (_cairo_ps_surface_operation_supported (surface, op, pattern))
-	return CAIRO_STATUS_SUCCESS;
+    if (_cairo_ps_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
+	return TRUE;
     else
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return FALSE;
 }
 
 /* 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
  * characters in a string to represent a single ASCII85 byte, (for the
  * escape sequences "\\", "\(", and "\)") and we must not split these
  * across two strings. So we'd be in trouble if we went right to the
@@ -1509,18 +1534,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
 _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
-	    cairo_image_surface_t *image,
-	    const char		  *name)
+			      cairo_image_surface_t *image,
+			      const char	    *name)
 {
     cairo_status_t status, status2;
     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;
     int x, y, i;
@@ -1654,34 +1679,47 @@ static cairo_status_t
  bail1:
     if (opaque_image != image)
 	cairo_surface_destroy (opaque);
  bail0:
     return status;
 }
 
 static void
-_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
-		    cairo_solid_pattern_t *pattern)
+_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t    *surface,
+				      cairo_solid_pattern_t *pattern)
 {
-    if (color_is_gray (&pattern->color))
+    cairo_color_t *color = &pattern->color;
+    double red, green, blue;
+
+    red = color->red;
+    green = color->green;
+    blue = color->blue;
+
+    if (!CAIRO_COLOR_IS_OPAQUE(color)) {
+	uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
+
+	red   = ((color->red_short   >> 8) + one_minus_alpha) / 255.0;
+	green = ((color->green_short >> 8) + one_minus_alpha) / 255.0;
+	blue  = ((color->blue_short  >> 8) + one_minus_alpha) / 255.0;
+    }
+
+    if (color_is_gray (color))
 	_cairo_output_stream_printf (surface->stream,
 				     "%f G\n",
-				     pattern->color.red);
+				     red);
     else
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f %f R\n",
-				     pattern->color.red,
-				     pattern->color.green,
-				     pattern->color.blue);
+				     red, green, blue);
 }
 
 static cairo_status_t
-_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
-		      cairo_surface_pattern_t *pattern)
+_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
+					cairo_surface_pattern_t *pattern)
 {
     cairo_status_t status;
     double bbox_width, bbox_height;
     double xstep, ystep;
     cairo_matrix_t inverse = pattern->base.matrix;
 
     status = cairo_matrix_invert (&inverse);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
@@ -1841,21 +1879,23 @@ static cairo_int_status_t
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_status_t status;
     const char *ps_operator;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return CAIRO_STATUS_SUCCESS;
 
+#if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_intersect_clip_path\n");
+#endif
 
     if (path == NULL) {
-	_cairo_output_stream_printf (stream, "initclip\n");
+	_cairo_output_stream_printf (stream, "grestore gsave\n");
 	return CAIRO_STATUS_SUCCESS;
     }
 
     /* 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) {
@@ -1914,28 +1954,22 @@ static cairo_int_status_t
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_rectangle_int_t extents, pattern_extents;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	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 (_cairo_ps_surface_operation_supported (op, source));
-    */
+    assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
+#if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_paint\n");
+#endif
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status)
 	return status;
 
     status = _cairo_pattern_get_extents (source, &pattern_extents);
     if (status)
 	return status;
@@ -2012,19 +2046,20 @@ static cairo_int_status_t
     int num_dashes = style->num_dashes;
     double dash_offset = style->dash_offset;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
-
+#if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_stroke\n");
+#endif
 
     /* 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
      * case. That's not what the cairo semantics want, so we first
      * touch up the array to eliminate any 0.0 values that will
      * result in "on" segments.
      */
@@ -2143,18 +2178,20 @@ static cairo_int_status_t
     cairo_int_status_t status;
     const char *ps_operator;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
+#if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_fill\n");
+#endif
 
     _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) {
@@ -2201,18 +2238,20 @@ static cairo_int_status_t
     cairo_bool_t vertical, horizontal;
     cairo_output_stream_t *word_wrap;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
+#if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_show_glyphs\n");
+#endif
 
     if (num_glyphs <= 0)
         return CAIRO_STATUS_SUCCESS;
 
     num_glyphs_unsigned = num_glyphs;
 
     _cairo_ps_surface_emit_pattern (surface, source);
     glyph_ids = _cairo_malloc_ab (num_glyphs_unsigned, sizeof (cairo_ps_glyph_id_t));
@@ -2228,19 +2267,18 @@ static cairo_int_status_t
         glyph_ids[i].subset_id = subset_glyph.subset_id;
         glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index;
     }
 
     i = 0;
     while (i < num_glyphs_unsigned) {
         if (glyph_ids[i].subset_id != current_subset_id) {
             _cairo_output_stream_printf (surface->stream,
-                                         "/CairoFont-%d-%d findfont\n"
-                                         "[ %f %f %f %f 0 0 ] makefont\n"
-                                         "setfont\n",
+                                         "/CairoFont-%d-%d "
+                                         "[ %f %f %f %f 0 0 ] selectfont\n",
                                          subset_glyph.font_id,
                                          glyph_ids[i].subset_id,
                                          scaled_font->scale.xx,
                                          scaled_font->scale.yx,
                                          -scaled_font->scale.xy,
                                          -scaled_font->scale.yy);
             current_subset_id = glyph_ids[i].subset_id;
         }
@@ -2338,17 +2376,17 @@ static const cairo_surface_backend_t cai
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* acquire_dest_image */
     NULL, /* release_dest_image */
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
-    _cairo_ps_surface_copy_page,
+    NULL, /* cairo_ps_surface_copy_page */
     _cairo_ps_surface_show_page,
     NULL, /* set_clip_region */
     _cairo_ps_surface_intersect_clip_path,
     _cairo_ps_surface_get_extents,
     NULL, /* old_show_glyphs */
     _cairo_ps_surface_get_font_options,
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
@@ -33,17 +33,17 @@
  * 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>
+#include "cairoint.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include <cairo-quartz.h>
 
 typedef struct cairo_quartz_surface {
     cairo_surface_t base;
 
     void *imageData;
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -1676,24 +1676,16 @@ cairo_quartz_surface_create (cairo_forma
     cairo_quartz_surface_t *surf;
     CGContextRef cgc;
     CGColorSpaceRef cgColorspace;
     CGBitmapInfo bitinfo;
     void *imageData;
     int stride;
     int bitsPerComponent;
 
-    unsigned int realWidth = width;
-    unsigned int realHeight = height;
-
-    if (width == 0)
-	width = 1;
-    if (height == 0)
-	height = 1;
-
     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;
@@ -1740,17 +1732,17 @@ cairo_quartz_surface_create (cairo_forma
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     /* flip the Y axis */
     CGContextTranslateCTM (cgc, 0.0, height);
     CGContextScaleCTM (cgc, 1.0, -1.0);
 
     surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
-						  realWidth, realHeight);
+						   width, height);
     if (!surf) {
 	CGContextRelease (cgc);
 	// create_internal will have set an error
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     surf->imageData = imageData;
 
--- a/gfx/cairo/cairo/src/cairo-region-private.h
+++ b/gfx/cairo/cairo/src/cairo-region-private.h
@@ -32,21 +32,17 @@
  *
  * Contributor(s):
  *	Vladimir Vukicevic <vladimir@pobox.com>
  */
 
 #ifndef CAIRO_REGION_PRIVATE_H
 #define CAIRO_REGION_PRIVATE_H
 
-#ifdef MOZ_TREE_CAIRO
-#include "pixman.h"
-#else
-#include <pixman/pixman.h>
-#endif
+#include <pixman.h>
 
 /* cairo_region_t is defined in cairoint.h */
 
 struct _cairo_region {
     pixman_region16_t rgn;
 };
 
 cairo_private void
@@ -101,9 +97,13 @@ cairo_private cairo_int_status_t
 
 cairo_private cairo_bool_t
 _cairo_region_not_empty (cairo_region_t *region);
 
 cairo_private void
 _cairo_region_translate (cairo_region_t *region,
 			 int x, int y);
 
+cairo_private pixman_region_overlap_t
+_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box);
+
+
 #endif /* CAIRO_REGION_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-region.c
+++ b/gfx/cairo/cairo/src/cairo-region.c
@@ -202,8 +202,21 @@ cairo_bool_t
 }
 
 void
 _cairo_region_translate (cairo_region_t *region,
 			 int x, int y)
 {
     pixman_region_translate (&region->rgn, x, y);
 }
+
+pixman_region_overlap_t
+_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *rect)
+{
+    pixman_box16_t pbox;
+
+    pbox.x1 = rect->x;
+    pbox.y1 = rect->y;
+    pbox.x2 = rect->x + rect->width;
+    pbox.y2 = rect->y + rect->height;
+
+    return pixman_region_contains_rectangle (&region->rgn, &pbox);
+}
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -1,9 +1,8 @@
-#define _cairo_image_surface_nil_invalid_format __moz__cairo_image_surface_nil_invalid_format
 #define cairo_append_path _moz_cairo_append_path
 #define cairo_arc _moz_cairo_arc
 #define cairo_arc_negative _moz_cairo_arc_negative
 #define cairo_arc_to _moz_cairo_arc_to
 #define cairo_atsui_font_face_create_for_atsu_font_id _moz_cairo_atsui_font_face_create_for_atsu_font_id
 #define cairo_beos_surface_create _moz_cairo_beos_surface_create
 #define cairo_beos_surface_create_for_bitmap _moz_cairo_beos_surface_create_for_bitmap
 #define cairo_clip _moz_cairo_clip
@@ -215,32 +214,34 @@
 #define cairo_show_page _moz_cairo_show_page
 #define cairo_show_text _moz_cairo_show_text
 #define cairo_status _moz_cairo_status
 #define cairo_status_to_string _moz_cairo_status_to_string
 #define cairo_stroke _moz_cairo_stroke
 #define cairo_stroke_extents _moz_cairo_stroke_extents
 #define cairo_stroke_preserve _moz_cairo_stroke_preserve
 #define cairo_stroke_to_path _moz_cairo_stroke_to_path
+#define cairo_surface_copy_page _moz_cairo_surface_copy_page
 #define cairo_surface_create_similar _moz_cairo_surface_create_similar
 #define cairo_surface_destroy _moz_cairo_surface_destroy
 #define cairo_surface_finish _moz_cairo_surface_finish
 #define cairo_surface_flush _moz_cairo_surface_flush
 #define cairo_surface_get_content _moz_cairo_surface_get_content
 #define cairo_surface_get_device_offset _moz_cairo_surface_get_device_offset
 #define cairo_surface_get_font_options _moz_cairo_surface_get_font_options
 #define cairo_surface_get_reference_count _moz_cairo_surface_get_reference_count
 #define cairo_surface_get_type _moz_cairo_surface_get_type
 #define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
 #define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
 #define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle
 #define cairo_surface_reference _moz_cairo_surface_reference
 #define cairo_surface_set_device_offset _moz_cairo_surface_set_device_offset
 #define cairo_surface_set_fallback_resolution _moz_cairo_surface_set_fallback_resolution
 #define cairo_surface_set_user_data _moz_cairo_surface_set_user_data
+#define cairo_surface_show_page _moz_cairo_surface_show_page
 #define cairo_surface_status _moz_cairo_surface_status
 #define cairo_surface_write_to_png _moz_cairo_surface_write_to_png
 #define cairo_surface_write_to_png_stream _moz_cairo_surface_write_to_png_stream
 #define cairo_svg_get_versions _moz_cairo_svg_get_versions
 #define cairo_svg_surface_create _moz_cairo_svg_surface_create
 #define cairo_svg_surface_create_for_stream _moz_cairo_svg_surface_create_for_stream
 #define cairo_svg_surface_restrict_to_version _moz_cairo_svg_surface_restrict_to_version
 #define cairo_svg_version_to_string _moz_cairo_svg_version_to_string
--- a/gfx/cairo/cairo/src/cairo-scaled-font.c
+++ b/gfx/cairo/cairo/src/cairo-scaled-font.c
@@ -29,21 +29,127 @@
  *
  * The Initial Developer of the Original Code is Keith Packard
  *
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
  *	Carl D. Worth <cworth@cworth.org>
  *      Graydon Hoare <graydon@redhat.com>
  *      Owen Taylor <otaylor@redhat.com>
+ *      Behdad Esfahbod <behdad@behdad.org>
  */
 
 #include "cairoint.h"
 #include "cairo-scaled-font-private.h"
 
+/*
+ *  NOTES:
+ *
+ *  To store rasterizations of glyphs, we use an image surface and the
+ *  device offset to represent the glyph origin.
+ *
+ *  A device_transform converts from device space (a conceptual space) to
+ *  surface space.  For simple cases of translation only, it's called a
+ *  device_offset and is public API (cairo_surface_[gs]et_device_offset).
+ *  A possibly better name for those functions could have been
+ *  cairo_surface_[gs]et_origing.  So, that's what they do: they set where
+ *  the device-space origin (0,0) is in the surface.  If the origin is inside
+ *  the surface, device_offset values are positive.  It may look like this:
+ *
+ *  Device space:
+ *        (-x,-y) <-- negative numbers
+ *           +----------------+
+ *           |      .         |
+ *           |      .         |
+ *           |......(0,0) <---|-- device-space origin
+ *           |                |
+ *           |                |
+ *           +----------------+
+ *                    (width-x,height-y)
+ *
+ *  Surface space:
+ *         (0,0) <-- surface-space origin
+ *           +---------------+
+ *           |      .        |
+ *           |      .        |
+ *           |......(x,y) <--|-- device_offset
+ *           |               |
+ *           |               |
+ *           +---------------+
+ *                     (width,height)
+ *
+ *  In other words: device_offset is the coordinates of the device-space
+ *  origin relative to the top-left of the surface.
+ *
+ *  We use device offsets in a couple of places:
+ *
+ *    - Public API: To let toolkits like Gtk+ give user a surface that
+ *      only represents part of the final destination (say, the expose
+ *      area), but has the same device space as the destination.  In these
+ *      cases device_offset is typically negative.  Example:
+ *
+ *           application window
+ *           +---------------+
+ *           |      .        |
+ *           | (x,y).        |
+ *           |......+---+    |
+ *           |      |   | <--|-- expose area
+ *           |      +---+    |
+ *           +---------------+
+ *
+ *      In this case, the user of cairo API can set the device_space on
+ *      the expose area to (-x,-y) to move the device space origin to that
+ *      of the application window, such that drawing in the expose area
+ *      surface and painting it in the application window has the same
+ *      effect as drawing in the application window directly.  Gtk+ has
+ *      been using this feature.
+ *
+ *    - Glyph surfaces: In most font rendering systems, glyph surfaces
+ *      have an origin at (0,0) and a bounding box that is typically
+ *      represented as (x_bearing,y_bearing,width,height).  Depending on
+ *      which way y progresses in the system, y_bearing may typically be
+ *      negative (for systems similar to cairo, with origin at top left),
+ *      or be positive (in systems like PDF with origin at bottom left).
+ *      No matter which is the case, it is important to note that
+ *      (x_bearing,y_bearing) is the coordinates of top-left of the glyph
+ *      relative to the glyph origin.  That is, for example:
+ *
+ *      Scaled-glyph space:
+ *
+ *        (x_bearing,y_bearing) <-- negative numbers
+ *           +----------------+
+ *           |      .         |
+ *           |      .         |
+ *           |......(0,0) <---|-- glyph origin
+ *           |                |
+ *           |                |
+ *           +----------------+
+ *                    (width+x_bearing,height+y_bearing)
+ *
+ *      Note the similarity of the origin to the device space.  That is
+ *      exactly how we use the device_offset to represent scaled glyphs:
+ *      to use the device-space origin as the glyph origin.
+ *
+ *  Now compare the scaled-glyph space to device-space and surface-space
+ *  and convince yourself that:
+ *
+ *  	(x_bearing,y_bearing) = (-x,-y) = - device_offset
+ *
+ *  That's right.  If you are not convinced yet, contrast the definition
+ *  of the two:
+ *
+ *  	"(x_bearing,y_bearing) is the coordinates of top-left of the
+ *  	 glyph relative to the glyph origin."
+ *
+ *  	"In other words: device_offset is the coordinates of the
+ *  	 device-space origin relative to the top-left of the surface."
+ *
+ *  and note that glyph origin = device-space origin.
+ */
+
 static cairo_bool_t
 _cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
 {
     const cairo_scaled_glyph_t *key_a = abstract_key_a;
     const cairo_scaled_glyph_t *key_b = abstract_key_b;
 
     return (_cairo_scaled_glyph_index (key_a) ==
 	    _cairo_scaled_glyph_index (key_b));
@@ -292,24 +398,26 @@ static void
 			     const cairo_font_options_t *options)
 {
     uint32_t hash = FNV1_32_INIT;
 
     scaled_font->status = CAIRO_STATUS_SUCCESS;
     scaled_font->font_face = font_face;
     scaled_font->font_matrix = *font_matrix;
     scaled_font->ctm = *ctm;
+    /* ignore translation values in the ctm */
+    scaled_font->ctm.x0 = 0.;
+    scaled_font->ctm.y0 = 0.;
     scaled_font->options = *options;
 
-    /* We do a bytewise hash on the font matrices, ignoring the
-     * translation values in the ctm */
+    /* We do a bytewise hash on the font matrices */
     hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx),
 			    sizeof(cairo_matrix_t), hash);
     hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx),
-			    sizeof(double) * 4, hash);
+			    sizeof(cairo_matrix_t), hash);
 
     hash ^= (unsigned long) scaled_font->font_face;
 
     hash ^= cairo_font_options_hash (&scaled_font->options);
 
     scaled_font->hash_entry.hash = hash;
 }
 
@@ -1103,20 +1211,18 @@ cairo_status_t
 	    if (glyph_surface->format == CAIRO_FORMAT_ARGB32)
 		pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
 						  pixman_image, TRUE);
 
 	}
 
 	/* round glyph locations to the nearest pixel */
 	/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
-	x = _cairo_lround (glyphs[i].x +
-                           glyph_surface->base.device_transform.x0);
-	y = _cairo_lround (glyphs[i].y +
-                           glyph_surface->base.device_transform.y0);
+	x = _cairo_lround (glyphs[i].x - glyph_surface->base.device_transform.x0);
+	y = _cairo_lround (glyphs[i].y - glyph_surface->base.device_transform.y0);
 
 	_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
 
 	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
 					   &glyph_pattern.base,
 					   NULL,
 					   mask,
 					   0, 0,
@@ -1281,17 +1387,17 @@ static cairo_status_t
 
     bytes_per_row = (a1_mask->width + 7) / 8;
     for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) {
 	for (x = 0, byte_ptr = row, cols = (a1_mask->width + 7) / 8; cols; byte_ptr++, cols--) {
 	    byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
 	    for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
 		if (byte & (1 << bit)) {
 		    status = _add_unit_rectangle_to_path (path,
-							  x + xoff, y + yoff);
+							  x - xoff, y - yoff);
 		    if (status)
 			return status;
 		}
 	    }
 	}
     }
 
     if (a1_mask != mask)
--- a/gfx/cairo/cairo/src/cairo-surface-fallback.c
+++ b/gfx/cairo/cairo/src/cairo-surface-fallback.c
@@ -1066,17 +1066,17 @@ cairo_surface_t *
 
     _cairo_pattern_fini (&pattern.base);
     if (status) {
 	cairo_surface_destroy (snapshot);
 	return (cairo_surface_t *) &_cairo_surface_nil;
     }
 
     _cairo_surface_release_source_image (surface,
-					 image, &image_extra);
+					 image, image_extra);
 
     snapshot->device_transform = surface->device_transform;
     snapshot->device_transform_inverse = surface->device_transform_inverse;
 
     snapshot->is_snapshot = TRUE;
 
     return snapshot;
 }
@@ -1259,37 +1259,41 @@ cairo_status_t
 				       cairo_surface_t	*src,
 				       int		 src_x,
 				       int		 src_y,
 				       int		 width,
 				       int		 height,
 				       cairo_surface_t **clone_out)
 {
     cairo_status_t status;
-    cairo_pattern_union_t src_pattern;
     cairo_surface_t *new_surface = NULL;
+    cairo_t *cr;
 
     new_surface = _cairo_surface_create_similar_scratch (surface,
 							 cairo_surface_get_content (src),
 							 width, height);
     if (new_surface->status)
 	return new_surface->status;
 
-    _cairo_pattern_init_for_surface (&src_pattern.surface, src);
+    /* We have to copy these here, so that the coordinate spaces are correct */
+    new_surface->device_transform = src->device_transform;
+    new_surface->device_transform_inverse = src->device_transform_inverse;
 
-    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
-				       &src_pattern.base,
-				       NULL,
-				       new_surface,
-				       src_x, src_y,
-				       0, 0,
-				       0, 0,
-				       width, height);
-
-    _cairo_pattern_fini (&src_pattern.base);
+    /* We can't use _cairo_composite directly, because backends that
+     * implement the "high-level" API may not have it implemented.
+     * (For example, SVG.)  We can fix this by either checking if the
+     * destination supports composite first, or we can make clone a
+     * required "high-level" operation.
+     */
+    cr = cairo_create (new_surface);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_surface (cr, src, -src_x, -src_y);
+    cairo_paint (cr);
+    status = cairo_status (cr);
+    cairo_destroy (cr);
 
     if (status == CAIRO_STATUS_SUCCESS)
 	*clone_out = new_surface;
-    else if (new_surface)
+    else
 	cairo_surface_destroy (new_surface);
 
     return status;
 }
--- a/gfx/cairo/cairo/src/cairo-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-surface-private.h
@@ -55,16 +55,24 @@ struct _cairo_surface {
     unsigned int ref_count;
     cairo_status_t status;
     cairo_bool_t finished;
     cairo_user_data_array_t user_data;
 
     cairo_matrix_t device_transform;
     cairo_matrix_t device_transform_inverse;
 
+    /* The actual resolution of the device, in dots per inch. */
+    double x_resolution;
+    double y_resolution;
+
+    /* The resolution that should be used when generating image-based
+     * fallback; generally only used by the analysis/paginated
+     * surfaces
+     */
     double x_fallback_resolution;
     double y_fallback_resolution;
 
     cairo_clip_t *clip;
 
     /*
      * Each time a clip region is modified, it gets the next value in this
      * sequence.  This means that clip regions for this surface are uniquely
--- a/gfx/cairo/cairo/src/cairo-surface.c
+++ b/gfx/cairo/cairo/src/cairo-surface.c
@@ -57,16 +57,18 @@ const cairo_surface_t name = {					\
     { 1.0, 0.0,							\
       0.0, 1.0,							\
       0.0, 0.0							\
     },					/* device_transform */	\
     { 1.0, 0.0,							\
       0.0, 1.0,							\
       0.0, 0.0							\
     },					/* device_transform_inverse */	\
+    0.0,				/* x_resolution */	\
+    0.0,				/* y_resolution */	\
     0.0,				/* x_fallback_resolution */	\
     0.0,				/* y_fallback_resolution */	\
     NULL,				/* clip */		\
     0,					/* next_clip_serial */	\
     0,					/* current_clip_serial */	\
     FALSE,				/* is_snapshot */	\
     FALSE,				/* has_font_options */	\
     { CAIRO_ANTIALIAS_DEFAULT,					\
@@ -190,16 +192,19 @@ void
     surface->status = CAIRO_STATUS_SUCCESS;
     surface->finished = FALSE;
 
     _cairo_user_data_array_init (&surface->user_data);
 
     cairo_matrix_init_identity (&surface->device_transform);
     cairo_matrix_init_identity (&surface->device_transform_inverse);
 
+    surface->x_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
+    surface->y_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
+
     surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
     surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
 
     surface->clip = NULL;
     surface->next_clip_serial = 0;
     surface->current_clip_serial = 0;
 
     surface->is_snapshot = FALSE;
@@ -1019,56 +1024,59 @@ cairo_status_t
 _cairo_surface_clone_similar (cairo_surface_t  *surface,
 			      cairo_surface_t  *src,
 			      int               src_x,
 			      int               src_y,
 			      int               width,
 			      int               height,
 			      cairo_surface_t **clone_out)
 {
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     cairo_image_surface_t *image;
     void *image_extra;
 
     if (surface->finished)
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
-    if (surface->backend->clone_similar == NULL)
-	return (cairo_int_status_t)
-	    _cairo_surface_fallback_clone_similar (surface, src,
-						   src_x, src_y,
-						   width, height,
-						   clone_out);
+    if (surface->backend->clone_similar) {
+	status = surface->backend->clone_similar (surface, src, src_x, src_y,
+						  width, height, clone_out);
+
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	    /* If we failed, try again with an image surface */
+	    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
+	    if (status == CAIRO_STATUS_SUCCESS) {
+		status =
+		    surface->backend->clone_similar (surface, &image->base,
+						     src_x, src_y,
+						     width, height,
+						     clone_out);
 
-    status = surface->backend->clone_similar (surface, src, src_x, src_y,
-					      width, height, clone_out);
-    if (status == CAIRO_STATUS_SUCCESS && *clone_out != src)
-        (*clone_out)->device_transform = src->device_transform;
+		_cairo_surface_release_source_image (src, image, image_extra);
+	    }
+	}
+    }
 
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+    /* If we're still unsupported, hit our fallback path to get a clone */
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	status =
+	    _cairo_surface_fallback_clone_similar (surface, src, src_x, src_y,
+						   width, height, clone_out);
+
+    /* We should never get UNSUPPORTED here, so if we have an error, bail. */
+    if (status)
 	return status;
 
-    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
-    if (status != CAIRO_STATUS_SUCCESS)
-	return status;
-
-    status = surface->backend->clone_similar (surface, &image->base, src_x,
-					      src_y, width, height, clone_out);
-    if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) {
+    /* Update the clone's device_transform (which the underlying surface
+     * backend knows nothing about) */
+    if (*clone_out != src) {
         (*clone_out)->device_transform = src->device_transform;
         (*clone_out)->device_transform_inverse = src->device_transform_inverse;
-    }
+    }	
 
-    /* If the above failed point, we could implement a full fallback
-     * using acquire_dest_image, but that's going to be very
-     * inefficient compared to a backend-specific implementation of
-     * clone_similar() with an image source. So we don't bother
-     */
-
-    _cairo_surface_release_source_image (src, image, image_extra);
     return status;
 }
 
 /* XXX: Shouldn't really need to do this here. */
 #include "cairo-meta-surface-private.h"
 
 /**
  * _cairo_surface_snapshot
@@ -1386,16 +1394,75 @@ cairo_status_t
  CLEANUP_SOURCE:
     _cairo_pattern_fini (&dev_source.base);
  FINISH:
 
     return status;
 }
 
 cairo_status_t
+_cairo_surface_fill_stroke (cairo_surface_t	    *surface,
+			    cairo_operator_t	     fill_op,
+			    cairo_pattern_t	    *fill_source,
+			    cairo_fill_rule_t	     fill_rule,
+			    double		     fill_tolerance,
+			    cairo_antialias_t	     fill_antialias,
+			    cairo_path_fixed_t	    *path,
+			    cairo_operator_t	     stroke_op,
+			    cairo_pattern_t	    *stroke_source,
+			    cairo_stroke_style_t    *stroke_style,
+			    cairo_matrix_t	    *stroke_ctm,
+			    cairo_matrix_t	    *stroke_ctm_inverse,
+			    double		     stroke_tolerance,
+			    cairo_antialias_t	     stroke_antialias)
+{
+    cairo_status_t status;
+
+    if (surface->backend->fill_stroke) {
+	cairo_pattern_union_t dev_stroke_source;
+	cairo_pattern_union_t dev_fill_source;
+	cairo_matrix_t dev_ctm = *stroke_ctm;
+	cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
+
+	status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base);
+	if (status)
+	    return status;
+
+	status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base);
+	if (status) {
+	    _cairo_pattern_fini (&dev_stroke_source.base);
+	    return status;
+	}
+
+	status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base,
+						fill_rule, fill_tolerance, fill_antialias,
+						path, stroke_op, &dev_stroke_source.base, stroke_style,
+						&dev_ctm, &dev_ctm_inverse, stroke_tolerance,
+						stroke_antialias);
+
+	_cairo_pattern_fini (&dev_stroke_source.base);
+	_cairo_pattern_fini (&dev_fill_source.base);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
+
+    status = _cairo_surface_fill (surface, fill_op, fill_source, path,
+				  fill_rule, fill_tolerance, fill_antialias);
+    if (status)
+	return status;
+
+    status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path,
+				    stroke_style, stroke_ctm, stroke_ctm_inverse,
+				    stroke_tolerance, stroke_antialias);
+
+    return status;
+}
+
+cairo_status_t
 _cairo_surface_stroke (cairo_surface_t		*surface,
 		       cairo_operator_t		 op,
 		       cairo_pattern_t		*source,
 		       cairo_path_fixed_t	*path,
 		       cairo_stroke_style_t	*stroke_style,
 		       cairo_matrix_t		*ctm,
 		       cairo_matrix_t		*ctm_inverse,
 		       double			 tolerance,
@@ -1518,51 +1585,74 @@ cairo_status_t
     return  _cairo_surface_fallback_composite_trapezoids (op, pattern, dst,
 							  antialias,
 							  src_x, src_y,
 							  dst_x, dst_y,
 							  width, height,
 							  traps, num_traps);
 }
 
+/**
+ * cairo_surface_copy_page:
+ * @suface: a #cairo_surface_t
+ *
+ * Emits the current page for backends that support multiple pages,
+ * but doesn't clear it, so that the contents of the current page will
+ * be retained for the next page.  Use cairo_surface_show_page() if you
+ * want to get an empty page after the emission.
+ *
+ * Since: 1.6
+ */
 cairo_status_t
-_cairo_surface_copy_page (cairo_surface_t *surface)
+cairo_surface_copy_page (cairo_surface_t *surface)
 {
     assert (! surface->is_snapshot);
 
     if (surface->status)
 	return surface->status;
 
     if (surface->finished)
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
     /* It's fine if some backends don't implement copy_page */
     if (surface->backend->copy_page == NULL)
 	return CAIRO_STATUS_SUCCESS;
 
     return surface->backend->copy_page (surface);
 }
+slim_hidden_def (cairo_surface_copy_page);
+
+/**
+ * cairo_surface_show_page:
+ * @surface: a #cairo_Surface_t
+ *
+ * Emits and clears the current page for backends that support multiple
+ * pages.  Use cairo_surface_copy_page() if you don't want to clear the page.
+ *
+ * Since: 1.6
+ **/
 
 cairo_status_t
-_cairo_surface_show_page (cairo_surface_t *surface)
+cairo_surface_show_page (cairo_surface_t *surface)
 {
     assert (! surface->is_snapshot);
 
     if (surface->status)
 	return surface->status;
 
     if (surface->finished)
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
     /* It's fine if some backends don't implement show_page */
     if (surface->backend->show_page == NULL)
 	return CAIRO_STATUS_SUCCESS;
 
     return surface->backend->show_page (surface);
 }
+slim_hidden_def (cairo_surface_show_page);
 
 /**
  * _cairo_surface_get_current_clip_serial:
  * @surface: the #cairo_surface_t to return the serial number for
  *
  * Returns the serial number associated with the current
  * clip in the surface.  All gstate functions must
  * verify that the correct clip is set in the surface before
@@ -1830,16 +1920,24 @@ cairo_status_t
 	return surface->status;
 
     if (surface->finished)
 	return CAIRO_STATUS_SURFACE_FINISHED;
 
     return surface->backend->get_extents (surface, rectangle);
 }
 
+/* Note: the backends may modify the contents of the glyph array as long as
+ * they do not return CAIRO_STATUS_UNSUPPORTED. This makes it possible to
+ * avoid copying the array again and again, and edit it in-place.
+ * Backends are in fact free to use the array as a generic buffer as they
+ * see fit.
+ * See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and
+ * 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale.
+ */
 cairo_status_t
 _cairo_surface_show_glyphs (cairo_surface_t	*surface,
 			    cairo_operator_t	 op,
 			    cairo_pattern_t	*source,
 			    cairo_glyph_t	*glyphs,
 			    int			 num_glyphs,
 			    cairo_scaled_font_t	*scaled_font)
 {
@@ -2188,10 +2286,29 @@ static cairo_status_t
 	assert (status == CAIRO_STATUS_SUCCESS);
 
 	_cairo_pattern_transform (pattern_out, &device_to_surface);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+/**
+ * _cairo_surface_set_resolution
+ * @surface: the surface
+ * @x_res: x resolution, in dpi
+ * @y_res: y resolution, in dpi
+ *
+ * Set the actual surface resolution of @surface to the given x and y DPI.
+ * Mainly used for correctly computing the scale factor when fallback
+ * rendering needs to take place in the paginated surface.
+ */
+void
+_cairo_surface_set_resolution (cairo_surface_t *surface,
+			       double x_res,
+			       double y_res)
+{
+    surface->x_resolution = x_res;
+    surface->y_resolution = y_res;
+}
+
 /*  LocalWords:  rasterized
  */
--- a/gfx/cairo/cairo/src/cairo-svg-surface.c
+++ b/gfx/cairo/cairo/src/cairo-svg-surface.c
@@ -1,9 +1,9 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* vim: set sw=4 sts=4: -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Red Hat, Inc
  * Copyright © 2005-2006 Emmanuel Pacaud <emmanuel.pacaud@free.fr>
  * Copyright © 2006 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
@@ -446,26 +446,25 @@ static cairo_int_status_t
     _cairo_svg_surface_store_page (surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_svg_surface_emit_transform (cairo_output_stream_t *output,
 		char const *attribute_str,
-		char const *trailer,
 		cairo_matrix_t *matrix)
 {
-    _cairo_output_stream_printf (output,
-				 "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"%s",
-				 attribute_str,
-				 matrix->xx, matrix->yx,
-				 matrix->xy, matrix->yy,
-				 matrix->x0, matrix->y0,
-				 trailer);
+    if (!_cairo_matrix_is_identity (matrix))
+	_cairo_output_stream_printf (output,
+				     "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"",
+				     attribute_str,
+				     matrix->xx, matrix->yx,
+				     matrix->xy, matrix->yy,
+				     matrix->x0, matrix->y0);
 }
 
 typedef struct
 {
     cairo_output_stream_t *output;
     cairo_matrix_t *ctm_inverse;
 } svg_path_info_t;
 
@@ -611,17 +610,18 @@ static cairo_int_status_t
     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);
     }
 
     _cairo_output_stream_printf (document->xml_node_glyphs, "<g");
-    _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
+    _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", &image->base.device_transform_inverse);
+    _cairo_output_stream_printf (document->xml_node_glyphs, ">/n");
 
     for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
 	for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
 	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
 	    for (bit = 7; bit >= 0 && x < image->width; bit--, x++) {
 		if (output_byte & (1 << bit)) {
 		    _cairo_output_stream_printf (document->xml_node_glyphs,
 						 "<rect x=\"%d\" y=\"%d\" width=\"1\" height=\"1\"/>\n",
@@ -912,25 +912,26 @@ static cairo_status_t
 
     if (pattern_id != invalid_pattern_id) {
 	_cairo_output_stream_printf (output,
 				     "<pattern id=\"pattern%d\" "
 				     "patternUnits=\"userSpaceOnUse\" "
 				     "width=\"%d\" height=\"%d\"",
 				     pattern_id,
 				     extents.width, extents.height);
-	_cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
+	_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
+	_cairo_output_stream_printf (output, ">\n");
     }
 
     _cairo_output_stream_printf (output,
 				 "  <image width=\"%d\" height=\"%d\"",
 				 extents.width, extents.height);
 
     if (pattern_id == invalid_pattern_id)
-	_cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
+	_cairo_svg_surface_emit_transform (output, " transform", &p2u);
 
     if (extra_attributes)
 	_cairo_output_stream_printf (output, " %s", extra_attributes);
 
     _cairo_output_stream_printf (output, " xlink:href=\"");
 
     status = _cairo_surface_base64_encode (surface, output);
 
@@ -985,17 +986,17 @@ static cairo_status_t
 					   document->owner->y_fallback_resolution);
 
     status = _cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
     if (status) {
 	cairo_surface_destroy (&meta->base);
 	return status;
     }
 
-    status = _cairo_surface_show_page (paginated_surface);
+    status = cairo_surface_show_page (paginated_surface);
     if (status) {
 	cairo_surface_destroy (&meta->base);
 	return status;
     }
 
     new_snapshot.meta = meta;
     new_snapshot.id = svg_surface->id;
     status = _cairo_array_append (&document->meta_snapshots, &new_snapshot);
@@ -1087,25 +1088,26 @@ static cairo_status_t
     if (pattern_id != invalid_pattern_id) {
 	_cairo_output_stream_printf (output,
 				     "<pattern id=\"pattern%d\" "
 				     "patternUnits=\"userSpaceOnUse\" "
 				     "width=\"%d\" height=\"%d\"",
 				     pattern_id,
 				     meta_surface->width_pixels,
 				     meta_surface->height_pixels);
-	_cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
+	_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
+	_cairo_output_stream_printf (output, ">\n");
     }
 
     _cairo_output_stream_printf (output,
 				 "<use xlink:href=\"#surface%d\"",
 				 id);
 
     if (pattern_id == invalid_pattern_id)
-	_cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
+	_cairo_svg_surface_emit_transform (output, " transform", &p2u);
 
     if (extra_attributes)
 	_cairo_output_stream_printf (output, " %s", extra_attributes);
 
     _cairo_output_stream_printf (output, "/>\n");
 
     if (pattern_id != invalid_pattern_id)
 	_cairo_output_stream_printf (output, "</pattern>\n");
@@ -1394,17 +1396,18 @@ static cairo_status_t
     _cairo_output_stream_printf (document->xml_node_defs,
 				 "<linearGradient id=\"linear%d\" "
 				 "gradientUnits=\"userSpaceOnUse\" "
 				 "x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" ",
 				 document->linear_pattern_id,
 				 x0, y0, x1, y1);
 
     _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
-    _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+    _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+    _cairo_output_stream_printf (document->xml_node_defs, ">\n");
 
     _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
 
     _cairo_output_stream_printf (document->xml_node_defs,
 				 "</linearGradient>\n");
 
     _cairo_output_stream_printf (style,
 				 "%s: url(#linear%d);",
@@ -1464,18 +1467,18 @@ static cairo_status_t
 	_cairo_output_stream_printf (document->xml_node_defs,
 				     "<radialGradient id=\"radial%d\" "
 				     "gradientUnits=\"userSpaceOnUse\" "
 				     "cx=\"%f\" cy=\"%f\" "
 				     "fx=\"%f\" fy=\"%f\" r=\"%f\" ",
 				     document->radial_pattern_id,
 				     x1, y1,
 				     x1, y1, r1);
-
-	_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+	_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+	_cairo_output_stream_printf (document->xml_node_defs, ">\n");
 
 	if (extend == CAIRO_EXTEND_NONE ||
 	    pattern->base.n_stops < 1)
 	    _cairo_output_stream_printf (document->xml_node_defs,
 					 "<stop offset=\"0\" style=\""
 					 "stop-color: rgb(0%%,0%%,0%%); "
 					 "stop-opacity: 0;\"/>\n");
 	else {
@@ -1549,17 +1552,18 @@ static cairo_status_t
 				     document->radial_pattern_id,
 				     x1, y1,
 				     fx, fy, r1);
 
 	if (emulate_reflect)
 	    _cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" ");
 	else
 	    _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base);
-	_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+	_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+	_cairo_output_stream_printf (document->xml_node_defs, ">\n");
 
 	/* To support cairo's EXTEND_NONE, (for which SVG has no similar
 	 * notion), we add transparent color stops on either end of the
 	 * user-provided stops. */
 	if (extend == CAIRO_EXTEND_NONE) {
 	    _cairo_output_stream_printf (document->xml_node_defs,
 					 "<stop offset=\"0\" style=\""
 					 "stop-color: rgb(0%%,0%%,0%%); "
@@ -1608,16 +1612,134 @@ static cairo_status_t
 	return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
 
     case CAIRO_PATTERN_TYPE_RADIAL:
 	return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
     }
     return CAIRO_STATUS_SUCCESS;
 }
 
+static void
+_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
+				    cairo_svg_surface_t *surface,
+				    cairo_operator_t op,
+				    cairo_pattern_t *source,
+				    cairo_fill_rule_t fill_rule)
+{
+    _cairo_output_stream_printf (output,
+				 "fill-rule: %s; ",
+				 fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
+				 "evenodd" : "nonzero");
+    _cairo_svg_surface_emit_operator (output, surface, op);
+    _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
+}
+
+static void
+_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
+				      cairo_svg_surface_t   *surface,
+				      cairo_operator_t	     op,
+				      cairo_pattern_t	    *source,
+				      cairo_stroke_style_t  *stroke_style)
+{
+    const char *line_cap, *line_join;
+    unsigned int i;
+
+    switch (stroke_style->line_cap) {
+	case CAIRO_LINE_CAP_BUTT:
+	    line_cap = "butt";
+	    break;
+	case CAIRO_LINE_CAP_ROUND:
+	    line_cap = "round";
+	    break;
+	case CAIRO_LINE_CAP_SQUARE:
+	    line_cap = "square";
+	    break;
+	default:
+	    ASSERT_NOT_REACHED;
+    }
+
+    switch (stroke_style->line_join) {
+	case CAIRO_LINE_JOIN_MITER:
+	    line_join = "miter";
+	    break;
+	case CAIRO_LINE_JOIN_ROUND:
+	    line_join = "round";
+	    break;
+	case CAIRO_LINE_JOIN_BEVEL:
+	    line_join = "bevel";
+	    break;
+	default:
+	    ASSERT_NOT_REACHED;
+    }
+
+    _cairo_output_stream_printf (output,
+				 "stroke-width: %f; "
+				 "stroke-linecap: %s; "
+				 "stroke-linejoin: %s; ",
+				 stroke_style->line_width,
+				 line_cap,
+				 line_join);
+
+     _cairo_svg_surface_emit_pattern (surface, source, output, TRUE);
+     _cairo_svg_surface_emit_operator (output, surface, op);
+
+    if (stroke_style->num_dashes > 0) {
+	_cairo_output_stream_printf (output, "stroke-dasharray: ");
+	for (i = 0; i < stroke_style->num_dashes; i++) {
+	    _cairo_output_stream_printf (output, "%f",
+					 stroke_style->dash[i]);
+	    if (i + 1 < stroke_style->num_dashes)
+		_cairo_output_stream_printf (output, ",");
+	    else
+		_cairo_output_stream_printf (output, "; ");
+	}
+	if (stroke_style->dash_offset != 0.0) {
+	    _cairo_output_stream_printf (output,
+					 "stroke-dashoffset: %f; ",
+					 stroke_style->dash_offset);
+	}
+    }
+
+    _cairo_output_stream_printf (output,
+				 "stroke-miterlimit: %f; ",
+				 stroke_style->miter_limit);
+}
+
+static cairo_int_status_t
+_cairo_svg_surface_fill_stroke (void			*abstract_surface,
+				cairo_operator_t	 fill_op,
+				cairo_pattern_t		*fill_source,
+				cairo_fill_rule_t	 fill_rule,
+				double			 fill_tolerance,
+				cairo_antialias_t	 fill_antialias,
+				cairo_path_fixed_t	*path,
+				cairo_operator_t	 stroke_op,
+				cairo_pattern_t		*stroke_source,
+				cairo_stroke_style_t	*stroke_style,
+				cairo_matrix_t		*stroke_ctm,
+				cairo_matrix_t		*stroke_ctm_inverse,
+				double			 stroke_tolerance,
+				cairo_antialias_t	 stroke_antialias)
+{
+    cairo_svg_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+
+    _cairo_output_stream_printf (surface->xml_node, "<path style=\"");
+    _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, fill_source, fill_rule);
+    _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, stroke_source, stroke_style);
+    _cairo_output_stream_printf (surface->xml_node, "\" ");
+
+    status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
+
+    _cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm);
+    _cairo_output_stream_printf (surface->xml_node, "/>\n");
+
+    return status;
+}
+
 static cairo_int_status_t
 _cairo_svg_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)
@@ -1625,23 +1747,18 @@ static cairo_int_status_t
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_svg_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_svg_surface_operation_supported (surface, op, source));
 
-    _cairo_output_stream_printf (surface->xml_node,
- 				 "<path style=\"stroke: none; "
- 				 "fill-rule: %s; ",
- 				 fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
- 				 "evenodd" : "nonzero");
-    _cairo_svg_surface_emit_operator (surface->xml_node, surface, op);
-    _cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, FALSE);
+    _cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;");
+    _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule);
     _cairo_output_stream_printf (surface->xml_node, "\" ");
 
     status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
 
     _cairo_output_stream_printf (surface->xml_node, "/>\n");
 
     return status;
 }
@@ -1810,88 +1927,30 @@ static cairo_int_status_t
 			   cairo_stroke_style_t *stroke_style,
 			   cairo_matrix_t	*ctm,
 			   cairo_matrix_t	*ctm_inverse,
 			   double		 tolerance,
 			   cairo_antialias_t	 antialias)
 {
     cairo_svg_surface_t *surface = abstract_dst;
     cairo_status_t status;
-    const char *line_cap, *line_join;
-    unsigned int i;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_svg_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_svg_surface_operation_supported (surface, op, source));
 
-    switch (stroke_style->line_cap) {
-    case CAIRO_LINE_CAP_BUTT:
- 	line_cap = "butt";
- 	break;
-    case CAIRO_LINE_CAP_ROUND:
- 	line_cap = "round";
- 	break;
-    case CAIRO_LINE_CAP_SQUARE:
- 	line_cap = "square";
- 	break;
-    default:
- 	ASSERT_NOT_REACHED;
-    }
-
-    switch (stroke_style->line_join) {
-    case CAIRO_LINE_JOIN_MITER:
- 	line_join = "miter";
- 	break;
-    case CAIRO_LINE_JOIN_ROUND:
- 	line_join = "round";
- 	break;
-    case CAIRO_LINE_JOIN_BEVEL:
- 	line_join = "bevel";
- 	break;
-    default:
- 	ASSERT_NOT_REACHED;
-    }
-
-    _cairo_output_stream_printf (surface->xml_node,
- 				 "<path style=\"fill: none; "
- 				 "stroke-width: %f; "
- 				 "stroke-linecap: %s; "
- 				 "stroke-linejoin: %s; ",
-				 stroke_style->line_width,
- 				 line_cap,
- 				 line_join);
-
-     _cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, TRUE);
-     _cairo_svg_surface_emit_operator (surface->xml_node, surface, op);
-
-    if (stroke_style->num_dashes > 0) {
- 	_cairo_output_stream_printf (surface->xml_node, "stroke-dasharray: ");
-	for (i = 0; i < stroke_style->num_dashes; i++) {
- 	    _cairo_output_stream_printf (surface->xml_node, "%f",
- 					 stroke_style->dash[i]);
- 	    if (i + 1 < stroke_style->num_dashes)
- 		_cairo_output_stream_printf (surface->xml_node, ",");
- 	    else
- 		_cairo_output_stream_printf (surface->xml_node, "; ");
-	}
-	if (stroke_style->dash_offset != 0.0) {
- 	    _cairo_output_stream_printf (surface->xml_node,
- 					 "stroke-dashoffset: %f; ",
- 					 stroke_style->dash_offset);
-	}
-    }
-
-    _cairo_output_stream_printf (surface->xml_node,
- 				 "stroke-miterlimit: %f;\" ",
- 				 stroke_style->miter_limit);
+    _cairo_output_stream_printf (surface->xml_node, "<path style=\"fill: none; ");
+    _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op, source, stroke_style);
+    _cairo_output_stream_printf (surface->xml_node, "\" ");
 
     status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
 
-    _cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", ctm);
+    _cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm);
+    _cairo_output_stream_printf (surface->xml_node, "/>\n");
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_svg_surface_show_glyphs (void			*abstract_surface,
 				cairo_operator_t	 op,
 				cairo_pattern_t		*pattern,
@@ -2038,17 +2097,21 @@ static const cairo_surface_backend_t cai
 	NULL, /* flush */
 	NULL, /* mark dirty rectangle */
 	NULL, /* scaled font fini */
 	NULL, /* scaled glyph fini */
 	_cairo_svg_surface_paint,
 	_cairo_svg_surface_mask,
 	_cairo_svg_surface_stroke,
 	_cairo_svg_surface_fill,
-	_cairo_svg_surface_show_glyphs
+	_cairo_svg_surface_show_glyphs,
+	NULL, /* snapshot */
+	NULL, /* is_similar */
+	NULL, /* reset */
+	_cairo_svg_surface_fill_stroke
 };
 
 static cairo_svg_document_t *
 _cairo_svg_document_create (cairo_output_stream_t	*output_stream,
 			    double			 width,
 			    double			 height,
 			    cairo_svg_version_t		 version)
 {
--- a/gfx/cairo/cairo/src/cairo-truetype-subset.c
+++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c
@@ -926,23 +926,26 @@ cairo_status_t
 
     truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
     truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
     truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em;
     truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em;
     truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em;
     truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
 
-    truetype_subset->data = malloc (length);
-    if (truetype_subset->data == NULL) {
-	status = CAIRO_STATUS_NO_MEMORY;
-	goto fail3;
-    }
+    if (length) {
+	truetype_subset->data = malloc (length);
+	if (truetype_subset->data == NULL) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto fail3;
+	}
 
-    memcpy (truetype_subset->data, data, length);
+	memcpy (truetype_subset->data, data, length);
+    } else
+	truetype_subset->data = NULL;
     truetype_subset->data_length = length;
 
     if (num_strings) {
 	offsets_length = num_strings * sizeof (unsigned long);
 	truetype_subset->string_offsets = malloc (offsets_length);
 	if (truetype_subset->string_offsets == NULL) {
 	    status = CAIRO_STATUS_NO_MEMORY;
 	    goto fail4;
--- a/gfx/cairo/cairo/src/cairo-types-private.h
+++ b/gfx/cairo/cairo/src/cairo-types-private.h
@@ -33,47 +33,34 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_TYPES_PRIVATE_H
 #define CAIRO_TYPES_PRIVATE_H
 
-typedef struct _cairo_array cairo_array_t;
-struct _cairo_array {
-    unsigned int size;
-    unsigned int num_elements;
-    unsigned int element_size;
-    char **elements;
-
-    cairo_bool_t is_snapshot;
-};
-
-typedef cairo_array_t cairo_user_data_array_t;
+/* This is the only header file not including cairoint.h.  It only contains
+ * typedefs.*/
+#include "cairo.h"
 
-struct _cairo_font_options {
-    cairo_antialias_t antialias;
-    cairo_subpixel_order_t subpixel_order;
-    cairo_hint_style_t hint_style;
-    cairo_hint_metrics_t hint_metrics;
-};
-
+typedef struct _cairo_array cairo_array_t;
 typedef struct _cairo_hash_table cairo_hash_table_t;
-
-typedef struct _cairo_cache {
-    cairo_hash_table_t *hash_table;
-
-    cairo_destroy_func_t entry_destroy;
-
-    unsigned long max_size;
-    unsigned long size;
-
-    int freeze_count;
-} cairo_cache_t;
+typedef struct _cairo_cache cairo_cache_t;
+typedef struct _cairo_hash_entry cairo_hash_entry_t;
+typedef struct _cairo_surface_backend cairo_surface_backend_t;
+typedef struct _cairo_clip cairo_clip_t;
+typedef struct _cairo_output_stream cairo_output_stream_t;
+typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
+typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
+typedef struct _cairo_scaled_font_backend   cairo_scaled_font_backend_t;
+typedef struct _cairo_font_face_backend     cairo_font_face_backend_t;
+typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
+typedef enum _cairo_paginated_mode cairo_paginated_mode_t;
+typedef cairo_array_t cairo_user_data_array_t;
 
 /**
  * cairo_hash_entry_t:
  *
  * A #cairo_hash_entry_t contains both a key and a value for
  * cairo_hash_table_t. User-derived types for cairo_hash_entry_t must
  * be type-compatible with this structure (eg. they must have an
  * unsigned long as the first parameter. The easiest way to get this
@@ -99,30 +86,67 @@ typedef struct _cairo_cache {
  * Which parts of the entry make up the "key" and which part make up
  * the value are entirely up to the caller, (as determined by the
  * computation going into base.hash as well as the keys_equal
  * function). A few of the cairo_hash_table functions accept an entry
  * which will be used exclusively as a "key", (indicated by a
  * parameter name of key). In these cases, the value-related fields of
  * the entry need not be initialized if so desired.
  **/
-typedef struct _cairo_hash_entry {
+struct _cairo_hash_entry {
     unsigned long hash;
-} cairo_hash_entry_t;
+};
 
+struct _cairo_array {
+    unsigned int size;
+    unsigned int num_elements;
+    unsigned int element_size;
+    char **elements;
+
+    cairo_bool_t is_snapshot;
+};
 
-typedef struct _cairo_surface_backend cairo_surface_backend_t;
-typedef struct _cairo_clip cairo_clip_t;
-typedef struct _cairo_output_stream cairo_output_stream_t;
-typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
-typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
-typedef struct _cairo_scaled_font_backend   cairo_scaled_font_backend_t;
-typedef struct _cairo_font_face_backend     cairo_font_face_backend_t;
+struct _cairo_font_options {
+    cairo_antialias_t antialias;
+    cairo_subpixel_order_t subpixel_order;
+    cairo_hint_style_t hint_style;
+    cairo_hint_metrics_t hint_metrics;
+};
+
+struct _cairo_cache {
+    cairo_hash_table_t *hash_table;
 
+    cairo_destroy_func_t entry_destroy;
 
-typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
+    unsigned long max_size;
+    unsigned long size;
 
-typedef enum {
+    int freeze_count;
+};
+
+enum _cairo_paginated_mode {
     CAIRO_PAGINATED_MODE_ANALYZE,	/* analyze page regions */
     CAIRO_PAGINATED_MODE_RENDER		/* render page contents */
-} cairo_paginated_mode_t;
+};
+
+/* Sure wish C had a real enum type so that this would be distinct
+   from cairo_status_t. Oh well, without that, I'll use this bogus 1000
+   offset */
+typedef enum _cairo_int_status {
+    CAIRO_INT_STATUS_DEGENERATE = 1000,
+    CAIRO_INT_STATUS_UNSUPPORTED,
+    CAIRO_INT_STATUS_NOTHING_TO_DO,
+    CAIRO_INT_STATUS_CACHE_EMPTY,
+    CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
+    CAIRO_INT_STATUS_IMAGE_FALLBACK,
+    CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN,
+} cairo_int_status_t;
+
+typedef enum _cairo_internal_surface_type {
+    CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+    CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+} cairo_internal_surface_type_t;
 
 #endif /* CAIRO_TYPES_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-win32-font.c
+++ b/gfx/cairo/cairo/src/cairo-win32-font.c
@@ -298,43 +298,40 @@ static cairo_scaled_font_t *
     f->delete_scaled_hfont = !f->scaled_hfont;
 
     cairo_matrix_multiply (&scale, font_matrix, ctm);
     _compute_transform (f, &scale);
 
     status = _cairo_scaled_font_init (&f->base, font_face,
 				      font_matrix, ctm, options,
 				      &cairo_win32_scaled_font_backend);
-    if (status) {
-	free (f);
-	return NULL;
-    }
+    if (status)
+	goto FAIL;
 
     status = _cairo_win32_scaled_font_set_metrics (f);
+
     if (status) {
-	_cairo_scaled_font_fini (f);
-	free (f);
-	return NULL;
+	_cairo_scaled_font_fini (&f->base);
+	goto FAIL;
     }
 
     return &f->base;
+
+ FAIL:
+    free (f);
+    return NULL;
 }
 
 static cairo_status_t
 _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
 					HDC                        hdc)
 {
     XFORM xform;
 
-    xform.eM11 = scaled_font->logical_to_device.xx;
-    xform.eM21 = scaled_font->logical_to_device.xy;
-    xform.eM12 = scaled_font->logical_to_device.yx;
-    xform.eM22 = scaled_font->logical_to_device.yy;
-    xform.eDx = scaled_font->logical_to_device.x0;
-    xform.eDy = scaled_font->logical_to_device.y0;
+    _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
 
     if (!SetWorldTransform (hdc, &xform))
 	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
@@ -0,0 +1,1220 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * 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
+ * (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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ *      Adrian Johnson <ajohnson@redneon.com>
+ *      Vladimir Vukicevic <vladimir@pobox.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-paginated-private.h"
+
+#include "cairo-clip-private.h"
+#include "cairo-win32-private.h"
+
+#include <windows.h>
+
+#if !defined(POSTSCRIPT_IDENTIFY)
+# define POSTSCRIPT_IDENTIFY 0x1015
+#endif
+
+#if !defined(PSIDENT_GDICENTRIC)
+# define PSIDENT_GDICENTRIC 0x0000
+#endif
+
+#if !defined(GET_PS_FEATURESETTING)
+# define GET_PS_FEATURESETTING 0x1019
+#endif
+
+#if !defined(FEATURESETTING_PSLEVEL)
+# define FEATURESETTING_PSLEVEL 0x0002
+#endif
+
+#define PELS_72DPI  ((LONG)(72. / 0.0254))
+#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil)
+
+static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
+static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend;
+
+static void
+_cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface)
+{
+    DWORD word;
+    INT ps_feature, ps_level;
+
+    word = PSIDENT_GDICENTRIC;
+    if (ExtEscape (surface->dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0)
+	return;
+
+    ps_feature = FEATURESETTING_PSLEVEL;
+    if (ExtEscape (surface->dc, GET_PS_FEATURESETTING, sizeof(INT),
+		   (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0)
+	return;
+
+    if (ps_level >= 3)
+	surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+}
+
+static cairo_bool_t
+surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+{
+    cairo_extend_t extend;
+
+    if (cairo_surface_get_type (pattern->surface) != CAIRO_SURFACE_TYPE_WIN32 &&
+	pattern->surface->backend->acquire_source_image == NULL)
+    {
+	return FALSE;
+    }
+
+    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 (cairo_win32_surface_t *surface, const cairo_pattern_t *pattern)
+{
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
+	return TRUE;
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+	return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
+	return surface->flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
+
+    return FALSE;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface,
+                                                 cairo_operator_t       op,
+                                                 const cairo_pattern_t *pattern)
+{
+    if (! pattern_supported (surface, pattern))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (op == CAIRO_OPERATOR_SOURCE ||
+	op == CAIRO_OPERATOR_CLEAR)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* If IGNORE_OPERATORS was set, then we pretend everything is
+     * OVER/SOURCE.  Otherwise, we go to fallback.
+     */
+    if (!(surface->flags & CAIRO_WIN32_SURFACE_IGNORE_OPERATORS) &&
+	op != CAIRO_OPERATOR_OVER)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
+     * the pattern contains transparency, we return
+     * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
+     * surface. If the analysis surface determines that there is
+     * anything drawn under this operation, a fallback image will be
+     * used. Otherwise the operation will be replayed during the
+     * render stage and we blend the transarency into the white
+     * background to convert the pattern to opaque.
+     */
+
+    if (_cairo_operator_always_opaque (op))
+	return CAIRO_STATUS_SUCCESS;
+
+    if (_cairo_operator_always_translucent (op))
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+
+    if (_cairo_pattern_is_opaque (pattern))
+	return CAIRO_STATUS_SUCCESS;
+    else
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+}
+
+static cairo_bool_t
+_cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surface,
+                                                   cairo_operator_t       op,
+                                                   const cairo_pattern_t *pattern)
+{
+    if (_cairo_win32_printing_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
+	return TRUE;
+    else
+	return FALSE;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface,
+                                                  cairo_pattern_t       *source)
+{
+    cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source;
+    cairo_color_t c = pattern->color;
+    COLORREF color;
+    BYTE red, green, blue;
+
+    red   = c.red_short   >> 8;
+    green = c.green_short >> 8;
+    blue  = c.blue_short  >> 8;
+
+    if (!CAIRO_COLOR_IS_OPAQUE(&c)) {
+	/* Blend into white */
+	uint8_t one_minus_alpha = 255 - (c.alpha_short >> 8);
+
+	red   = (c.red_short   >> 8) + one_minus_alpha;
+	green = (c.green_short >> 8) + one_minus_alpha;
+	blue  = (c.blue_short  >> 8) + one_minus_alpha;
+    }
+
+    color = RGB (red, green, blue);
+
+    surface->brush = CreateSolidBrush (color);
+    if (!surface->brush)
+	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)");
+    surface->old_brush = SelectObject (surface->dc, surface->brush);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_printing_surface_done_solid_brush (cairo_win32_surface_t *surface)
+{
+    if (surface->old_brush) {
+	SelectObject (surface->dc, surface->old_brush);
+	DeleteObject (surface->brush);
+	surface->old_brush = NULL;
+    }
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface,
+                                                   cairo_pattern_t       *pattern)
+{
+    RECT clip;
+    cairo_status_t status;
+
+    GetClipBox (surface->dc, &clip);
+    status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern);
+    if (status)
+	return status;
+
+    FillRect (surface->dc, &clip, surface->brush);
+    _cairo_win32_printing_surface_done_solid_brush (surface);
+
+    return 0;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t   *surface,
+                                                     cairo_surface_pattern_t *pattern)
+{
+    cairo_status_t status;
+    cairo_extend_t extend;
+    cairo_surface_t *pat_surface;
+    cairo_surface_attributes_t pat_attr;
+    cairo_image_surface_t *image;
+    void *image_extra;
+    cairo_surface_t *opaque_surface;
+    cairo_pattern_union_t opaque_pattern;
+    cairo_image_surface_t *opaque_image = NULL;
+    BITMAPINFO bi;
+    cairo_matrix_t m;
+    int oldmode;
+    XFORM xform;
+    int x_tile, y_tile, left, right, top, bottom;
+    RECT clip;
+
+    extend = cairo_pattern_get_extend (&pattern->base);
+    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 = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
+    if (status)
+	goto FINISH;
+
+    if (image->base.status) {
+	status = image->base.status;
+	goto FINISH2;
+    }
+
+    if (image->format != CAIRO_FORMAT_RGB24) {
+	opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+						     image->width,
+						     image->height);
+	if (opaque_surface->status) {
+	    status = opaque_surface->status;
+	    goto FINISH3;
+	}
+
+	_cairo_pattern_init_for_surface (&opaque_pattern.surface, &image->base);
+
+	status = _cairo_surface_fill_rectangle (opaque_surface,
+				                CAIRO_OPERATOR_SOURCE,
+						CAIRO_COLOR_WHITE,
+						0, 0,
+						image->width, image->height);
+	if (status) {
+	    _cairo_pattern_fini (&opaque_pattern.base);
+	    goto FINISH3;
+	}
+
+	status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
+				           &opaque_pattern.base,
+					   NULL,
+					   opaque_surface,
+					   0, 0,
+					   0, 0,
+					   0, 0,
+					   image->width,
+					   image->height);
+	if (status) {
+	    _cairo_pattern_fini (&opaque_pattern.base);
+	    goto FINISH3;
+	}
+
+	_cairo_pattern_fini (&opaque_pattern.base);
+	opaque_image = (cairo_image_surface_t *) opaque_surface;
+    } else {
+	opaque_surface = &image->base;
+	opaque_image = image;
+    }
+
+    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bi.bmiHeader.biWidth = opaque_image->width;
+    bi.bmiHeader.biHeight = -opaque_image->height;
+    bi.bmiHeader.biSizeImage = 0;
+    bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+    bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+    bi.bmiHeader.biPlanes = 1;
+    bi.bmiHeader.biBitCount = 32;
+    bi.bmiHeader.biCompression = BI_RGB;
+    bi.bmiHeader.biClrUsed = 0;
+    bi.bmiHeader.biClrImportant = 0;
+
+    m = pattern->base.matrix;
+    cairo_matrix_invert (&m);
+
+    SaveDC (surface->dc);
+    SetGraphicsMode (surface->dc, GM_ADVANCED);
+    _cairo_matrix_to_win32_xform (&m, &xform);
+
+    if (!SetWorldTransform (surface->dc, &xform))
+	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
+
+    oldmode = SetStretchBltMode(surface->dc, HALFTONE);
+
+    GetClipBox (surface->dc, &clip);
+    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
+	left = (int) floor((double)clip.left/opaque_image->width);
+	right = (int) ceil((double)clip.right/opaque_image->width);
+	top = (int) floor((double)clip.top/opaque_image->height);
+	bottom = (int) ceil((double)clip.bottom/opaque_image->height);
+    } else {
+	left = 0;
+	right = 1;
+	top = 0;
+	bottom = 1;
+    }
+
+    for (y_tile = top; y_tile < bottom; y_tile++) {
+	for (x_tile = left; x_tile < right; x_tile++) {
+	    if (!StretchDIBits (surface->dc,
+				x_tile*opaque_image->width,
+				y_tile*opaque_image->height,
+				opaque_image->width,
+				opaque_image->height,
+				0,
+				0,
+				opaque_image->width,
+				opaque_image->height,
+				opaque_image->data,
+				&bi,
+				DIB_RGB_COLORS,
+				SRCCOPY))
+		return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
+	}
+    }
+    SetStretchBltMode(surface->dc, oldmode);
+    RestoreDC (surface->dc, -1);
+
+FINISH3:
+    if (opaque_image != image)
+	cairo_surface_destroy (opaque_surface);
+FINISH2:
+    _cairo_surface_release_source_image (pat_surface, image, image_extra);
+FINISH:
+    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
+
+    return status;
+}
+
+static void
+vertex_set_color (TRIVERTEX *vert, cairo_color_t *color)
+{
+    vert->Alpha = 0xffff;
+    vert->Red   = color->red_short;
+    vert->Green = color->green_short;
+    vert->Blue  = color->blue_short;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surface,
+                                                    cairo_linear_pattern_t *pattern)
+{
+    TRIVERTEX *vert;
+    GRADIENT_RECT *rect;
+    RECT clip;
+    XFORM xform;
+    int i, num_stops;
+    cairo_matrix_t mat, rot;
+    double p1x, p1y, p2x, p2y, xd, yd, d, sn, cs;
+    cairo_extend_t extend;
+    int range_start, range_stop, num_ranges, num_rects, stop;
+    int total_verts, total_rects;
+
+    extend = cairo_pattern_get_extend (&pattern->base.base);
+    SaveDC (surface->dc);
+
+    mat = pattern->base.base.matrix;
+    cairo_matrix_invert (&mat);
+
+    p1x = _cairo_fixed_to_double (pattern->p1.x);
+    p1y = _cairo_fixed_to_double (pattern->p1.y);
+    p2x = _cairo_fixed_to_double (pattern->p2.x);
+    p2y = _cairo_fixed_to_double (pattern->p2.y);
+    cairo_matrix_translate (&mat, p1x, p1y);
+
+    xd = p2x - p1x;
+    yd = p2y - p1y;
+    d = sqrt (xd*xd + yd*yd);
+    sn = yd/d;
+    cs = xd/d;
+    cairo_matrix_init (&rot,
+		       cs, sn,
+		       -sn, cs,
+		        0, 0);
+    cairo_matrix_multiply (&mat, &rot, &mat);
+
+    _cairo_matrix_to_win32_xform (&mat, &xform);
+
+    SetGraphicsMode (surface->dc, GM_ADVANCED);
+    if (!SetWorldTransform (surface->dc, &xform))
+	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2");
+    GetWorldTransform(surface->dc, &xform);
+    p1x = 0.0;
+    p1y = 0.0;
+    p2x = d;
+    p2y = 0;
+
+    GetClipBox (surface->dc, &clip);
+    if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
+	range_start = (int) floor(clip.left/d);
+	range_stop = (int) ceil(clip.right/d);
+    } else {
+	range_start = 0;
+	range_stop = 1;
+    }
+    num_ranges = range_stop - range_start;
+    num_stops = pattern->base.n_stops;
+    num_rects = num_stops - 1;
+
+    /* Add an extra four points and two rectangles for EXTEND_PAD */
+    vert = malloc (sizeof (TRIVERTEX) * (num_rects*2*num_ranges + 4));
+    rect = malloc (sizeof (GRADIENT_RECT) * (num_rects*num_ranges + 2));
+
+    for (i = 0; i < num_ranges*num_rects; i++) {
+	vert[i*2].y = (LONG) clip.top;
+	if (i%num_rects == 0) {
+	    stop = 0;
+	    if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
+		stop = num_rects;
+	    vert[i*2].x = (LONG)(d*(range_start + i/num_rects));
+	    vertex_set_color (&vert[i*2], &pattern->base.stops[stop].color);
+	} else {
+	    vert[i*2].x = vert[i*2-1].x;
+	    vert[i*2].Red = vert[i*2-1].Red;
+	    vert[i*2].Green = vert[i*2-1].Green;
+	    vert[i*2].Blue = vert[i*2-1].Blue;
+	    vert[i*2].Alpha = vert[i*2-1].Alpha;
+	}
+
+	stop = i%num_rects + 1;
+	vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + _cairo_fixed_to_double (pattern->base.stops[stop].x)));
+	vert[i*2+1].y = (LONG) clip.bottom;
+	if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
+	    stop = num_rects - stop;
+	vertex_set_color (&vert[i*2+1], &pattern->base.stops[stop].color);
+
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+    }
+    total_verts = 2*num_ranges*num_rects;
+    total_rects = num_ranges*num_rects;
+
+    if (extend == CAIRO_EXTEND_PAD) {
+	vert[i*2].x = vert[i*2-1].x;
+	vert[i*2].y = (LONG) clip.top;
+	vert[i*2].Red = vert[i*2-1].Red;
+	vert[i*2].Green = vert[i*2-1].Green;
+	vert[i*2].Blue = vert[i*2-1].Blue;
+	vert[i*2].Alpha = 0xff00;
+	vert[i*2+1].x = clip.right;
+	vert[i*2+1].y = (LONG) clip.bottom;
+	vert[i*2+1].Red = vert[i*2-1].Red;
+	vert[i*2+1].Green = vert[i*2-1].Green;
+	vert[i*2+1].Blue = vert[i*2-1].Blue;
+	vert[i*2+1].Alpha = 0xff00;
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+
+	i++;
+
+	vert[i*2].x = clip.left;
+	vert[i*2].y = (LONG) clip.top;
+	vert[i*2].Red = vert[0].Red;
+	vert[i*2].Green = vert[0].Green;
+	vert[i*2].Blue = vert[0].Blue;
+	vert[i*2].Alpha = 0xff00;
+	vert[i*2+1].x = vert[0].x;
+	vert[i*2+1].y = (LONG) clip.bottom;
+	vert[i*2+1].Red = vert[0].Red;
+	vert[i*2+1].Green = vert[0].Green;
+	vert[i*2+1].Blue = vert[0].Blue;
+	vert[i*2+1].Alpha = 0xff00;
+	rect[i].UpperLeft = i*2;
+	rect[i].LowerRight = i*2 + 1;
+
+	total_verts += 4;
+	total_rects += 2;
+    }
+
+    if (!GradientFill (surface->dc,
+		       vert, total_verts,
+		       rect, total_rects,
+		       GRADIENT_FILL_RECT_H))
+	return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill");
+
+    free (rect);
+    free (vert);
+    RestoreDC (surface->dc, -1);
+
+    return 0;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface,
+                                             cairo_pattern_t       *pattern)
+{
+    cairo_status_t status;
+
+    switch (pattern->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	status = _cairo_win32_printing_surface_paint_solid_pattern (surface, pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	status = _cairo_win32_printing_surface_paint_surface_pattern (surface,
+                                                                      (cairo_surface_pattern_t *) pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	status = _cairo_win32_printing_surface_paint_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	if (status)
+	    return status;
+	break;
+
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+	break;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+typedef struct _win32_print_path_info {
+    cairo_win32_surface_t *surface;
+    cairo_line_cap_t       line_cap;
+    cairo_point_t          last_move_to_point;
+    cairo_bool_t           has_sub_path;
+} win32_path_info_t;
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_move_to (void *closure, cairo_point_t *point)
+{
+    win32_path_info_t *path_info = closure;
+
+    path_info->last_move_to_point = *point;
+    path_info->has_sub_path = FALSE;
+
+    MoveToEx (path_info->surface->dc,
+	      _cairo_fixed_integer_part (point->x),
+	      _cairo_fixed_integer_part (point->y),
+	      NULL);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_line_to (void *closure, cairo_point_t *point)
+{
+    win32_path_info_t *path_info = closure;
+
+    LineTo (path_info->surface->dc,
+	    _cairo_fixed_integer_part (point->x),
+	    _cairo_fixed_integer_part (point->y));
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_curve_to (void          *closure,
+                                             cairo_point_t *b,
+                                             cairo_point_t *c,
+                                             cairo_point_t *d)
+{
+    win32_path_info_t *path_info = closure;
+    POINT points[3];
+
+    points[0].x = _cairo_fixed_integer_part (b->x);
+    points[0].y = _cairo_fixed_integer_part (b->y);
+    points[1].x = _cairo_fixed_integer_part (c->x);
+    points[1].y = _cairo_fixed_integer_part (c->y);
+    points[2].x = _cairo_fixed_integer_part (d->x);
+    points[2].y = _cairo_fixed_integer_part (d->y);
+    PolyBezierTo (path_info->surface->dc, points, 3);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_path_close_path (void *closure)
+{
+    win32_path_info_t *path_info = closure;
+
+    CloseFigure (path_info->surface->dc);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_win32_printing_surface_emit_path (cairo_win32_surface_t *surface,
+                                         cairo_path_fixed_t    *path)
+{
+    win32_path_info_t path_info;
+    cairo_status_t status;
+
+    path_info.surface = surface;
+    status = _cairo_path_fixed_interpret (path,
+					  CAIRO_DIRECTION_FORWARD,
+					  _cairo_win32_printing_surface_path_move_to,
+					  _cairo_win32_printing_surface_path_line_to,
+					  _cairo_win32_printing_surface_path_curve_to,
+					  _cairo_win32_printing_surface_path_close_path,
+					  &path_info);
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_show_page (void *abstract_surface)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+
+    if (surface->clip_saved_dc != 0)
+	RestoreDC (surface->dc, surface->clip_saved_dc);
+    RestoreDC (surface->dc, -1);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_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_win32_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (path == NULL) {
+	if (surface->clip_saved_dc != 0) {
+	    RestoreDC (surface->dc, surface->clip_saved_dc);
+	    surface->clip_saved_dc = 0;
+	}
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	SetPolyFillMode (surface->dc, WINDING);
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	SetPolyFillMode (surface->dc, ALTERNATE);
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    if (surface->clip_saved_dc == 0)
+	surface->clip_saved_dc = SaveDC (surface->dc);
+    SelectClipPath (surface->dc, RGN_AND);
+
+    return status;
+}
+
+static void
+_cairo_win32_printing_surface_get_font_options (void                  *abstract_surface,
+                                                cairo_font_options_t  *options)
+{
+    _cairo_font_options_init_default (options);
+
+    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
+    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_paint (void             *abstract_surface,
+                                     cairo_operator_t  op,
+                                     cairo_pattern_t  *source)
+{
+    cairo_win32_surface_t *surface = abstract_surface;
+    cairo_solid_pattern_t white;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&white, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
+	source = (cairo_pattern_t*) &white;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+
+    return _cairo_win32_printing_surface_paint_pattern (surface, source);
+}
+
+static int
+_cairo_win32_line_cap (cairo_line_cap_t cap)
+{
+    switch (cap) {
+    case CAIRO_LINE_CAP_BUTT:
+	return PS_ENDCAP_FLAT;
+    case CAIRO_LINE_CAP_ROUND:
+	return PS_ENDCAP_ROUND;
+    case CAIRO_LINE_CAP_SQUARE:
+	return PS_ENDCAP_SQUARE;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static int
+_cairo_win32_line_join (cairo_line_join_t join)
+{
+    switch (join) {
+    case CAIRO_LINE_JOIN_MITER:
+	return PS_JOIN_MITER;
+    case CAIRO_LINE_JOIN_ROUND:
+	return PS_JOIN_ROUND;
+    case CAIRO_LINE_JOIN_BEVEL:
+	return PS_JOIN_BEVEL;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_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_win32_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
+    HPEN pen;
+    LOGBRUSH brush;
+    COLORREF color;
+    XFORM xform;
+    DWORD pen_style;
+    DWORD *dash_array;
+    HGDIOBJ obj;
+    unsigned int i;
+    cairo_solid_pattern_t white;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&white, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
+	source = (cairo_pattern_t*) &white;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	/* Win32 does not support a dash offset. */
+	if (style->num_dashes > 0 && style->dash_offset != 0.0)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+    }
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+
+    dash_array = NULL;
+    if (style->num_dashes) {
+	pen_style = PS_USERSTYLE;
+	dash_array = calloc (sizeof (DWORD), style->num_dashes);
+	for (i = 0; i < style->num_dashes; i++) {
+	    dash_array[i] = (DWORD) style->dash[i];
+	}
+    } else {
+	pen_style = PS_SOLID;
+    }
+
+    SetMiterLimit (surface->dc, (FLOAT) style->miter_limit, NULL);
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+	cairo_color_t c = solid->color;
+
+	if (!CAIRO_COLOR_IS_OPAQUE(&c)) {
+	    /* Blend into white */
+	    c.red = c.red*c.alpha + 1 - c.alpha;
+	    c.green = c.green*c.alpha + 1 - c.alpha;
+	    c.blue = c.blue*c.alpha + 1 - c.alpha;
+	}
+
+	color = RGB ((BYTE)(c.red*255),
+		     (BYTE)(c.green*255),
+		     (BYTE)(c.blue*255));
+    } else {
+	/* Color not used as the pen will only be used by WidenPath() */
+	color = RGB (0,0,0);
+    }
+    brush.lbStyle = BS_SOLID;
+    brush.lbColor = color;
+    brush.lbHatch = 0;
+    pen_style = PS_GEOMETRIC |
+	        _cairo_win32_line_cap (style->line_cap) |
+	        _cairo_win32_line_join (style->line_join);
+    pen = ExtCreatePen(pen_style,
+		       style->line_width < 1.0 ? 1 : _cairo_lround(style->line_width),
+		       &brush,
+		       style->num_dashes,
+		       dash_array);
+    if (pen == NULL)
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen");
+    obj = SelectObject (surface->dc, pen);
+    if (obj == NULL)
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject");
+
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+    if (status)
+	return status;
+
+    /*
+     * Switch to user space to set line parameters
+     */
+    SaveDC (surface->dc);
+    SetGraphicsMode (surface->dc, GM_ADVANCED);
+    _cairo_matrix_to_win32_xform (ctm, &xform);
+    xform.eDx = 0.0f;
+    xform.eDy = 0.0f;
+
+    if (!SetWorldTransform (surface->dc, &xform))
+	return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform");
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	StrokePath (surface->dc);
+    } else {
+	if (!WidenPath (surface->dc))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath");
+	if (!SelectClipPath (surface->dc, RGN_AND))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath");
+
+	/* Return to device space to paint the pattern */
+	if (!ModifyWorldTransform (surface->dc, &xform, MWT_IDENTITY))
+	    return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform");
+	_cairo_win32_printing_surface_paint_pattern (surface, source);
+    }
+    RestoreDC (surface->dc, -1);
+    DeleteObject (pen);
+    if (dash_array)
+	free (dash_array);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_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_win32_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
+    cairo_solid_pattern_t white;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&white, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
+	source = (cairo_pattern_t*) &white;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
+
+    assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
+
+    BeginPath (surface->dc);
+    status = _cairo_win32_printing_surface_emit_path (surface, path);
+    EndPath (surface->dc);
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	SetPolyFillMode (surface->dc, WINDING);
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	SetPolyFillMode (surface->dc, ALTERNATE);
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	_cairo_win32_printing_surface_select_solid_brush (surface, source);
+	FillPath (surface->dc);
+	_cairo_win32_printing_surface_done_solid_brush (surface);
+    } else {
+	SaveDC (surface->dc);
+	SelectClipPath (surface->dc, RGN_AND);
+	_cairo_win32_printing_surface_paint_pattern (surface, source);
+	RestoreDC (surface->dc, -1);
+    }
+
+    fflush(stderr);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_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_win32_surface_t *surface = abstract_surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_pattern_t *opaque = NULL;
+    int i;
+    XFORM xform;
+    cairo_solid_pattern_t white;
+
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	_cairo_pattern_init_solid (&white, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
+	source = (cairo_pattern_t*) &white;
+	op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	if (!(cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
+	      source->type == CAIRO_PATTERN_TYPE_SOLID)) {
+	    for (i = 0; i < num_glyphs; i++) {
+		status = _cairo_scaled_glyph_lookup (scaled_font,
+						     glyphs[i].index,
<