b=411224, r=vlad: 411224-cairo-upgrade-1.5.5
authorvladimir@pobox.com
Fri, 18 Jan 2008 13:46:26 -0800
changeset 10414 df253072d285f862886ea681a0e040445a7fefde
parent 10413 12c08039b6b523800b8b727689a42b6e17c2da51
child 10415 99224b77f8026554900a9991c3369da59651083b
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)
reviewersvlad
bugs411224
milestone1.9b3pre
b=411224, r=vlad: 411224-cairo-upgrade-1.5.5
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-atsui-font.c
gfx/cairo/cairo/src/cairo-bentley-ottmann.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-compiler-private.h
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-directfb.h
gfx/cairo/cairo/src/cairo-features.h.in
gfx/cairo/cairo/src/cairo-fixed-private.h
gfx/cairo/cairo/src/cairo-freelist-private.h
gfx/cairo/cairo/src/cairo-ft-font.c
gfx/cairo/cairo/src/cairo-glitz-surface.c
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-output-stream.c
gfx/cairo/cairo/src/cairo-paginated-private.h
gfx/cairo/cairo/src/cairo-paginated-surface.c
gfx/cairo/cairo/src/cairo-path-bounds.c
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-operators-private.h
gfx/cairo/cairo/src/cairo-pdf-operators.c
gfx/cairo/cairo/src/cairo-pdf-surface-private.h
gfx/cairo/cairo/src/cairo-pdf-surface.c
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-surface.c
gfx/cairo/cairo/src/cairo-region.c
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-unicode.c
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.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-private.h
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
gfx/cairo/cairo/src/cairo-xlib-xrender.h
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/check-has-hidden-symbols.c
gfx/cairo/libpixman/src/pixman-compose.c
gfx/cairo/libpixman/src/pixman-pict.c
gfx/cairo/libpixman/src/pixman-private.h
gfx/cairo/libpixman/src/pixman.h
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,18 +2,18 @@ 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 - 1.5.2-55-g39b8ddf)
-  pixman (0.9.x - pixman-0.9.6-13-g4193b3c)
+  cairo (1.5.x - 1.5.4-141-g57c2b75)
+  pixman (0.9.x - pixman-0.9.6-25-ge0af592)
   glitz 0.5.2 (cvs - 2006-01-10)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
 ==== Patches ====
 
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -116,61 +116,64 @@ CSRCS   = \
         cairo-surface-fallback.c \
         cairo-traps.c \
         cairo-unicode.c \
         cairo-wideint.c \
         $(NULL)
 
 EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
 
+PSPDF_BASE_CSRCS = \
+	cairo-base85-stream.c \
+	cairo-type1-subset.c \
+	cairo-type1-fallback.c \
+	cairo-truetype-subset.c \
+	cairo-cff-subset.c \
+	$(NULL)
+
+PDF_CSRCS = \
+	cairo-pdf-surface.c \
+	cairo-pdf-operators.c \
+	$(NULL)
+
+PS_CSRCS = cairo-ps-surface.c
+
+PDF_EXPORTS = cairo-pdf.h
+PS_EXPORTS = cairo-ps.h
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
-CSRCS   += cairo-win32-font.c \
-           cairo-win32-surface.c \
+CSRCS	+= cairo-win32.c \
+	   cairo-win32-font.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
+CSRCS   += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS)
+EXPORTS += $(PDF_EXPORTS)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 CSRCS   += cairo-os2-surface.c
 EXPORTS += cairo-os2.h cairo-os2-private.h
-CSRCS   += cairo-base85-stream.c \
-           cairo-pdf-surface.c \
-           cairo-type1-subset.c \
-           cairo-type1-fallback.c \
-           cairo-truetype-subset.c \
-           cairo-cff-subset.c
-EXPORTS += cairo-pdf.h
+CSRCS   += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS)
+EXPORTS += $(PDF_EXPORTS)
 endif
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 CSRCS   += cairo-quartz-surface.c cairo-atsui-font.c
 EXPORTS += cairo-quartz.h cairo-atsui.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 CPPSRCS += cairo-beos-surface.cpp
 EXPORTS += cairo-beos.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-CSRCS   += cairo-base85-stream.c \
-           cairo-pdf-surface.c \
-           cairo-ps-surface.c \
-	   cairo-type1-subset.c \
-	   cairo-type1-fallback.c \
-	   cairo-truetype-subset.c \
-	   cairo-cff-subset.c
-EXPORTS += cairo-ps.h cairo-pdf.h
+CSRCS   += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS)
+EXPORTS += $(PDF_EXPORTS) $(PS_EXPORTS)
 endif
 
 ifdef BUILD_CAIRO_SVG
 CSRCS	+= cairo-svg-surface.c
 EXPORTS += cairo-svg.h
 endif
 
 ifdef MOZ_X11
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -52,56 +52,89 @@ typedef struct {
     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_box_t page_bbox;
 
+    cairo_bool_t has_ctm;
+    cairo_matrix_t ctm;
+
 } 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_t *analysis = &surface->base;
     cairo_surface_pattern_t *surface_pattern;
-    cairo_surface_t *meta_surface;
-    cairo_surface_t *analysis;
     cairo_status_t status;
+    cairo_bool_t old_has_ctm;
+    cairo_matrix_t old_ctm, p2d;
 
     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_error (CAIRO_STATUS_NO_MEMORY);
+    old_ctm = surface->ctm;
+    old_has_ctm = surface->has_ctm;
+    p2d = pattern->matrix;
+    status = cairo_matrix_invert (&p2d);
+    /* _cairo_pattern_set_matrix guarantees invertibility */
+    assert (status == CAIRO_STATUS_SUCCESS);
 
-    status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis);
+    cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
+
+    status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
+							    analysis);
     if (status == CAIRO_STATUS_SUCCESS)
-	    status = analysis->status;
-    cairo_surface_destroy (analysis);
+	status = analysis->status;
+
+    surface->ctm = old_ctm;
+    surface->has_ctm = old_has_ctm;
 
     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;
     cairo_box_t bbox;
 
     if (rect->width == 0 || rect->height == 0)
 	return CAIRO_STATUS_SUCCESS;
 
+    if (surface->has_ctm) {
+	double x1, y1, x2, y2;
+
+	x1 = rect->x;
+	y1 = rect->y;
+	x2 = rect->x + rect->width;
+	y2 = rect->y + rect->height;
+	_cairo_matrix_transform_bounding_box (&surface->ctm,
+					      &x1, &y1, &x2, &y2,
+					      NULL);
+	rect->x = floor (x1);
+	rect->y = floor (y1);
+
+	x2 = ceil (x2) - rect->x;
+	y2 = ceil (y2) - rect->y;
+	if (x2 <= 0 || y2 <= 0)
+	    return CAIRO_STATUS_SUCCESS;
+
+	rect->width  = x2;
+	rect->height = y2;
+    }
+
     bbox.p1.x = _cairo_fixed_from_int (rect->x);
     bbox.p1.y = _cairo_fixed_from_int (rect->y);
     bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
     bbox.p2.y = _cairo_fixed_from_int (rect->y + rect->height);
 
     if (surface->first_op) {
 	surface->first_op = FALSE;
 	surface->page_bbox = bbox;
@@ -183,38 +216,34 @@ static cairo_int_status_t
 					     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.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;
+	_cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
 
 	extent.x = floor (x1);
 	extent.y = floor (y1);
-	extent.width = ceil (x2) - extent.x;
+	extent.width  = ceil (x2) - extent.x;
 	extent.height = ceil (y2) - extent.y;
 
 	_cairo_rectangle_intersect (&surface->current_clip, &extent);
     }
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 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;
 
@@ -377,17 +406,17 @@ static cairo_int_status_t
 	_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) {
+	if (status || traps.num_traps == 0) {
 	    _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;
@@ -400,19 +429,19 @@ static cairo_int_status_t
     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,
+			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
-			      cairo_antialias_t	 	 antialias)
+			      cairo_antialias_t		 antialias)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_traps_t            traps;
     cairo_box_t              box;
     cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->fill)
@@ -449,17 +478,17 @@ static cairo_int_status_t
 
 	_cairo_traps_init (&traps);
 	_cairo_traps_limit (&traps, &box);
 	status = _cairo_path_fixed_fill_to_traps (path,
 						  fill_rule,
 						  tolerance,
 						  &traps);
 
-	if (status) {
+	if (status || traps.num_traps == 0) {
 	    _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;
@@ -572,16 +601,18 @@ cairo_surface_t *
 
     /* I believe the content type here is truly arbitrary. I'm quite
      * 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;
+    cairo_matrix_init_identity (&surface->ctm);
+    surface->has_ctm = FALSE;
 
     surface->target = target;
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
     _cairo_region_init (&surface->supported_region);
     _cairo_region_init (&surface->fallback_region);
 
--- a/gfx/cairo/cairo/src/cairo-atsui-font.c
+++ b/gfx/cairo/cairo/src/cairo-atsui-font.c
@@ -268,18 +268,17 @@ static cairo_status_t
 					 &xscale, &yscale, 1);
     font->font_matrix = CGAffineTransformMake (1., 0.,
 					       0., yscale/xscale,
 					       0., 0.);
     font->size = FloatToFixed (xscale);
 
     err = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix, &font->style);
     if (err != noErr) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	status = CAIRO_STATUS_NO_MEMORY;
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL;
     }
 
     {
 	Fixed theSize = FloatToFixed(1.0);
 	const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
 	const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
 	ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
@@ -296,18 +295,17 @@ static cairo_status_t
 
     font->unscaled_style = style;
     font->fontID = font_id;
 
     *font_out = &font->base;
 
     status = _cairo_atsui_font_set_metrics (font);
 
-    font->cgfref = NULL;
-
+    font->cgfref = 0;
   FAIL:
     if (status) {
 	if (font) {
 	    if (font->style)
 		ATSUDisposeStyle(font->style);
 	    free (font);
 	}
 
@@ -448,16 +446,17 @@ static void
         return;
 
     if (font->style)
         ATSUDisposeStyle(font->style);
     if (font->unscaled_style)
         ATSUDisposeStyle(font->unscaled_style);
     if (font->cgfref)
 	CGFontRelease(font->cgfref);
+
 }
 
 static GlyphID 
 _cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
     unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
     if (index > 0xffff) 
 	return kATSDeletedGlyphcode;
     return index;
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -1416,17 +1416,17 @@ update_minmax(cairo_fixed_t *inout_min,
 
 cairo_status_t
 _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	*traps,
 					   cairo_polygon_t	*polygon,
 					   cairo_fill_rule_t	 fill_rule)
 {
     int intersections;
     cairo_status_t status;
-    cairo_bo_edge_t stack_edges[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_bo_edge_t)];
+    cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)];
     cairo_bo_edge_t *edges;
     cairo_fixed_t xmin = 0x7FFFFFFF;
     cairo_fixed_t ymin = 0x7FFFFFFF;
     cairo_fixed_t xmax = -0x80000000;
     cairo_fixed_t ymax = -0x80000000;
     int num_bo_edges;
     int i;
 
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -699,17 +699,17 @@ static cairo_bool_t
     user_rect->x = x1;
     user_rect->y = y1;
     user_rect->width = x2 - x1;
     user_rect->height = y2 - y1;
 
     return is_tight;
 }
 
-cairo_private cairo_rectangle_list_t*
+cairo_rectangle_list_t *
 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 {
     cairo_rectangle_list_t *list;
     cairo_rectangle_t *rectangles = NULL;
     int n_boxes = 0;
 
     if (clip->all_clipped)
 	goto DONE;
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -65,22 +65,24 @@ CAIRO_BEGIN_DECLS
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
 #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \
 	__attribute__((__format__(__printf__, fmt_index, va_index)))
 #else
 #define CAIRO_PRINTF_FORMAT(fmt_index, va_index)
 #endif
 
 /* slim_internal.h */
+#define CAIRO_HAS_HIDDEN_SYMBOLS 1
 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
 #define cairo_private_no_warn	__attribute__((__visibility__("hidden")))
 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
 #define cairo_private_no_warn	__hidden
 #else /* not gcc >= 3.3 and not Sun Studio >= 8 */
 #define cairo_private_no_warn
+#undef CAIRO_HAS_HIDDEN_SYMBOLS
 #endif
 
 #ifndef WARN_UNUSED_RESULT
 #define WARN_UNUSED_RESULT
 #endif
 /* Add attribute(warn_unused_result) if supported */
 #define cairo_warn	    WARN_UNUSED_RESULT
 #define cairo_private	    cairo_private_no_warn cairo_warn
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -29,33 +29,36 @@
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *    Michael Emmel <mike.emmel@gmail.com>
  *    Claudio Ciccani <klan@users.sf.net>
  */
+ 
 
 #include "cairoint.h"
-
 #include "cairo-directfb.h"
 
+#include <stdlib.h>
+
 #include <directfb.h>
-
 #include <direct/types.h>
 #include <direct/debug.h>
 #include <direct/memcpy.h>
 #include <direct/util.h>
 
 
 /*
- * Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
+ * Rectangle works fine.
+ * Bugs 361377, 359553, 359243 in Gnome BTS are caused
+ * by GDK/DirectFB, not by Cairo/DirectFB.
  */
-#define DFB_RECTANGLES 0
+#define DFB_RECTANGLES 1
 
 /*
  * Composite works fine.
  */
 #define DFB_COMPOSITE 1 
 
 /*
  * CompositeTrapezoids works (without antialiasing).
@@ -63,35 +66,40 @@
 #define DFB_COMPOSITE_TRAPEZOIDS 0
 
 /*
  * ShowGlyphs works fine.
  */
 #define DFB_SHOW_GLYPHS 1
 
 
-D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend")
+D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend");
 
 /*****************************************************************************/
 
 
 typedef struct _cairo_directfb_surface {
     cairo_surface_t      base;
     cairo_format_t       format;
+    cairo_content_t      content;
+    
     IDirectFB           *dfb;
-    int                 owner;
     IDirectFBSurface    *dfbsurface;
+    IDirectFBSurface    *tmpsurface;
+    
     /* color buffer */
     cairo_surface_t     *color;
         
     DFBRegion           *clips;
     int                  n_clips;
-    DFBRegion           *dirty_region;
+    
     int                  width;
     int                  height;
+    
+    cairo_bool_t         local;
 } cairo_directfb_surface_t;
 
 
 typedef struct _cairo_directfb_font_cache {
     IDirectFB           *dfb; 
     IDirectFBSurface    *dfbsurface;
 
     int                  width;
@@ -103,16 +111,20 @@ typedef struct _cairo_directfb_font_cach
     int                  y;
 } cairo_directfb_font_cache_t;
     
 
 static cairo_surface_backend_t cairo_directfb_surface_backend;
 
 /*****************************************************************************/
 
+static int _directfb_argb_font = 0;
+
+/*****************************************************************************/
+
 
 #define RUN_CLIPPED( surface, clip, func ) {\
     if ((surface)->clips) {\
         int k;\
         for (k = 0; k < (surface)->n_clips; k++) {\
             if (clip) {\
                 DFBRegion  reg = (surface)->clips[k];\
                 DFBRegion *cli = (clip);\
@@ -137,46 +149,50 @@ static cairo_surface_backend_t cairo_dir
         }\
     }\
     else {\
         (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
         func;\
     }\
 }
 
-#define TRANSFORM_POINT( m, x, y, ret_x, ret_y ) {\
+#define TRANSFORM_POINT2X( m, x, y, ret_x, ret_y ) {\
     double _x = (x);\
     double _y = (y);\
-    (ret_x) = (_x * (m)->xx + _y * (m)->xy + (m)->x0);\
-    (ret_y) = (_x * (m)->yx + _y * (m)->yy + (m)->y0);\
+    (ret_x) = (_x * (m).xx + (m).x0);\
+    (ret_y) = (_y * (m).yy + (m).y0);\
+}
+
+#define TRANSFORM_POINT3X( m, x, y, ret_x, ret_y ) {\
+    double _x = (x);\
+    double _y = (y);\
+    (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\
+    (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\
 }
 
 /* XXX: A1 has a different bits ordering in cairo.
  *      Probably we should drop it.
  */
 
 static cairo_content_t 
-_directfb_format_to_content ( DFBSurfacePixelFormat format )
+_directfb_format_to_content (DFBSurfacePixelFormat format)
 {
-    switch (format) {
-        case DSPF_ARGB:
+    if (DFB_PIXELFORMAT_HAS_ALPHA(format)) {
+        if (DFB_COLOR_BITS_PER_PIXEL(format))
             return CAIRO_CONTENT_COLOR_ALPHA;
-        case DSPF_A8: 
-            return CAIRO_CONTENT_ALPHA;
-        case DSPF_RGB32:
-        case DSPF_A1: 
-        default:
-            return CAIRO_CONTENT_COLOR;
-         break;
+            
+        return CAIRO_CONTENT_ALPHA;
     }
+    
+    return CAIRO_CONTENT_COLOR;
 }
 
                                                            
 static inline DFBSurfacePixelFormat 
-cairo_to_directfb_format (cairo_format_t format)
+_cairo_to_directfb_format (cairo_format_t format)
 {
     switch (format) {
         case CAIRO_FORMAT_RGB24:
             return DSPF_RGB32;
         case CAIRO_FORMAT_ARGB32:
             return DSPF_ARGB; 
         case CAIRO_FORMAT_A8:
             return DSPF_A8; 
@@ -185,55 +201,51 @@ cairo_to_directfb_format (cairo_format_t
         default:
             break;
     }
     
     return -1;
 }
 
 static inline cairo_format_t
-directfb_to_cairo_format (DFBSurfacePixelFormat format)
+_directfb_to_cairo_format (DFBSurfacePixelFormat format)
 {
     switch (format) {
         case DSPF_RGB32:
             return CAIRO_FORMAT_RGB24;
         case DSPF_ARGB:
             return CAIRO_FORMAT_ARGB32;
-        case DSPF_A8 :
+        case DSPF_A8:
             return CAIRO_FORMAT_A8;
-        case DSPF_A1 :
+        case DSPF_A1:
             return CAIRO_FORMAT_A1;
         default:
             break;
     }
     
     return -1;
 }
 
 
 static cairo_status_t
 _directfb_get_operator (cairo_operator_t         operator,
-                        DFBSurfaceDrawingFlags  *ret_drawing,
-                        DFBSurfaceBlittingFlags *ret_blitting,
                         DFBSurfaceBlendFunction *ret_srcblend,
                         DFBSurfaceBlendFunction *ret_dstblend )
-{ 
-    DFBSurfaceDrawingFlags  drawing  = DSDRAW_BLEND;
-    DFBSurfaceBlittingFlags blitting = DSBLIT_BLEND_ALPHACHANNEL;
+{
     DFBSurfaceBlendFunction srcblend = DSBF_ONE;
     DFBSurfaceBlendFunction dstblend = DSBF_ZERO;
     
     switch (operator) {
         case CAIRO_OPERATOR_CLEAR:
             srcblend = DSBF_ZERO;
             dstblend = DSBF_ZERO;
             break;
         case CAIRO_OPERATOR_SOURCE:
-            drawing  = DSDRAW_NOFX;
-            blitting = DSBLIT_NOFX;
+            srcblend = DSBF_ONE;
+            dstblend = DSBF_ZERO;
             break;
         case CAIRO_OPERATOR_OVER:
             srcblend = DSBF_ONE;
             dstblend = DSBF_INVSRCALPHA;
             break;
         case CAIRO_OPERATOR_IN:
             srcblend = DSBF_DESTALPHA;
             dstblend = DSBF_ZERO;
@@ -276,21 +288,17 @@ static cairo_status_t
             break;
         case CAIRO_OPERATOR_SATURATE:
             srcblend = DSBF_SRCALPHASAT;
             dstblend = DSBF_ONE;
             break;
         default:
             return CAIRO_INT_STATUS_UNSUPPORTED;
     }
-    
-    if (ret_drawing)
-        *ret_drawing = drawing;
-    if (ret_blitting)
-        *ret_blitting = blitting;
+
     if (ret_srcblend)
         *ret_srcblend = srcblend;
     if (ret_dstblend)
         *ret_dstblend = dstblend;
     
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -314,86 +322,116 @@ static IDirectFBSurface*
         DirectFBError ("IDirectFB::CreateSurface()", ret);
         return NULL;
     }
     
     return buffer;
 }
 
 static cairo_status_t
-_directfb_acquire_surface (cairo_directfb_surface_t *surface, 
-                                              cairo_rectangle_int_t *intrest_rec,
-                                              cairo_image_surface_t **image_out,
-                                              cairo_rectangle_int_t *image_rect_out,
-                                              void                  **image_extra,
-                                              DFBSurfaceLockFlags       lock_flags)
+_directfb_acquire_surface (cairo_directfb_surface_t  *surface, 
+                           cairo_rectangle_int_t     *intrest_rec,
+                           cairo_image_surface_t    **image_out,
+                           cairo_rectangle_int_t     *image_rect_out,
+                           void                     **image_extra,
+                           DFBSurfaceLockFlags        lock_flags)
 {   
-    void      *data;
-    int        pitch;
-    IDirectFBSurface *buffer;
+    IDirectFBSurface *buffer = NULL;
     DFBRectangle source_rect;
-    cairo_format_t            cairo_format;
-    cairo_format = surface->format;    
+    cairo_format_t cairo_format;
+    void *data;
+    int   pitch; 
         
     if (surface->format == (cairo_format_t) -1) {
-        if( intrest_rec ) {
+        DFBSurfaceCapabilities caps;
+        
+        if (intrest_rec) {
             source_rect.x = intrest_rec->x;
             source_rect.y = intrest_rec->y;
             source_rect.w = intrest_rec->width; 
             source_rect.h = intrest_rec->height; 
-        }else {
-            source_rect.x=0;
-            source_rect.y=0;
-            surface->dfbsurface->GetSize (surface->dfbsurface,&source_rect.w, &source_rect.h);   
+        } else {
+            source_rect.x = 0;
+            source_rect.y = 0;
+            surface->dfbsurface->GetSize (surface->dfbsurface,
+                                          &source_rect.w, &source_rect.h);   
+        }
+
+        if (surface->tmpsurface) {
+            int w, h;
+            surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h);
+            if (w < source_rect.w || h < source_rect.h) {
+                surface->tmpsurface->Release (surface->tmpsurface);
+                surface->tmpsurface = NULL;
+            }
+        }
+        
+        cairo_format = _cairo_format_from_content (surface->content);
+        if (!surface->tmpsurface) {
+            D_DEBUG_AT (Cairo_DirectFB, "Allocating buffer for surface %p.\n", surface);
+       
+            surface->tmpsurface = 
+                _directfb_buffer_surface_create (surface->dfb, 
+                                                 _cairo_to_directfb_format (cairo_format),
+                                                 source_rect.w, source_rect.h);
+            if (!surface->tmpsurface)
+                goto ERROR;
         }
-        D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n",
-                         surface->dfbsurface ? "Reallocating" : "Allocating");
-        cairo_format = directfb_to_cairo_format(DSPF_ARGB);    
-        buffer = _directfb_buffer_surface_create (surface->dfb,DSPF_ARGB,source_rect.w,source_rect.h);
-        if (!buffer)
-            goto ERROR;
-        *image_extra = buffer;        
-        buffer->SetBlittingFlags (buffer,DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE);
-        buffer->Blit (buffer,surface->dfbsurface,&source_rect,0,0);
-    } else {
+        buffer = surface->tmpsurface;
+        
+        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
+        if (caps & DSCAPS_FLIPPING) {
+            DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, 
+                                 .x2 = source_rect.x + source_rect.w - 1,
+                                 .y2 = source_rect.y + source_rect.h - 1 };
+            surface->dfbsurface->Flip (surface->dfbsurface, &region, DSFLIP_BLIT);
+        } 
+        buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0);
+    }
+    else {
         /*might be a subsurface get the offset*/
-        surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface,&source_rect);
-        buffer = surface->dfbsurface;
-        *image_extra = buffer;        
+        surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
+        cairo_format = surface->format;
+        buffer = surface->dfbsurface;     
     }
-      
-        
-    if( buffer->Lock (buffer,lock_flags, &data, &pitch) )
+    
+    *image_extra = buffer;
+    
+    if (buffer->Lock (buffer, lock_flags, &data, &pitch)) {
+        D_DEBUG_AT (Cairo_DirectFB, "Couldn't lock surface!\n");
         goto ERROR;
+    }
             
-    *image_out = (cairo_image_surface_t *)cairo_image_surface_create_for_data (data,
-                          cairo_format,source_rect.w,source_rect.h, pitch);
-   if (*image_out == NULL ) 
-      goto ERROR;
+    *image_out = (cairo_image_surface_t *)
+                    cairo_image_surface_create_for_data (data, cairo_format,
+                                            source_rect.w, source_rect.h, pitch);
+    if (*image_out == NULL) 
+        goto ERROR;
 
     if (image_rect_out) {
         image_rect_out->x = source_rect.x;
         image_rect_out->y = source_rect.y;
         image_rect_out->width = source_rect.w;
         image_rect_out->height = source_rect.h;
-    }else {
-        /*lock for read*/
+    } else {
+        /* lock for read */
         cairo_surface_t *sur = &((*image_out)->base); 
-        /*might be a subsurface*/
-        if( buffer == surface->dfbsurface )
-            cairo_surface_set_device_offset (sur,source_rect.x,source_rect.y);
+        /* might be a subsurface */
+        if (buffer == surface->dfbsurface)
+            cairo_surface_set_device_offset (sur, source_rect.x, source_rect.y);
     }
-   return CAIRO_STATUS_SUCCESS;
+   
+    return CAIRO_STATUS_SUCCESS;
 
-   ERROR:
+ERROR:
     *image_extra = NULL;
-    if( buffer ) {
-      buffer->Unlock (buffer);
-      if( buffer != surface->dfbsurface) 
-        buffer->Release(buffer);
+    if (buffer) {
+        buffer->Unlock (buffer);
+        if (buffer != surface->dfbsurface) 
+            buffer->Release (buffer);
     }
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 }
 
 
 
 static cairo_surface_t *
 _cairo_directfb_surface_create_similar (void            *abstract_src,
@@ -410,36 +448,52 @@ static cairo_surface_t *
                 __FUNCTION__, source, content, width, height);
     
     width = (width <= 0) ? 1 : width;
     height = (height<= 0) ? 1 : height;
 
     format = _cairo_format_from_content (content);             
     surface = calloc (1, sizeof(cairo_directfb_surface_t));
     if (!surface) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         return NULL;
     }
    
-    surface->dfbsurface = _directfb_buffer_surface_create (source->dfb,
-                                              cairo_to_directfb_format (format),
-                                              width, height);
-    assert(surface->dfbsurface);
-
-    surface->owner = TRUE;
+    surface->dfb = source->dfb;
+    
+    if (width < 8 || height < 8) {
+        IDirectFBSurface *tmp;
+        /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
+        tmp =  _directfb_buffer_surface_create (surface->dfb, 
+                                        _cairo_to_directfb_format (format),
+                                        MAX (width, 8), MAX (height, 8));
+        if (tmp) {
+            DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
+            tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
+            tmp->Release (tmp);
+        }
+    }
+    else {
+        surface->dfbsurface = _directfb_buffer_surface_create (surface->dfb,
+                                    _cairo_to_directfb_format (format), width, height);
+    }
+    
     if (!surface->dfbsurface) {
-        assert(0);
+        D_ASSERT (surface->dfbsurface != NULL);
         free (surface);
         return NULL;
     }
-    _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,content);
-    surface->dfb = source->dfb;
-    surface->format = format;
-    surface->width  = width;
-    surface->height = height;
+    
+    _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, content);
+    surface->format  = format;
+    surface->content = content;
+    surface->width   = width;
+    surface->height  = height;
+    surface->local   = true;
+    
     return &surface->base;
 }
 
 static cairo_status_t
 _cairo_directfb_surface_finish (void *data)
 {
     cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data;
     
@@ -451,110 +505,119 @@ static cairo_status_t
         surface->clips   = NULL;
         surface->n_clips = 0;
     }
     
     if (surface->color) {
         cairo_surface_destroy (surface->color);
         surface->color = NULL;
     }
+    
+    if (surface->tmpsurface) {
+        surface->tmpsurface->Release (surface->tmpsurface);
+        surface->tmpsurface = NULL;
+    }
 
     if (surface->dfbsurface) {
-       if( surface->owner )
         surface->dfbsurface->Release (surface->dfbsurface);
-       surface->dfbsurface = NULL;
+        surface->dfbsurface = NULL;
     }
     
-    if (surface->dfb) {
-        surface->dfb     = NULL;
-    }
+    if (surface->dfb)
+        surface->dfb = NULL;
         
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_directfb_surface_acquire_source_image (void                   *abstract_surface,
                                               cairo_image_surface_t **image_out,
                                               void                  **image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
+    
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
-    return _directfb_acquire_surface (surface,NULL,image_out,NULL,image_extra,DSLF_READ);
+    
+    return _directfb_acquire_surface (surface, NULL, image_out, 
+                                      NULL, image_extra, DSLF_READ);
 }
 
 static void
 _cairo_directfb_surface_release_source_image (void                  *abstract_surface,
                                               cairo_image_surface_t *image,
                                               void                  *image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra;
     
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
     
     buffer->Unlock (buffer);
-    if (surface->dfbsurface != buffer) {
-        buffer->Release (buffer);
-    }
+    
     cairo_surface_destroy (&image->base);
 }
 
 static cairo_status_t
-_cairo_directfb_surface_acquire_dest_image (void                   *abstract_surface,
-                                            cairo_rectangle_int_t      *interest_rect,
-                                            cairo_image_surface_t **image_out,
-                                            cairo_rectangle_int_t      *image_rect_out,
-                                            void                  **image_extra)
+_cairo_directfb_surface_acquire_dest_image (void                     *abstract_surface,
+                                            cairo_rectangle_int_t    *interest_rect,
+                                            cairo_image_surface_t   **image_out,
+                                            cairo_rectangle_int_t    *image_rect_out,
+                                            void                    **image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
     D_DEBUG_AT (Cairo_DirectFB, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
+                "%s( surface=%p, interest_rect={ %d %d %d %d } ).\n", 
+                __FUNCTION__, surface, 
+                interest_rect ? interest_rect->x : 0,
+                interest_rect ? interest_rect->y : 0,
+                interest_rect ? interest_rect->width : surface->width,
+                interest_rect ? interest_rect->height : surface->height);
     
-    return _directfb_acquire_surface (surface,interest_rect,image_out,image_rect_out,image_extra,
-                                            DSLF_READ | DSLF_WRITE);
+    return _directfb_acquire_surface (surface, interest_rect, image_out, 
+                                      image_rect_out, image_extra, DSLF_READ | DSLF_WRITE);
 }
 
 static void
 _cairo_directfb_surface_release_dest_image (void                  *abstract_surface,
-                                            cairo_rectangle_int_t     *interest_rect,
+                                            cairo_rectangle_int_t *interest_rect,
                                             cairo_image_surface_t *image,
-                                            cairo_rectangle_int_t     *image_rect,
+                                            cairo_rectangle_int_t *image_rect,
                                             void                  *image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra; 
     
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
+    
     buffer->Unlock (buffer);
 
     if (surface->dfbsurface != buffer) {
         DFBRegion region = { .x1 = interest_rect->x, .y1 = interest_rect->y,
-                .x2 = interest_rect->x+interest_rect->width-1,
-                .y2 = interest_rect->y+interest_rect->height-1 };
+                             .x2 = interest_rect->x+interest_rect->width-1,
+                             .y2 = interest_rect->y+interest_rect->height-1 };
         surface->dfbsurface->SetClip (surface->dfbsurface, &region);
-        /* surface->dfbsurface->SetBlittingFlags (surface->dfbsurface,
-                        DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE); */
-        surface->dfbsurface->Blit (surface->dfbsurface,buffer,NULL,
-                        image_rect->x,image_rect->y);
-        buffer->Release (buffer);
+        surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
+        surface->dfbsurface->Blit (surface->dfbsurface, buffer,
+                                   NULL, image_rect->x, image_rect->y);
     }
+    
     cairo_surface_destroy (&image->base);
 }
 
 static cairo_status_t
 _cairo_directfb_surface_clone_similar (void             *abstract_surface,
                                        cairo_surface_t  *src,
-				       int               src_x,
-				       int               src_y,
-				       int               width,
-				       int               height,
+                                       int               src_x,
+                                       int               src_y,
+                                       int               width,
+                                       int               height,
                                        cairo_surface_t **clone_out)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     cairo_directfb_surface_t *clone;
     
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src);
 
@@ -581,32 +644,43 @@ static cairo_status_t
         ret = clone->dfbsurface->Lock (clone->dfbsurface, 
                                    DSLF_WRITE, (void *)&dst, &pitch);
         if (ret) {
             DirectFBError ("IDirectFBSurface::Lock()", ret);
             cairo_surface_destroy ((cairo_surface_t *)clone);
             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
         }
 
-	dst += pitch * src_y;
-	src += image_src->stride * src_y;
+        dst += pitch * src_y;
+        src += image_src->stride * src_y;
         
         if (image_src->format == CAIRO_FORMAT_A1) {
             /* A1 -> A8 */
             for (i = 0; i < height; i++) {
                 for (j = src_x; j < src_x + width; j++)
                     dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
                 dst += pitch;
                 src += image_src->stride;
             }
         }
         else {
-	    /* A8 -> A8 */
+            int len;
+            
+            if (image_src->format == CAIRO_FORMAT_A8) {
+                dst += src_x;
+                src += src_x;
+                len  = width;
+            } else {
+                dst += src_x * 4;
+                src += src_x * 4;
+                len  = width * 4;
+            }
+            
             for (i = 0; i < height; i++) {
-                direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width );
+                direct_memcpy (dst+src_x, src+src_x, len);
                 dst += pitch;
                 src += image_src->stride;
             }
         }
         
         clone->dfbsurface->Unlock (clone->dfbsurface);
         
         *clone_out = &clone->base;
@@ -614,36 +688,36 @@ static cairo_status_t
         return CAIRO_STATUS_SUCCESS;
     }
     
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
-_directfb_prepare_composite (cairo_directfb_surface_t   *dst,
+_directfb_prepare_composite (cairo_directfb_surface_t    *dst,
                              cairo_pattern_t             *src_pattern,
                              cairo_pattern_t             *mask_pattern,
                              cairo_operator_t             op,
                              int *src_x,             int *src_y,
                              int *mask_x,            int *mask_y,
                              unsigned int                 width,
                              unsigned int                 height,                        
                              cairo_directfb_surface_t   **ret_src,
                              cairo_surface_attributes_t  *ret_src_attr)
 {
     cairo_directfb_surface_t   *src;
-    cairo_surface_attributes_t	src_attr;
+    cairo_surface_attributes_t  src_attr;
     cairo_status_t              ret;
     DFBSurfaceBlittingFlags     flags;
     DFBSurfaceBlendFunction     sblend;
     DFBSurfaceBlendFunction     dblend;
     DFBColor                    color;
     
-    if (_directfb_get_operator (op, NULL, &flags, &sblend, &dblend))
+    if (_directfb_get_operator (op, &sblend, &dblend))
         return CAIRO_INT_STATUS_UNSUPPORTED;
      
     if (mask_pattern) {
         cairo_solid_pattern_t *pattern;
         
         if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
             cairo_pattern_t *tmp;
             int              tmp_x, tmp_y;
@@ -658,20 +732,19 @@ static cairo_int_status_t
             tmp_x = *src_x; tmp_y = *src_y;
             
             src_pattern = mask_pattern;
             *src_x = *mask_x; *src_y = *mask_y;
             
             mask_pattern = tmp;
             *mask_x = tmp_x; *mask_y = tmp_y;
             
-            if (sblend == DSBF_ONE) {
-                flags |= DSBLIT_BLEND_ALPHACHANNEL;                   
+            if (sblend == DSBF_ONE) {                  
                 sblend = DSBF_SRCALPHA;
-                /* dblend = DSBF_INVSRCALPHA; */
+                /*dblend = DSBF_INVSRCALPHA;*/
             }
         }
             
         pattern = (cairo_solid_pattern_t *)mask_pattern;
         color.a = pattern->color.alpha_short >> 8;
         color.r = pattern->color.red_short   >> 8;
         color.g = pattern->color.green_short >> 8;
         color.b = pattern->color.blue_short  >> 8;
@@ -686,46 +759,69 @@ static cairo_int_status_t
         if (!dst->color) {
             dst->color = _cairo_directfb_surface_create_similar (dst,
                                                 CAIRO_CONTENT_COLOR_ALPHA, 1, 1);
             if (!dst->color)
                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
         }
         
         src = (cairo_directfb_surface_t *)dst->color;
-        src->dfbsurface->SetColor (src->dfbsurface,
-                               pattern->color.red_short   >> 8,
-                               pattern->color.green_short >> 8,
-                               pattern->color.blue_short  >> 8,
-                               pattern->color.alpha_short >> 8);
-        src->dfbsurface->FillRectangle (src->dfbsurface, 0, 0, 1, 1);
-        
-        cairo_matrix_init_identity (&src_attr.matrix);                           
+        src->dfbsurface->Clear (src->dfbsurface,
+                                pattern->color.red_short   >> 8,
+                                pattern->color.green_short >> 8,
+                                pattern->color.blue_short  >> 8,
+                                pattern->color.alpha_short >> 8);
+                                  
         src_attr.matrix   = src_pattern->matrix;
         src_attr.extend   = CAIRO_EXTEND_NONE;
         src_attr.filter   = CAIRO_FILTER_NEAREST;
         src_attr.x_offset =
         src_attr.y_offset = 0;
     }
     else {
         ret = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
                                               *src_x, *src_y, width, height,
                                               (cairo_surface_t **)&src, &src_attr);
         if (ret)
             return ret;
     }
-        
+    
+    if (src->content == CAIRO_CONTENT_COLOR) {
+        if (sblend == DSBF_SRCALPHA)
+            sblend = DSBF_ONE;
+        else if (sblend == DSBF_INVSRCALPHA)
+            sblend = DSBF_ZERO;
+            
+        if (dblend == DSBF_SRCALPHA)
+            dblend = DSBF_ONE;
+        else if (dblend == DSBF_INVSRCALPHA)
+            dblend = DSBF_ZERO;
+    }
+    if (dst->content == CAIRO_CONTENT_COLOR) {
+        if (sblend == DSBF_DESTALPHA)
+            sblend = DSBF_ONE;
+        else if (sblend == DSBF_INVDESTALPHA)
+            sblend = DSBF_ZERO;
+         
+        if (dblend == DSBF_DESTALPHA)
+            dblend = DSBF_ONE;
+        else if (dblend == DSBF_INVDESTALPHA)
+            dblend = DSBF_ZERO;   
+    }
+
+    flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) 
+            ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; 
     if (color.a != 0xff)
         flags |= DSBLIT_BLEND_COLORALPHA;
     if (color.r != 0xff || color.g != 0xff || color.b != 0xff)
         flags |= DSBLIT_COLORIZE;
             
     dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
     
-    if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL)) {
+    if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
         dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
         dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
     }
     
     if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE))    
         dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); 
         
     *ret_src = src;
@@ -741,210 +837,268 @@ static void
                             cairo_surface_attributes_t *src_attr)
 {
     if (src != dst->color)
          _cairo_pattern_release_surface (src_pattern, src, src_attr);
 }
 #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */        
 
 #if DFB_COMPOSITE
+static DFBAccelerationMask
+_directfb_categorize_operation (cairo_surface_attributes_t *src_attr)
+{
+    cairo_matrix_t *m = &src_attr->matrix;
+    
+    if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) {
+        if (src_attr->extend != CAIRO_EXTEND_NONE)
+            return DFXL_NONE;
+        return DFXL_TEXTRIANGLES;
+    }
+        
+    if (m->xx != 1 || m->yy != 1) {
+        if (src_attr->extend != CAIRO_EXTEND_NONE)
+            return DFXL_NONE;
+        return DFXL_STRETCHBLIT;
+    }
+     
+    if (src_attr->extend != CAIRO_EXTEND_NONE &&
+        src_attr->extend != CAIRO_EXTEND_REPEAT)
+        return DFXL_NONE;
+           
+    return DFXL_BLIT;
+}
+
 static cairo_int_status_t
 _cairo_directfb_surface_composite (cairo_operator_t  op,
                                    cairo_pattern_t  *src_pattern,
                                    cairo_pattern_t  *mask_pattern,
                                    void             *abstract_dst,
                                    int  src_x,  int  src_y,
                                    int  mask_x, int  mask_y,
                                    int  dst_x,  int  dst_y,
                                    unsigned int      width,
                                    unsigned int      height)
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
-    cairo_directfb_surface_t   *src = NULL; /* hide compiler warning */
+    cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
-    cairo_matrix_t             *m;
-    cairo_status_t              ret;
+    DFBAccelerationMask         accel, mask;
+    cairo_int_status_t          ret;
     
     D_DEBUG_AT (Cairo_DirectFB,
                 "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
                    " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
                    " dst_y=%d, width=%u, height=%u ).\n",
                 __FUNCTION__, op, src_pattern, mask_pattern, dst, 
                 src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
     
     ret = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
                                        &src_x, &src_y, &mask_x, &mask_y, 
                                        width, height, &src, &src_attr);
     if (ret)
         return ret;
+        
+    accel = _directfb_categorize_operation (&src_attr);
     
-    ret = CAIRO_INT_STATUS_UNSUPPORTED;
+    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &mask);
+    if (!(mask & accel)) {
+        D_DEBUG_AT (Cairo_DirectFB, "No acceleration (%08x)!\n", accel);
+        if (accel != DFXL_BLIT) {
+            _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
+            return CAIRO_INT_STATUS_UNSUPPORTED;
+        }
+    }
+    
+    src_x += src_attr.x_offset;
+    src_y += src_attr.y_offset;
     
-    m = &src_attr.matrix;
-    if (_cairo_matrix_is_integer_translation (m, NULL, NULL)) {
-        DFBRectangle sr;
+    switch (accel) {
+        case DFXL_BLIT: {
+            DFBRectangle sr;
+        
+            sr.x = src_x + _cairo_lround (src_attr.matrix.x0);
+            sr.y = src_y + _cairo_lround (src_attr.matrix.y0);
+            sr.w = width;
+            sr.h = height;
+        
+            if (src_attr.extend == CAIRO_EXTEND_NONE) {
+                D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n");
+        
+                RUN_CLIPPED( dst, NULL,
+                             dst->dfbsurface->Blit (dst->dfbsurface,
+                                            src->dfbsurface, &sr, dst_x, dst_y));
+            }
+            else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
+                DFBRegion clip;
+            
+                clip.x1 = dst_x;
+                clip.y1 = dst_y;
+                clip.x2 = dst_x + width  - 1;
+                clip.y2 = dst_y + height - 1;
+            
+                D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n");
+            
+                RUN_CLIPPED( dst, &clip,
+                             dst->dfbsurface->TileBlit (dst->dfbsurface, 
+                                            src->dfbsurface, &sr, dst_x, dst_y));
+            }
+        }   break;
         
-        sr.x = src_x + src_attr.x_offset;
-        sr.y = src_y + src_attr.y_offset;
-        sr.w = src->width  - sr.x;
-        sr.h = src->height - sr.y;
-        
-        if (src_attr.extend == CAIRO_EXTEND_NONE) {
-            D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n");
+        case DFXL_STRETCHBLIT: {
+            DFBRectangle sr, dr;
+            double       x1, y1, x2, y2;
+            
+            TRANSFORM_POINT2X (src_attr.matrix, 
+                               src_x, src_y, x1, y1);
+            TRANSFORM_POINT2X (src_attr.matrix, 
+                               src_x+width, src_y+height, x2, y2);
+                               
+            sr.x = _cairo_lround (x1);
+            sr.y = _cairo_lround (y1);
+            sr.w = _cairo_lround (x2-x1);
+            sr.h = _cairo_lround (y2-y1);
+            
+            dr.x = dst_x;
+            dr.y = dst_y;
+            dr.w = width;
+            dr.h = height;
+            
+            D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
+
+            RUN_CLIPPED (dst, NULL,
+                         dst->dfbsurface->StretchBlit (dst->dfbsurface, 
+                                                       src->dfbsurface, &sr, &dr));
+        }   break;
         
-            RUN_CLIPPED( dst, NULL,
-                         dst->dfbsurface->Blit (dst->dfbsurface,
-                                            src->dfbsurface, &sr, dst_x, dst_y));
-            ret = CAIRO_STATUS_SUCCESS;
-        }
-        else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
+        case DFXL_TEXTRIANGLES: {
             DFBRegion clip;
+            DFBVertex v[4];
+            float     x1, y1, x2, y2;
+            int       w, h;
+            
+            if (cairo_matrix_invert (&src_attr.matrix) != CAIRO_STATUS_SUCCESS) {
+                ret = CAIRO_INT_STATUS_UNSUPPORTED;
+                break;
+            }
+            
+            x1 = src_attr.x_offset;
+            y1 = src_attr.y_offset;
+            x2 = src->width  - x1;
+            y2 = src->height - y1;
+            
+            src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
+            
+            TRANSFORM_POINT3X (src_attr.matrix, 
+                               x1, y1, v[0].x, v[0].y);
+            v[0].z = 0;
+            v[0].w = 1;
+            v[0].s = x1 / w;
+            v[0].t = y1 / h;
+        
+            TRANSFORM_POINT3X (src_attr.matrix, 
+                               x2, y1, v[1].x, v[1].y);
+            v[1].z = 0;
+            v[1].w = 1;
+            v[1].s = x2 / w;
+            v[1].t = y1 / h;
+        
+            TRANSFORM_POINT3X (src_attr.matrix,
+                               x2, y2, v[2].x, v[2].y);
+            v[2].z = 0;
+            v[2].w = 1;
+            v[2].s = x2 / w;
+            v[2].t = y2 / h;
+        
+            TRANSFORM_POINT3X (src_attr.matrix, 
+                               x1, y2, v[3].x, v[3].y);
+            v[3].z = 0;
+            v[3].w = 1;
+            v[3].s = x1 / w;
+            v[3].t = y2 / h;
             
             clip.x1 = dst_x;
             clip.y1 = dst_y;
             clip.x2 = dst_x + width  - 1;
             clip.y2 = dst_y + height - 1;
-            
-            D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n");
-            
-            RUN_CLIPPED( dst, &clip,
-                         dst->dfbsurface->TileBlit (dst->dfbsurface, 
-                                                src->dfbsurface, &sr, dst_x, dst_y));
-            ret = CAIRO_STATUS_SUCCESS;
-        }
-    }
-    else if (src_attr.extend == CAIRO_EXTEND_NONE &&
-             cairo_matrix_invert (m) == CAIRO_STATUS_SUCCESS)
-    {
-        DFBAccelerationMask accel;
-        
-        /* Yet I don't fully understand what these src_x/src_y mean.
-         * It seems they are X11 specific, so I ignore them for now.
-         */
-        src_x = src_y = 0;
-        
-        dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel);
-        
-        if (m->xy != 0.0 || m->yx != 0.0) {
-            if (accel & DFXL_TEXTRIANGLES) {
-                DFBVertex v[4];
-                float     w, h;
-                float     x1, y1, x2, y2;
-                int       i;
-            
-                w = MAX (src->width,  8);
-                h = MAX (src->height, 8);
-            
-                x1 = src_x + src_attr.x_offset;
-                y1 = src_y + src_attr.y_offset;
-                x2 = src->width  - x1;
-                y2 = src->height - y1;
-        
-                v[0].x = x1;
-                v[0].y = y1;
-                v[0].s = x1/w;
-                v[0].t = y1/h;
-        
-                v[1].x = x2;
-                v[1].y = y1;
-                v[1].s = x2/w;
-                v[1].t = y1/h;
         
-                v[2].x = x2;
-                v[2].y = y2;
-                v[2].s = x2/w;
-                v[2].t = y2/h;
-        
-                v[3].x = x1;
-                v[3].y = y2;
-                v[3].s = x1/w;
-                v[3].t = y2/h;
-        
-                for (i = 0; i < 4; i++) {
-                    TRANSFORM_POINT (m, v[i].x, v[i].y, v[i].x, v[i].y);
-                    v[i].z  = 0;
-                    v[i].w  = 1;
-                }
-        
-                D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
+            D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
             
-                RUN_CLIPPED (dst, NULL,
-                             dst->dfbsurface->TextureTriangles (dst->dfbsurface, 
+            RUN_CLIPPED (dst, &clip,
+                         dst->dfbsurface->TextureTriangles (dst->dfbsurface, 
                                             src->dfbsurface, v, NULL, 4, DTTF_FAN));
-                ret = CAIRO_STATUS_SUCCESS;
-            }
-        }
-        else {
-            if (accel & DFXL_STRETCHBLIT ||
-                src_attr.filter == CAIRO_FILTER_NEAREST)
-            {
-                DFBRectangle sr, dr;
-                double       x1, y1, x2, y2;
-            
-                sr.x = src_x + src_attr.x_offset;
-                sr.y = src_y + src_attr.y_offset;
-                sr.w = src->width  - sr.x;
-                sr.h = src->height - sr.y;
-            
-                TRANSFORM_POINT (m, sr.x, sr.y, x1, y1);
-                TRANSFORM_POINT (m, sr.x+sr.w, sr.y+sr.h, x2, y2);
-                
-                dr.x = _cairo_lround (x1);
-                dr.y = _cairo_lround (y1);
-                dr.w = _cairo_lround (x2-x1);
-                dr.h = _cairo_lround (y2-y1);
+        }   break;
         
-                D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
+        default:
+            D_BUG ("Unexpected operation");
+            break;
+    }
 
-                RUN_CLIPPED (dst, NULL,
-                             dst->dfbsurface->StretchBlit (dst->dfbsurface, 
-                                                       src->dfbsurface, &sr, &dr));
-                ret = CAIRO_STATUS_SUCCESS;
-            }
-        }
-    }  
-   
     _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
     
     return ret;
 }
 #endif /* DFB_COMPOSITE */
 
 #if DFB_RECTANGLES
 static cairo_int_status_t
-_cairo_directfb_surface_fill_rectangles (void                *abstract_surface,
-                                         cairo_operator_t     op,
-                                         const cairo_color_t *color,
-                                         cairo_rectangle_int_t   *rects,
-                                         int                  n_rects)
+_cairo_directfb_surface_fill_rectangles (void                  *abstract_surface,
+                                         cairo_operator_t       op,
+                                         const cairo_color_t   *color,
+                                         cairo_rectangle_int_t *rects,
+                                         int                    n_rects)
 {
-    cairo_directfb_surface_t *dst = abstract_surface;
+    cairo_directfb_surface_t *dst   = abstract_surface;
     DFBSurfaceDrawingFlags    flags;
     DFBSurfaceBlendFunction   sblend;
     DFBSurfaceBlendFunction   dblend;
     DFBRectangle              r[n_rects];
     int                       i;
     
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
                 __FUNCTION__, dst, op, color, rects, n_rects);
 
-    if (_directfb_get_operator (op, &flags, NULL, &sblend, &dblend))
+    if (_directfb_get_operator (op, &sblend, &dblend))
         return CAIRO_INT_STATUS_UNSUPPORTED;
+        
+    if (color->alpha_short >= 0xff00) {
+        if (sblend == DSBF_SRCALPHA)
+            sblend = DSBF_ONE;
+        else if (sblend == DSBF_INVSRCALPHA)
+            sblend = DSBF_ZERO;
+            
+        if (dblend == DSBF_SRCALPHA)
+            dblend = DSBF_ONE;
+        else if (dblend == DSBF_INVSRCALPHA)
+            dblend = DSBF_ZERO;
+    }
+    if (dst->content == CAIRO_CONTENT_COLOR) {
+        if (sblend == DSBF_DESTALPHA)
+            sblend = DSBF_ONE;
+        else if (sblend == DSBF_INVDESTALPHA)
+            sblend = DSBF_ZERO;
+         
+        if (dblend == DSBF_DESTALPHA)
+            dblend = DSBF_ONE;
+        else if (dblend == DSBF_INVDESTALPHA)
+            dblend = DSBF_ZERO;   
+    }
     
+    flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND;
     dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags);
     if (flags & DSDRAW_BLEND) {
         dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
         dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
     }    
     
-    dst->dfbsurface->SetColor (dst->dfbsurface, color->red_short   >> 8,
-                                        color->green_short >> 8, 
-                                        color->blue_short  >> 8, 
-                                        color->alpha_short >> 8 );
+    dst->dfbsurface->SetColor (dst->dfbsurface, 
+                               color->red_short   >> 8,
+                               color->green_short >> 8, 
+                               color->blue_short  >> 8, 
+                               color->alpha_short >> 8 );
        
     for (i = 0; i < n_rects; i++) {
         r[i].x = rects[i].x;
         r[i].y = rects[i].y;
         r[i].w = rects[i].width;
         r[i].h = rects[i].height;
     }
      
@@ -1103,32 +1257,33 @@ static cairo_int_status_t
     cairo_directfb_surface_t *surface = abstract_surface;
     
     D_DEBUG_AT (Cairo_DirectFB, 
                 "%s( surface=%p, region=%p ).\n",
                 __FUNCTION__, surface, region);
     
     if (region) {
         cairo_box_int_t *boxes;
-        int n_boxes, i;
-	cairo_status_t status;
+        int              n_boxes;
+        cairo_status_t   status;
+        int              i;
 
         status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
-	if (status)
-	    return status;
-
+        if (status)
+            return status;
+        
         if (surface->n_clips != n_boxes) {
-            if( surface->clips )
+            if (surface->clips)
                 free (surface->clips);
             
             surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion));
             if (!surface->clips) {
+                surface->n_clips = 0;
                 _cairo_region_boxes_fini (region, boxes);
-                surface->n_clips = 0;
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
             }
         
             surface->n_clips = n_boxes;
         }
         
         for (i = 0; i < n_boxes; i++) {
             surface->clips[i].x1 = boxes[i].p1.x;
             surface->clips[i].y1 = boxes[i].p1.y;
@@ -1145,96 +1300,56 @@ static cairo_int_status_t
             surface->n_clips = 0;
         }
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
-_cairo_directfb_abstract_surface_get_extents (void              *abstract_surface,
+_cairo_directfb_abstract_surface_get_extents (void                  *abstract_surface,
                                               cairo_rectangle_int_t *rectangle)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
     D_DEBUG_AT (Cairo_DirectFB,
                 "%s( surface=%p, rectangle=%p ).\n",
                 __FUNCTION__, surface, rectangle);
     
-    if (rectangle) {           
+    if (rectangle) {
+        if (!surface->local) {
+            surface->dfbsurface->GetSize (surface->dfbsurface,
+                                          &surface->width, &surface->height);
+        }   
         rectangle->x = 0;
         rectangle->y = 0;
-        rectangle->width = surface->width;
+        rectangle->width  = surface->width;
         rectangle->height = surface->height;
     }
     
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
-_cairo_directfb_surface_mark_dirty_rectangle (void *abstract_surface,
-                                              int   x,
-                                              int   y,
-                                              int   width,
-                                              int   height)
-{
-#if 0
-    cairo_directfb_surface_t *surface = abstract_surface;
-    
-    D_DEBUG_AT (Cairo_DirectFB,
-                "%s( surface=%p, x=%d, y=%d, width=%d, height=%d ).\n",
-                __FUNCTION__, surface, x, y, width, height);
-    if( !surface->dirty_region ) 
-            surface->dirty_region = malloc(sizeof(DFBRegion));
-    if (!dirty_region)
-            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-#endif 
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t 
-_cairo_directfb_surface_flush (void *abstract_surface)
-{
-#if 0
-    cairo_directfb_surface_t *surface = abstract_surface;
-    
-    D_DEBUG_AT (Cairo_DirectFB, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
-    
-    if (surface->surface != surface->buffer) {
-        surface->surface->SetClip (surface->surface, NULL);
-        surface->surface->SetBlittingFlags (surface->surface, DSBLIT_NOFX);
-        surface->surface->Blit (surface->surface, surface->buffer, NULL, 0, 0);
-    }
-#endif    
-    return CAIRO_STATUS_SUCCESS;
-}
-
 #if DFB_SHOW_GLYPHS
 static cairo_directfb_font_cache_t*
 _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height)
 {
     cairo_directfb_font_cache_t *cache;
 
     cache = calloc (1, sizeof(cairo_directfb_font_cache_t));
-    if (!cache) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
+    if (!cache)
+        return NULL;
 
-    cache->dfbsurface = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height);
+    cache->dfb = dfb;
+    cache->dfbsurface = _directfb_buffer_surface_create (dfb, 
+                            _directfb_argb_font ? DSPF_ARGB : DSPF_A8, width, height);
     if (!cache->dfbsurface) {
         free (cache);
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         return NULL;
     }
-
-    /* dfb->AddRef (dfb); */
-    cache->dfb = dfb;
-
     cache->width  = width;
     cache->height = height;
 
     return cache;
 }
 
 static void
 _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
@@ -1279,16 +1394,17 @@ static cairo_status_t
                                           &scaled_glyph);
         if (ret)
             return ret;
         
         img = scaled_glyph->surface;
         switch (img->format) {
             case CAIRO_FORMAT_A1:
             case CAIRO_FORMAT_A8:
+            case CAIRO_FORMAT_ARGB32:
                 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);
@@ -1301,32 +1417,32 @@ static cairo_status_t
             continue;
         
         if (!scaled_glyph->surface_private) {
             DFBRectangle *rect;
             
             if (x+img->width > 2048) {
                 x = 0;
                 y = h;
-                h = 8;
+                h = 0;
             }
         
             rects[n].x = x;
             rects[n].y = y;
             rects[n].w = img->width;
             rects[n].h = img->height;
  
             x += img->width;
             h  = MAX (h, img->height);
             w  = MAX (w, x);
             
             /* Remember glyph location */ 
             rect = malloc (sizeof(DFBRectangle));
             if (!rect)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
             *rect = rects[n];
             
             scaled_glyph->surface_private = rect;
             chars[num_chars++] = scaled_glyph;
             
             /*D_DEBUG_AT (Cairo_DirectFB, 
                         "Glyph %lu will be loaded at (%d,%d).\n",
                         glyphs[i].index, rects[n].x, rects[n].y);*/
@@ -1341,76 +1457,108 @@ static cairo_status_t
             
         n++;
     }
     
     if (!n)
         return CAIRO_INT_STATUS_NOTHING_TO_DO;
     
     h += y;
+    w = MAX (w, 8);
+    h = MAX (h, 8);
      
     if (cache) {
         if (cache->width < w || cache->height < h) {
             cairo_directfb_font_cache_t *new_cache;
             
             w = MAX (w, cache->width);
             h = MAX (h, cache->height);
             
             D_DEBUG_AT (Cairo_DirectFB,
                         "Reallocating font cache (%dx%d).\n", w, h);
             
             new_cache = _directfb_allocate_font_cache (surface->dfb, w, h);
             if (!new_cache)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
             
             new_cache->dfbsurface->Blit (new_cache->dfbsurface,
-                                     cache->dfbsurface, NULL, 0, 0);
+                                         cache->dfbsurface, NULL, 0, 0);
             
             _directfb_destroy_font_cache (cache);
             scaled_font->surface_private = cache = new_cache;
         }
     }
     else {
         D_DEBUG_AT (Cairo_DirectFB,
                     "Allocating font cache (%dx%d).\n", w, h);
         
         cache = _directfb_allocate_font_cache (surface->dfb, w, h);
-	if (!cache)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+        if (!cache)
+            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
             
         scaled_font->surface_backend = &cairo_directfb_surface_backend;
         scaled_font->surface_private = cache;
     }
     
     if (num_chars) {
         unsigned char *data;
         int            pitch;
     
         if (cache->dfbsurface->Lock (cache->dfbsurface, 
-                                 DSLF_WRITE, (void *)&data, &pitch))
+                                     DSLF_WRITE, (void *)&data, &pitch))
             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    
+            
         for (i = 0; i < num_chars; i++) {
             cairo_image_surface_t *img  = chars[i]->surface;
             DFBRectangle          *rect = chars[i]->surface_private;
-            unsigned char         *dst  = data + rect->y*pitch + rect->x;
+            unsigned char         *dst  = data;
             unsigned char         *src  = img->data;
+            int                    j;
             
+            dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x);
+                        
             if (img->format == CAIRO_FORMAT_A1) {
-                int j;
                 for (h = rect->h; h; h--) {
-                    for (j = 0; j < rect->w; j++)
-                        dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
+                    if (_directfb_argb_font) {
+                        for (j = 0; j < rect->w; j++)
+                            ((uint32_t *)dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0;
+                    }
+                    else {
+                        for (j = 0; j < rect->w; j++)
+                            dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0;
+                    }
+                    
                     dst += pitch;
                     src += img->stride;
                 }
             }
-            else {
+            else if (img->format == CAIRO_FORMAT_A8) {
                 for (h = rect->h; h; h--) {
-                    direct_memcpy (dst, src, rect->w);
+                    if (_directfb_argb_font) {
+                        for (j = 0; j < rect->w; j++)
+                            ((uint32_t *)dst)[j] = src[j] * 0x01010101;
+                    }
+                    else {
+                        direct_memcpy (dst, src, rect->w);
+                    }
+                    
+                    dst += pitch;
+                    src += img->stride;
+                }
+            }
+            else { /* ARGB32 */
+                for (h = rect->h; h; h--) {
+                    if (_directfb_argb_font) {
+                        direct_memcpy (dst, src, rect->w<<2);
+                    }
+                    else {
+                        for (j = 0; j < rect->w; j++)
+                            dst[j] = ((uint32_t *)src)[j] >> 24;
+                    }
+                    
                     dst += pitch;
                     src += img->stride;
                 }
             }
         }
         
         cache->dfbsurface->Unlock (cache->dfbsurface);
     }
@@ -1447,25 +1595,23 @@ static void
                  __FUNCTION__, scaled_glyph, scaled_font);
 
      if (scaled_glyph->surface_private) {
           free (scaled_glyph->surface_private);
           scaled_glyph->surface_private = NULL;
      }
 }
 
-
-
 static cairo_int_status_t
-_cairo_directfb_surface_show_glyphs ( void                 *abstract_dst,
-                                     cairo_operator_t      op,
-                                     cairo_pattern_t      *pattern,
-                                     cairo_glyph_t	  *glyphs,
-                                     int                   num_glyphs,
-                                     cairo_scaled_font_t  *scaled_font)
+_cairo_directfb_surface_show_glyphs (void                *abstract_dst,
+                                     cairo_operator_t     op,
+                                     cairo_pattern_t     *pattern,
+                                     cairo_glyph_t       *glyphs,
+                                     int                  num_glyphs,
+                                     cairo_scaled_font_t *scaled_font)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
     cairo_status_t               ret;
     DFBSurfaceBlittingFlags      flags;
     DFBSurfaceBlendFunction      sblend;
     DFBSurfaceBlendFunction      dblend;
     DFBColor                     color;
@@ -1475,41 +1621,43 @@ static cairo_int_status_t
     
     D_DEBUG_AT (Cairo_DirectFB,
                 "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
                 __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font);
                             
     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
         return CAIRO_INT_STATUS_UNSUPPORTED;
         
-    if (_directfb_get_operator (op, NULL, &flags, &sblend, &dblend) ||
+    if (_directfb_get_operator (op, &sblend, &dblend) ||
         sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) 
         return CAIRO_INT_STATUS_UNSUPPORTED;
         
     ret = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
                                         &cache, &rects[0], &points[0], &num);
     if (ret) {
         if (ret == CAIRO_INT_STATUS_NOTHING_TO_DO)
             ret = CAIRO_STATUS_SUCCESS;
         return ret;
     }
         
     color.a = ((cairo_solid_pattern_t *)pattern)->color.alpha_short >> 8;
-    color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short >> 8;
+    color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short   >> 8;
     color.g = ((cairo_solid_pattern_t *)pattern)->color.green_short >> 8;
-    color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short >> 8;
+    color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short  >> 8;
     
-    flags |= DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
+    flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
     if (color.a != 0xff)
         flags |= DSBLIT_BLEND_COLORALPHA;
         
-    if (sblend == DSBF_ONE) {
-        sblend = DSBF_SRCALPHA;
-        if (dblend == DSBF_ZERO)
-            dblend = DSBF_INVSRCALPHA;
+    if (!_directfb_argb_font) {
+        if (sblend == DSBF_ONE) {
+            sblend = DSBF_SRCALPHA;
+            if (dblend == DSBF_ZERO)
+                dblend = DSBF_INVSRCALPHA;
+        }
     } 
         
     dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
     dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
     dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
     dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a);
     
     D_DEBUG_AT (Cairo_DirectFB, "Running BatchBlit().\n");
@@ -1519,19 +1667,17 @@ static cairo_int_status_t
                                          cache->dfbsurface, rects, points, num));
         
     return CAIRO_STATUS_SUCCESS;
 }
 #endif /* DFB_SHOW_GLYPHS */
 
 
 static cairo_bool_t
-_cairo_directfb_surface_is_similar (void *surface_a,
-	                           void *surface_b,
-				   cairo_content_t content)
+_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
 {
     cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
     cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
 
     return a->dfb == b->dfb;
 }
 
 static cairo_surface_backend_t cairo_directfb_surface_backend = {
@@ -1555,100 +1701,116 @@ static cairo_surface_backend_t cairo_dir
 #endif
 #if DFB_COMPOSITE_TRAPEZOIDS
         _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
 #else
         NULL,/*composite_trapezoids*/
 #endif
         NULL, /* copy_page */
         NULL, /* show_page */
-        _cairo_directfb_surface_set_clip_region,/*set_clip_region*/
+        _cairo_directfb_surface_set_clip_region,/* set_clip_region */
         NULL, /* intersect_clip_path */
-        _cairo_directfb_abstract_surface_get_extents,/*get_extents*/
+        _cairo_directfb_abstract_surface_get_extents,/* get_extents */
         NULL, /* old_show_glyphs */
         NULL, /* get_font_options */
-        _cairo_directfb_surface_flush,/*flush*/
-        _cairo_directfb_surface_mark_dirty_rectangle,/*mark_dirty_rectangle*/
+        NULL, /* flush */
+        NULL, /* mark_dirty_rectangle */
 #if DFB_SHOW_GLYPHS
-        _cairo_directfb_surface_scaled_font_fini,/*scaled_font_fini*/
-        _cairo_directfb_surface_scaled_glyph_fini,/*scaled_glyph_fini*/
+        _cairo_directfb_surface_scaled_font_fini,/* scaled_font_fini */
+        _cairo_directfb_surface_scaled_glyph_fini,/* scaled_glyph_fini */
 #else
         NULL,
         NULL,
 #endif
         NULL, /* paint */
         NULL, /* mask */
         NULL, /* stroke */
         NULL, /* fill */
 #if DFB_SHOW_GLYPHS
-        _cairo_directfb_surface_show_glyphs,/*show_glyphs*/
+        _cairo_directfb_surface_show_glyphs,/* show_glyphs */
 #else
         NULL, /* show_glyphs */
 #endif
         NULL, /* snapshot */
-	_cairo_directfb_surface_is_similar,
-	NULL /* reset */
+        _cairo_directfb_surface_is_similar,
+        NULL /* reset */
 };
 
 
 static void
 cairo_directfb_surface_backend_init (IDirectFB *dfb)
 {
-    DFBGraphicsDeviceDescription dsc;
-    static int                   done = 0;
+    static int done = 0;
     
     if (done)
         return;
         
-    dfb->GetDeviceDescription (dfb, &dsc);
+    if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
+#if DFB_RECTANGLES
+        cairo_directfb_surface_backend.fill_rectangles = NULL;
+#endif
+#if DFB_COMPOSITE
+        cairo_directfb_surface_backend.composite = NULL;
+#endif
+#if DFB_COMPOSITE_TRAPEZOIDS
+        cairo_directfb_surface_backend.composite_trapezoids = NULL;
+#endif
+#if DFB_SHOW_GLYPHS
+        cairo_directfb_surface_backend.scaled_font_fini = NULL;
+        cairo_directfb_surface_backend.scaled_glyph_fini = NULL;
+        cairo_directfb_surface_backend.show_glyphs = NULL;
+#endif
+        D_DEBUG_AT (Cairo_DirectFB, "Acceleration disabled.\n");
+    }
+    else {
+        DFBGraphicsDeviceDescription dsc;
+        
+        dfb->GetDeviceDescription (dfb, &dsc);
     
 #if DFB_COMPOSITE
-    if (!(dsc.acceleration_mask & DFXL_BLIT))
-        cairo_directfb_surface_backend.composite = NULL;
+        if (!(dsc.acceleration_mask & DFXL_BLIT))
+            cairo_directfb_surface_backend.composite = NULL;
 #endif
 
 #if DFB_COMPOSITE_TRAPEZOIDS
-    if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
-        cairo_directfb_surface_backend.composite_trapezoids = NULL;
+        if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
+            cairo_directfb_surface_backend.composite_trapezoids = NULL;
 #endif
-
-#if DFB_SHOW_GLYPHS
-    if (!(dsc.acceleration_mask & DFXL_BLIT)            ||
-        !(dsc.blitting_flags & DSBLIT_COLORIZE)         ||
-        !(dsc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL))
-    {
-        cairo_directfb_surface_backend.scaled_font_fini = NULL;
-        cairo_directfb_surface_backend.scaled_glyph_fini = NULL;
-        cairo_directfb_surface_backend.show_glyphs = NULL;
     }
-#endif
+    
+    if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
+        _directfb_argb_font = 1;
+        D_DEBUG_AT (Cairo_DirectFB, "Using ARGB fonts.\n");
+    }
 
     done = 1;
 }   
 
 
 cairo_surface_t *
 cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) 
 {
-   DFBSurfacePixelFormat format;
     cairo_directfb_surface_t *surface;
+    DFBSurfacePixelFormat     format;
    
-    assert(dfb);
-    assert(dfb);
+    D_ASSERT (dfb != NULL);
+    D_ASSERT (dfbsurface != NULL);
+
     cairo_directfb_surface_backend_init (dfb);
         
     surface = calloc (1, sizeof(cairo_directfb_surface_t));
-    if (!surface) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
-        
+    if (!surface)
+        return NULL;
+     
+    dfbsurface->AddRef (dfbsurface);   
     dfbsurface->GetPixelFormat (dfbsurface, &format);
-    _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,
-                _directfb_format_to_content(format));
-    surface->owner = FALSE;
+    dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height);
     surface->dfb = dfb;
-    surface->dfbsurface = dfbsurface;
-    dfbsurface->GetSize (dfbsurface,&surface->width, &surface->height);   
-    surface->format = directfb_to_cairo_format(format);
+    surface->dfbsurface = dfbsurface;  
+    surface->format = _directfb_to_cairo_format (format);
+    surface->content = _directfb_format_to_content (format);
+
+    _cairo_surface_init (&surface->base, 
+                         &cairo_directfb_surface_backend, surface->content);  
+
     return &surface->base;
 }
 
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -29,29 +29,39 @@
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@isi.edu>
  */
 
+/*
+ * Environment variables affecting the backend:
+ *
+ *  CAIRO_DIRECTFB_NO_ACCEL (boolean)
+ *      if found, disables acceleration at all
+ *
+ *  CAIRO_DIRECTFB_ARGB_FONT (boolean)
+ *      if found, enables using ARGB fonts instead of A8
+ */
+
 #ifndef CAIRO_DIRECTFB_H
 #define CAIRO_DIRECTFB_H
 
 #include <cairo.h>
 
 #ifdef  CAIRO_HAS_DIRECTFB_SURFACE
 
 #include <directfb.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
-cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
+cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface);
 
 CAIRO_END_DECLS
 
 #else  /*CAIRO_HAS_DIRECTFB_SURFACE*/
 # error Cairo was not compiled with support for the directfb backend
 #endif /*CAIRO_HAS_DIRECTFB_SURFACE*/
 
 #endif /*CAIRO_DIRECTFB_H*/
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -48,19 +48,19 @@
 #endif
 
 #ifndef cairo_public
 # define cairo_public
 #endif
 
 #define CAIRO_VERSION_MAJOR 1
 #define CAIRO_VERSION_MINOR 5
-#define CAIRO_VERSION_MICRO 3
+#define CAIRO_VERSION_MICRO 5
 
-#define CAIRO_VERSION_STRING "1.5.3"
+#define CAIRO_VERSION_STRING "1.5.5"
 
 @PS_SURFACE_FEATURE@
 
 @PDF_SURFACE_FEATURE@
 
 @SVG_SURFACE_FEATURE@
 
 @XLIB_SURFACE_FEATURE@
--- a/gfx/cairo/cairo/src/cairo-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-fixed-private.h
@@ -54,17 +54,17 @@ typedef cairo_int128_t	cairo_fixed_96_32
  * size of a fixed type.  For now, it must be 32.
  */
 #define CAIRO_FIXED_BITS	32
 
 /* The number of fractional bits.  Changing this involves
  * making sure that you compute a double-to-fixed magic number.
  * (see below).
  */
-#define CAIRO_FIXED_FRAC_BITS	8
+#define CAIRO_FIXED_FRAC_BITS	16
 
 /* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */
 typedef int32_t cairo_fixed_t;
 
 /* An unsigned type of the same size as cairo_fixed_t */
 typedef uint32_t cairo_fixed_unsigned_t;
 
 /*
--- a/gfx/cairo/cairo/src/cairo-freelist-private.h
+++ b/gfx/cairo/cairo/src/cairo-freelist-private.h
@@ -17,18 +17,17 @@
  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  */
 #ifndef CAIRO_FREELIST_H
 #define CAIRO_FREELIST_H
 
-#include "cairoint.h"
-#include <stddef.h>
+#include "cairo-types-private.h"
 
 /* Opaque implementation types. */
 typedef struct _cairo_freelist cairo_freelist_t;
 typedef struct _cairo_freelist_node cairo_freelist_node_t;
 
 struct _cairo_freelist_node {
     cairo_freelist_node_t *next;
 };
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -59,20 +59,16 @@
 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
 
 /* This is the max number of FT_face objects we keep open at once
  */
 #define MAX_OPEN_FACES 10
 
-/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
- */
-#define MAX_FONT_SIZE 1000
-
 /*
  * The simple 2x2 matrix is converted into separate scale and shape
  * factors so that hinting works right
  */
 
 typedef struct _cairo_ft_font_transform {
     double  x_scale, y_scale;
     double  shape[2][2];
@@ -665,28 +661,19 @@ static cairo_status_t
     cairo_matrix_init (&unscaled->current_shape,
 		       sf.shape[0][0], sf.shape[0][1],
 		       sf.shape[1][0], sf.shape[1][1],
 		       0.0, 0.0);
 
     FT_Set_Transform(unscaled->face, &mat, NULL);
 
     if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
-        double x_scale = sf.x_scale;
-        double y_scale = sf.y_scale;
-        if (x_scale > MAX_FONT_SIZE) {
-            x_scale = MAX_FONT_SIZE;
-        }
-        if (y_scale > MAX_FONT_SIZE) {
-            y_scale = MAX_FONT_SIZE;
-        }
-
 	error = FT_Set_Char_Size (unscaled->face,
-				  x_scale * 64.0,
-				  y_scale * 64.0,
+				  sf.x_scale * 64.0,
+				  sf.y_scale * 64.0,
 				  0, 0);
 	if (error)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     } else {
 	double min_distance = DBL_MAX;
 	int i;
 	int best_i = 0;
 
@@ -1503,51 +1490,29 @@ static cairo_status_t
     _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
     _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
 
     status = _cairo_scaled_font_init (&scaled_font->base,
 			              font_face,
 				      font_matrix, ctm, options,
 				      &cairo_ft_scaled_font_backend);
     if (status) {
+	_cairo_unscaled_font_destroy (&unscaled->base);
 	free (scaled_font);
 	goto FAIL;
     }
 
     status = _cairo_ft_unscaled_font_set_scale (unscaled,
 				                &scaled_font->base.scale);
     if (status) {
+	_cairo_unscaled_font_destroy (&unscaled->base);
 	free (scaled_font);
 	goto FAIL;
     }
 
-    /*
-     * Force non-AA drawing when using a bitmap strike that
-     * won't be resampled due to non-scaling transform
-     */
-    if (!unscaled->have_shape &&
-	(scaled_font->ft_options.load_flags & FT_LOAD_NO_BITMAP) == 0 &&
-	scaled_font->ft_options.base.antialias != CAIRO_ANTIALIAS_NONE &&
-	(face->face_flags & FT_FACE_FLAG_FIXED_SIZES))
-    {
-	int		i;
-	FT_Size_Metrics	*size_metrics = &face->size->metrics;
-
-	for (i = 0; i < face->num_fixed_sizes; i++)
-	{
-	    FT_Bitmap_Size  *bitmap_size = &face->available_sizes[i];
-
-	    if (bitmap_size->x_ppem == size_metrics->x_ppem * 64 &&
-		bitmap_size->y_ppem == size_metrics->y_ppem * 64)
-	    {
-		scaled_font->ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
-		break;
-	    }
-	}
-    }
 
     metrics = &face->size->metrics;
 
     /*
      * Get to unscaled metrics so that the upper level can get back to
      * user space
      */
     if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
@@ -2165,46 +2130,48 @@ static cairo_int_status_t
         status = CAIRO_STATUS_SUCCESS;
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 #endif
 
     return status;
 }
 
-static void
+static cairo_int_status_t
 _cairo_ft_map_glyphs_to_unicode (void	                    *abstract_font,
                                  cairo_scaled_font_subset_t *font_subset)
 {
     cairo_ft_scaled_font_t *scaled_font = abstract_font;
     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
     FT_Face face;
     FT_UInt glyph;
     unsigned long charcode;
     unsigned int i;
     int count;
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
-	return;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     count = font_subset->num_glyphs;
     charcode = FT_Get_First_Char( face, &glyph);
     while (glyph != 0 && count > 0)
     {
         for (i = 0; i < font_subset->num_glyphs; i++) {
             if (font_subset->glyphs[i] == glyph) {
                 font_subset->to_unicode[i] = charcode;
                 count--;
                 break;
             }
         }
-        charcode = FT_Get_Next_Char(face, charcode, &glyph);
+        charcode = FT_Get_Next_Char (face, charcode, &glyph);
     }
     _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
     NULL,			/* text_to_glyphs */
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -1300,26 +1300,28 @@ static cairo_int_status_t
 				  NULL, 0);
 
 	size *= format.vertex.bytes_per_vertex;
 
 	while (n_traps)
 	{
 	    if (data_size < size)
 	    {
+		void *p;
 		data_size = size;
-		data = realloc (data, data_size);
-		if (!data)
+		p = realloc (data, data_size);
+		if (!p)
 		{
 		    _cairo_glitz_pattern_release_surface (src_pattern, src,
 							  &attributes);
 		    if (src_pattern == &tmp_src_pattern.base)
 			_cairo_pattern_fini (&tmp_src_pattern.base);
 		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 		}
+		data = p;
 
 		if (buffer)
 		    glitz_buffer_destroy (buffer);
 
 		buffer = glitz_buffer_create_for_data (data);
 		if (!buffer) {
 		    free (data);
 		    _cairo_glitz_pattern_release_surface (src_pattern, src,
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -30,21 +30,29 @@
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
+#define _GNU_SOURCE
+
 #include "cairoint.h"
 
 #include "cairo-clip-private.h"
 #include "cairo-gstate-private.h"
 
+#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#define ISFINITE(x) isfinite (x)
+#else
+#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
+#endif
+
 static cairo_status_t
 _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
 
 static cairo_status_t
 _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
 
 static cairo_status_t
 _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
@@ -618,107 +626,124 @@ void
     *matrix = gstate->ctm;
 }
 
 cairo_status_t
 _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
 {
     cairo_matrix_t tmp;
 
-    if (! (tx * tx >= 0.) || ! (ty * ty >= 0.)) /* check for NaNs */
+    if (! ISFINITE (tx) || ! ISFINITE (ty))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     cairo_matrix_init_translate (&tmp, tx, ty);
     cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
 
+    /* paranoid check against gradual numerical instability */
+    if (! _cairo_matrix_is_invertible (&gstate->ctm))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     cairo_matrix_init_translate (&tmp, -tx, -ty);
     cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
 {
     cairo_matrix_t tmp;
 
     if (sx * sy == 0.) /* either sx or sy is 0, or det == 0 due to underflow */
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
-    if (! (sx * sx > 0.) || ! (sy * sy > 0.)) /* check for NaNs */
+    if (! ISFINITE (sx) || ! ISFINITE (sy))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     cairo_matrix_init_scale (&tmp, sx, sy);
     cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
 
+    /* paranoid check against gradual numerical instability */
+    if (! _cairo_matrix_is_invertible (&gstate->ctm))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     cairo_matrix_init_scale (&tmp, 1/sx, 1/sy);
     cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
 {
     cairo_matrix_t tmp;
 
     if (angle == 0.)
 	return CAIRO_STATUS_SUCCESS;
 
-    if (! (angle * angle >= 0.)) /* check for NaNs */
+    if (! ISFINITE (angle))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     cairo_matrix_init_rotate (&tmp, angle);
     cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
 
+    /* paranoid check against gradual numerical instability */
+    if (! _cairo_matrix_is_invertible (&gstate->ctm))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     cairo_matrix_init_rotate (&tmp, -angle);
     cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_transform (cairo_gstate_t	      *gstate,
 			 const cairo_matrix_t *matrix)
 {
     cairo_matrix_t tmp;
     cairo_status_t status;
 
-    _cairo_gstate_unset_scaled_font (gstate);
-
     tmp = *matrix;
-    cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
-
     status = cairo_matrix_invert (&tmp);
     if (status)
 	return status;
+
+    _cairo_gstate_unset_scaled_font (gstate);
+
+    cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
     cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
 
+    /* paranoid check against gradual numerical instability */
+    if (! _cairo_matrix_is_invertible (&gstate->ctm))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_set_matrix (cairo_gstate_t       *gstate,
 			  const cairo_matrix_t *matrix)
 {
     cairo_status_t status;
 
+    if (! _cairo_matrix_is_invertible (matrix))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
     _cairo_gstate_unset_scaled_font (gstate);
 
     gstate->ctm = *matrix;
-
     gstate->ctm_inverse = *matrix;
     status = cairo_matrix_invert (&gstate->ctm_inverse);
-    if (status)
-	return status;
+    assert (status == CAIRO_STATUS_SUCCESS);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
 {
     _cairo_gstate_unset_scaled_font (gstate);
@@ -1127,29 +1152,29 @@ cairo_status_t
 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)
 {
     cairo_box_t extents;
 
-    _cairo_traps_extents (traps, &extents);
-
-    if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
+    if (traps->num_traps == 0) {
         /* no traps, so we actually won't draw anything */
 	if (x1)
 	    *x1 = 0.0;
 	if (y1)
 	    *y1 = 0.0;
 	if (x2)
 	    *x2 = 0.0;
 	if (y2)
 	    *y2 = 0.0;
     } else {
+	_cairo_traps_extents (traps, &extents);
+
 	if (x1)
 	    *x1 = _cairo_fixed_to_double (extents.p1.x);
 	if (y1)
 	    *y1 = _cairo_fixed_to_double (extents.p1.y);
 	if (x2)
 	    *x2 = _cairo_fixed_to_double (extents.p2.x);
 	if (y2)
 	    *y2 = _cairo_fixed_to_double (extents.p2.y);
@@ -1570,39 +1595,38 @@ cairo_status_t
 
     cairo_scaled_font_glyph_extents (gstate->scaled_font,
 				     glyphs, num_glyphs,
 				     extents);
 
     return cairo_scaled_font_status (gstate->scaled_font);
 }
 
-#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
 cairo_status_t
 _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
 			   const cairo_glyph_t *glyphs,
 			   int num_glyphs)
 {
     cairo_status_t status;
     cairo_pattern_union_t source_pattern;
     cairo_glyph_t *transformed_glyphs;
-    cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
+    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
     if (gstate->source->status)
 	return gstate->source->status;
 
     status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
     if (status)
 	return status;
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
     if (status)
 	return status;
 
-    if (num_glyphs <= STACK_GLYPHS_LEN) {
+    if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
 	transformed_glyphs = stack_transformed_glyphs;
     } else {
 	transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
 	if (transformed_glyphs == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
@@ -1631,23 +1655,23 @@ CLEANUP_GLYPHS:
 cairo_status_t
 _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
 			  const cairo_glyph_t *glyphs,
 			  int		       num_glyphs,
 			  cairo_path_fixed_t  *path)
 {
     cairo_status_t status;
     cairo_glyph_t *transformed_glyphs;
-    cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
+    cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
     if (status)
 	return status;
 
-    if (num_glyphs < STACK_GLYPHS_LEN)
+    if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs))
       transformed_glyphs = stack_transformed_glyphs;
     else
       transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
     if (transformed_glyphs == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs);
@@ -1658,17 +1682,16 @@ cairo_status_t
 					    path);
     CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
     if (transformed_glyphs != stack_transformed_glyphs)
       free (transformed_glyphs);
 
     return status;
 }
-#undef STACK_GLYPHS_LEN
 
 cairo_status_t
 _cairo_gstate_set_antialias (cairo_gstate_t *gstate,
 			     cairo_antialias_t antialias)
 {
     gstate->antialias = antialias;
 
     return CAIRO_STATUS_SUCCESS;
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -719,16 +719,34 @@ cairo_content_t
     case CAIRO_FORMAT_A1:
 	return CAIRO_CONTENT_ALPHA;
     }
 
     ASSERT_NOT_REACHED;
     return CAIRO_CONTENT_COLOR_ALPHA;
 }
 
+cairo_private cairo_format_t
+_cairo_format_width (cairo_format_t format)
+{
+    switch (format) {
+    case CAIRO_FORMAT_ARGB32:
+	return 32;
+    case CAIRO_FORMAT_RGB24:
+	return 24;
+    case CAIRO_FORMAT_A8:
+	return 8;
+    case CAIRO_FORMAT_A1:
+	return 1;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
 static cairo_surface_t *
 _cairo_image_surface_create_similar (void	       *abstract_src,
 				     cairo_content_t	content,
 				     int		width,
 				     int		height)
 {
     assert (CAIRO_CONTENT_VALID (content));
 
@@ -1029,29 +1047,27 @@ static cairo_int_status_t
     if (mask)
 	_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
 
     _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
 
     return status;
 }
 
-#define STACK_RECTS_LEN (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_rectangle16_t))
-
 static cairo_int_status_t
 _cairo_image_surface_fill_rectangles (void		      *abstract_surface,
 				      cairo_operator_t	       op,
 				      const cairo_color_t     *color,
 				      cairo_rectangle_int_t   *rects,
 				      int		       num_rects)
 {
     cairo_image_surface_t *surface = abstract_surface;
 
     pixman_color_t pixman_color;
-    pixman_rectangle16_t stack_rects[STACK_RECTS_LEN];
+    pixman_rectangle16_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (pixman_rectangle16_t)];
     pixman_rectangle16_t *pixman_rects = stack_rects;
     int i;
 
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
 
     pixman_color.red   = color->red_short;
     pixman_color.green = color->green_short;
     pixman_color.blue  = color->blue_short;
@@ -1080,20 +1096,16 @@ static cairo_int_status_t
     }
 
     if (pixman_rects != stack_rects)
 	free (pixman_rects);
 
     return status;
 }
 
-#undef STACK_RECTS_LEN
-
-#define STACK_TRAPS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_trapezoid_t)))
-
 static cairo_int_status_t
 _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
 					   cairo_pattern_t	*pattern,
 					   void			*abstract_dst,
 					   cairo_antialias_t	antialias,
 					   int			src_x,
 					   int			src_y,
 					   int			dst_x,
@@ -1105,17 +1117,17 @@ static cairo_int_status_t
 {
     cairo_surface_attributes_t	attributes;
     cairo_image_surface_t	*dst = abstract_dst;
     cairo_image_surface_t	*src;
     cairo_int_status_t		status;
     pixman_image_t		*mask;
     pixman_format_code_t	 format;
     uint32_t			*mask_data;
-    pixman_trapezoid_t		 stack_traps[STACK_TRAPS_LEN];
+    pixman_trapezoid_t		 stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
     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;
 
@@ -1239,18 +1251,16 @@ static cairo_int_status_t
 
  finish:
     if (pixman_traps != stack_traps)
 	free (pixman_traps);
 
     return status;
 }
 
-#undef STACK_TRAPS_LEN
-
 cairo_int_status_t
 _cairo_image_surface_set_clip_region (void *abstract_surface,
 				      cairo_region_t *region)
 {
     cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
 
     if (!pixman_image_set_clip_region (surface->pixman_image, &region->rgn))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
--- a/gfx/cairo/cairo/src/cairo-matrix.c
+++ b/gfx/cairo/cairo/src/cairo-matrix.c
@@ -33,16 +33,22 @@
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #define _GNU_SOURCE
 
 #include "cairoint.h"
 
+#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
+#define ISFINITE(x) isfinite (x)
+#else
+#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
+#endif
+
 static void
 _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
 
 static void
 _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix);
 
 /**
  * cairo_matrix_init_identity:
@@ -470,35 +476,34 @@ cairo_matrix_invert (cairo_matrix_t *mat
     /* inv (A) = 1/det (A) * adj (A) */
     double det;
 
     _cairo_matrix_compute_determinant (matrix, &det);
 
     if (det == 0)
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
-    /* this weird construct is for detecting NaNs */
-    if (! (det * det > 0.))
+    if (! ISFINITE (det))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_matrix_compute_adjoint (matrix);
     _cairo_matrix_scalar_multiply (matrix, 1 / det);
 
     return CAIRO_STATUS_SUCCESS;
 }
 slim_hidden_def(cairo_matrix_invert);
 
 cairo_bool_t
 _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
 {
     double det;
 
     _cairo_matrix_compute_determinant (matrix, &det);
 
-    return det != 0. && det * det > 0.;
+    return det != 0. && ISFINITE (det);
 }
 
 void
 _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
 				   double		*det)
 {
     double a, b, c, d;
 
@@ -512,16 +517,18 @@ void
 void
 _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
 				     double *sx, double *sy, int x_major)
 {
     double det;
 
     _cairo_matrix_compute_determinant (matrix, &det);
 
+    assert (ISFINITE (det));
+
     if (det == 0)
     {
 	*sx = *sy = 0;
     }
     else
     {
 	double x = x_major != 0;
 	double y = x == 0;
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c
+++ b/gfx/cairo/cairo/src/cairo-meta-surface.c
@@ -56,18 +56,17 @@
  */
 
 #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_CREATE_REGIONS
 } 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.
  *
@@ -471,17 +470,17 @@ static cairo_int_status_t
 
   CLEANUP_SCALED_FONT:
     cairo_scaled_font_destroy (command->scaled_font);
     free (command->glyphs);
   CLEANUP_SOURCE:
     _cairo_pattern_fini (&command->source.base);
   CLEANUP_COMMAND:
     free (command);
-    return _cairo_error (status);
+    return status;
 }
 
 /**
  * _cairo_meta_surface_snapshot
  * @surface: a #cairo_surface_t which must be a meta surface
  *
  * Make an immutable copy of @surface. It is an error to call a
  * surface-modifying function on the result of this function.
@@ -848,21 +847,16 @@ static cairo_status_t
 	    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 _cairo_surface_set_error (surface, status);
 }
@@ -872,26 +866,16 @@ cairo_status_t
 			    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,
--- a/gfx/cairo/cairo/src/cairo-os2-surface.c
+++ b/gfx/cairo/cairo/src/cairo-os2-surface.c
@@ -130,16 +130,84 @@ cairo_os2_fini (void)
      * so there are still memory chunks allocated at this point.
      * In these cases, Watcom might still have a bigger memory chunk,
      * called "the heap" allocated from the OS.
      * As we want to minimize the memory we lose from the point of
      * view of the OS, we call this function to shrink that heap
      * as much as possible.
      */
     _heapshrink ();
+#else
+    /* GCC has a heapmin function that approximately corresponds to
+     * what the Watcom function does
+     */
+    _heapmin ();
+#endif
+}
+
+/*
+ * This function calls the allocation function depending on which
+ * method was compiled into the library: it can be native allocation
+ * (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free).
+ * Actually, for pixel buffers that we use this function for, cairo
+ * uses _cairo_malloc_abc, so we use that here, too. And use the
+ * change to check the size argument
+ */
+void *_buffer_alloc (size_t a, size_t b, const unsigned int size)
+{
+    /* check length like in the _cairo_malloc_abc macro, but we can leave
+     * away the unsigned casts as our arguments are unsigned already
+     */
+    size_t nbytes = b &&
+                    a >= INT32_MAX / b ? 0 : size &&
+                    a*b >= INT32_MAX / size ? 0 : a * b * size;
+    void *buffer = NULL;
+#ifdef OS2_USE_PLATFORM_ALLOC
+    APIRET rc = NO_ERROR;
+
+    rc = DosAllocMem ((PPVOID)&buffer,
+                      nbytes,
+#ifdef OS2_HIGH_MEMORY           /* only if compiled with high-memory support, */
+                      OBJ_ANY |  /* we can allocate anywhere!                  */
+#endif
+                      PAG_READ | PAG_WRITE | PAG_COMMIT);
+    if (rc != NO_ERROR) {
+        /* should there for some reason be another error, let's return
+         * a null surface and free the buffer again, because that's
+         * how a malloc failure would look like
+         */
+        if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) {
+            DosFreeMem (buffer);
+        }
+        return NULL;
+    }
+#else
+    buffer = malloc (nbytes);
+#endif
+
+    /* This does not seem to be needed, malloc'd space is usually
+     * already zero'd out!
+     */
+    /*
+     * memset (buffer, 0x00, nbytes);
+     */
+
+    return buffer;
+}
+
+/*
+ * This function selects the free function depending on which
+ * allocation method was compiled into the library
+ */
+void _buffer_free (void *buffer)
+{
+#ifdef OS2_USE_PLATFORM_ALLOC
+    DosFreeMem (buffer);
+#else
+    free (buffer);
 #endif
 }
 
 #ifdef BUILD_CAIRO_DLL
 /* The main DLL entry for DLL initialization and uninitialization */
 /* Only include this code if we're about to build a DLL.          */
 
 #ifdef __WATCOMC__
@@ -291,19 +359,19 @@ static void
          * - clean up the new buffer
          */
         BITMAPINFOHEADER2 bmpheader;
         unsigned char *pchPixBuf, *pchPixSource;
         void *pBufStart;
         ULONG ulPixels;
 
         /* allocate temporary pixel buffer */
-        pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
-						      surface->bitmap_info.cx,
-						      3);
+        pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy,
+                                                     surface->bitmap_info.cx,
+                                                     3);
         pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
         pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
 
         /* copy the first three bytes for each pixel but skip over the fourth */
         for (ulPixels = 0; ulPixels < surface->bitmap_info.cx * surface->bitmap_info.cy; ulPixels++)
         {
             /* copy BGR from source buffer */
             *pchPixBuf++ = *pchPixSource++;
@@ -325,17 +393,17 @@ static void
         rc = GpiDrawBits (hps_begin_paint,
                           pchPixBuf,
                           (PBITMAPINFO2)&bmpheader,
                           4,
                           aptlPoints,
                           ROP_SRCCOPY,
                           BBO_IGNORE);
 
-        free (pchPixBuf);
+        _buffer_free (pchPixBuf);
     }
 
     /* Restore Y inversion */
     GpiEnableYInversion (hps_begin_paint, lOldYInversion);
 }
 
 static void
 _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
@@ -709,44 +777,37 @@ cairo_os2_surface_create (HPS hps_client
     memset (&(local_os2_surface->bitmap_info), 0, sizeof (local_os2_surface->bitmap_info));
     local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2);
     local_os2_surface->bitmap_info.cx = width;
     local_os2_surface->bitmap_info.cy = height;
     local_os2_surface->bitmap_info.cPlanes = 1;
     local_os2_surface->bitmap_info.cBitCount = 32;
 
     /* Allocate memory for pixels */
-    local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
+    local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4);
     if (!(local_os2_surface->pixels)) {
         /* Not enough memory for the pixels! */
         DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
         DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
         free (local_os2_surface);
         _cairo_error (CAIRO_STATUS_NO_MEMORY);
         return (cairo_surface_t *) &_cairo_surface_nil;
     }
 
-    /* This is possibly not needed, malloc'd space is
-     * usually zero'd out!
-     */
-    /*
-     memset (local_os2_surface->pixels, 0x00, swpTemp.cx * swpTemp.cy * 4);
-     */
-
     /* Create image surface from pixel array */
     local_os2_surface->image_surface = (cairo_image_surface_t *)
         cairo_image_surface_create_for_data (local_os2_surface->pixels,
                                              CAIRO_FORMAT_ARGB32,
                                              width,      /* Width */
                                              height,     /* Height */
                                              width * 4); /* Rowstride */
 
     if (local_os2_surface->image_surface->base.status) {
         /* Could not create image surface! */
-        free (local_os2_surface->pixels);
+        _buffer_free (local_os2_surface->pixels);
         DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
         DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
         free (local_os2_surface);
         _cairo_error (CAIRO_STATUS_NO_MEMORY);
         return (cairo_surface_t *) &_cairo_surface_nil;
     }
 
     /* Initialize base surface */
@@ -779,91 +840,84 @@ cairo_os2_surface_set_size (cairo_surfac
     if ((new_width <= 0) ||
         (new_height <= 0))
     {
         /* Invalid size! */
         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     /* Allocate memory for new stuffs */
-    pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4);
+    pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4);
     if (!pchNewPixels) {
         /* Not enough memory for the pixels!
          * Everything remains the same!
          */
         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    /* This is possibly not needed, malloc'd space is usually
-     * already zero'd out!
-     */
-    /*
-     memset (pchNewPixels, 0x00, new_width * new_height * 4);
-     */
-
     /* Create image surface from new pixel array */
     pNewImageSurface = (cairo_image_surface_t *)
         cairo_image_surface_create_for_data (pchNewPixels,
                                              CAIRO_FORMAT_ARGB32,
                                              new_width,      /* Width */
                                              new_height,     /* Height */
                                              new_width * 4); /* Rowstride */
 
     if (pNewImageSurface->base.status) {
         /* Could not create image surface!
          * Everything remains the same!
          */
-        free (pchNewPixels);
+        _buffer_free (pchNewPixels);
         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     /* Okay, new memory allocated, so it's time to swap old buffers
      * to new ones!
      */
     if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) {
         /* Could not get mutex!
          * Everything remains the same!
          */
         cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
-        free (pchNewPixels);
+        _buffer_free (pchNewPixels);
         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     /* We have to make sure that we won't destroy a surface which
      * is lent to some other code (Cairo is drawing into it)!
      */
     while (local_os2_surface->pixel_array_lend_count > 0) {
         ULONG ulPostCount;
         DosResetEventSem (local_os2_surface->hev_pixel_array_came_back, &ulPostCount);
         DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields);
         /* Wait for somebody to return the pixels! */
         rc = DosWaitEventSem (local_os2_surface->hev_pixel_array_came_back, timeout);
         if (rc != NO_ERROR) {
             /* Either timeout or something wrong... Exit. */
             cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
-            free (pchNewPixels);
+            _buffer_free (pchNewPixels);
             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
         }
         /* Okay, grab mutex and check counter again! */
         if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)
             != NO_ERROR)
         {
             /* Could not get mutex!
              * Everything remains the same!
              */
             cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
-            free (pchNewPixels);
+            _buffer_free (pchNewPixels);
             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
         }
     }
 
     /* Destroy old image surface */
     cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
     /* Destroy old pixel buffer */
-    free (local_os2_surface->pixels);
+    _buffer_free (local_os2_surface->pixels);
     /* Set new image surface */
     local_os2_surface->image_surface = pNewImageSurface;
     /* Set new pixel buffer */
     local_os2_surface->pixels = pchNewPixels;
     /* Change bitmap2 structure */
     local_os2_surface->bitmap_info.cx = new_width;
     local_os2_surface->bitmap_info.cy = new_height;
 
@@ -952,17 +1006,17 @@ static cairo_status_t
         return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
     }
 
     DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT);
 
     /* Destroy old image surface */
     cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
     /* Destroy old pixel buffer */
-    free (local_os2_surface->pixels);
+    _buffer_free (local_os2_surface->pixels);
     DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
     DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
 
     /* The memory itself will be free'd by the cairo_surface_destroy ()
      * who called us.
      */
 
     return CAIRO_STATUS_SUCCESS;
--- a/gfx/cairo/cairo/src/cairo-output-stream.c
+++ b/gfx/cairo/cairo/src/cairo-output-stream.c
@@ -33,18 +33,20 @@
  * Author(s):
  *	Kristian Høgsberg <krh@redhat.com>
  */
 
 #include "cairoint.h"
 
 #include "cairo-output-stream-private.h"
 
+#include <stdio.h>
 #include <locale.h>
 #include <ctype.h>
+#include <errno.h>
 
 #ifdef _MSC_VER
 #define snprintf _snprintf
 #endif /* _MSC_VER */
 
 
 void
 _cairo_output_stream_init (cairo_output_stream_t            *stream,
@@ -533,18 +535,24 @@ cairo_output_stream_t *
 cairo_output_stream_t *
 _cairo_output_stream_create_for_filename (const char *filename)
 {
     stdio_stream_t *stream;
     FILE *file;
 
     file = fopen (filename, "wb");
     if (file == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
-	return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
+	switch (errno) {
+	case ENOMEM:
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_output_stream_t *) &_cairo_output_stream_nil;
+	default:
+	    _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
+	    return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
+	}
     }
 
     stream = malloc (sizeof *stream);
     if (stream == NULL) {
 	fclose (file);
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
     }
--- a/gfx/cairo/cairo/src/cairo-paginated-private.h
+++ b/gfx/cairo/cairo/src/cairo-paginated-private.h
@@ -105,28 +105,32 @@ struct _cairo_paginated_surface_backend 
  *
  * 4. Calls set_bounding_box to provide the target surface with the
  *    tight bounding box of the page.
  *
  * 5. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
  *
  * 6. Replays a subset of the meta-surface operations to the target surface
  *
- * 7. Replays the remaining operations to an image surface, sets an
+ * 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
+ *
+ * 8. Replays the remaining operations to an image surface, sets an
  *    appropriate clip on the target, then paints the resulting image
  *    surface to the target.
  *
- * So, the target will see drawing operations during two separate
- * stages, (ANALYZE and RENDER). During the ANALYZE phase the target
- * should not actually perform any rendering, (for example, if
- * performing output to a file, no output should be generated during
- * this stage). Instead the drawing functions simply need to return
- * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
- * whether rendering would be supported. And it should do this as
- * quickly as possible.
+ * So, the target will see drawing operations during three separate
+ * stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase
+ * the target should not actually perform any rendering, (for example,
+ * if performing output to a file, no output should be generated
+ * during this stage). Instead the drawing functions simply need to
+ * return CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to
+ * indicate whether rendering would be supported. And it should do
+ * this as quickly as possible. The FALLBACK phase allows the surface
+ * to distinguish fallback images from native rendering in case they
+ * need to be handled as a special case.
  *
  * NOTE: The paginated surface layer assumes that the target surface
  * is "blank" by default at the beginning of each page, without any
  * need for an explicit erase operation, (as opposed to an image
  * surface, for example, which might have uninitialized content
  * originally). As such, it optimizes away CLEAR operations that
  * happen at the beginning of each page---the target surface will not
  * even see these operations.
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -144,29 +144,29 @@ cairo_status_t
     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);
     status = cairo_surface_status (paginated_surface->meta);
     if (status)
-	return status;
+	return _cairo_surface_set_error (surface, status);
 
     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);
+	status = cairo_surface_show_page (abstract_surface);
 
     if (status == CAIRO_STATUS_SUCCESS) {
 	cairo_surface_finish (surface->target);
 	status = cairo_surface_status (surface->target);
     }
 
     if (status == CAIRO_STATUS_SUCCESS) {
 	cairo_surface_finish (surface->meta);
@@ -288,17 +288,18 @@ static cairo_int_status_t
     cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;
 
     if (surface->target->status)
 	return surface->target->status;
 
     analysis = _cairo_analysis_surface_create (surface->target,
 					       surface->width, surface->height);
     if (analysis == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return _cairo_surface_set_error (surface->target,
+		                         CAIRO_STATUS_NO_MEMORY);
 
     surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
     status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
     if (status || analysis->status) {
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = analysis->status;
 	goto FAIL;
     }
@@ -336,16 +337,17 @@ static cairo_int_status_t
             has_finegrained_fallback = FALSE;
             break;
     }
 
     if (has_supported) {
 	status = _cairo_meta_surface_replay_region (surface->meta,
 						    surface->target,
 						    CAIRO_META_REGION_NATIVE);
+	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 	if (status)
 	    goto FAIL;
     }
 
     if (has_page_fallback)
     {
 	cairo_box_int_t box;
 
@@ -359,17 +361,19 @@ static cairo_int_status_t
     }
 
     if (has_finegrained_fallback)
     {
         cairo_region_t *region;
         cairo_box_int_t *boxes;
         int num_boxes, i;
 
-	/* Reset clip region before drawing the fall back images */
+	surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
+
+    /* 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)
 	    goto FAIL;
 
@@ -609,53 +613,19 @@ static cairo_int_status_t
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
 
     return status;
 }
 
 static cairo_surface_t *
 _cairo_paginated_surface_snapshot (void *abstract_other)
 {
-    cairo_status_t status;
     cairo_paginated_surface_t *other = abstract_other;
 
-    /* XXX: Just making a snapshot of other->meta is what we really
-     * want. But this currently triggers a bug somewhere (the "mask"
-     * test from the test suite segfaults).
-     *
-     * For now, we'll create a new image surface and replay onto
-     * that. It would be tempting to replay into other->image and then
-     * return a snapshot of that, but that will cause the self-copy
-     * test to fail, (since our replay will be affected by a clip that
-     * should not have any effect on the use of the resulting snapshot
-     * as a source).
-     */
-
-#if 0
     return _cairo_surface_snapshot (other->meta);
-#else
-    cairo_rectangle_int_t extents;
-    cairo_surface_t *surface;
-
-    status = _cairo_surface_get_extents (other->target, &extents);
-    if (status)
-	return (cairo_surface_t*) &_cairo_surface_nil;
-
-    surface = _cairo_paginated_surface_create_image_surface (other,
-							     extents.width,
-							     extents.height);
-
-    status = _cairo_meta_surface_replay (other->meta, surface);
-    if (status) {
-	cairo_surface_destroy (surface);
-	surface = (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    return surface;
-#endif
 }
 
 static const cairo_surface_backend_t cairo_paginated_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
     _cairo_paginated_surface_create_similar,
     _cairo_paginated_surface_finish,
     _cairo_paginated_surface_acquire_source_image,
     _cairo_paginated_surface_release_source_image,
--- a/gfx/cairo/cairo/src/cairo-path-bounds.c
+++ b/gfx/cairo/cairo/src/cairo-path-bounds.c
@@ -143,40 +143,38 @@ static cairo_status_t
 
 static cairo_status_t
 _cairo_path_bounder_close_path (void *closure)
 {
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */
-cairo_status_t
+void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 			  double *x1, double *y1,
 			  double *x2, double *y2)
 {
     cairo_status_t status;
 
     cairo_path_bounder_t bounder;
 
     _cairo_path_bounder_init (&bounder);
 
     status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
 					  _cairo_path_bounder_move_to,
 					  _cairo_path_bounder_line_to,
 					  _cairo_path_bounder_curve_to,
 					  _cairo_path_bounder_close_path,
 					  &bounder);
-    if (status) {
-	*x1 = *y1 = *x2 = *y2 = 0.0;
-	_cairo_path_bounder_fini (&bounder);
-	return status;
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    if (! bounder.has_point) {
+	*x1 = *y1 = *x2 = *y2 = 0.;
+    } else {
+	*x1 = _cairo_fixed_to_double (bounder.min_x);
+	*y1 = _cairo_fixed_to_double (bounder.min_y);
+	*x2 = _cairo_fixed_to_double (bounder.max_x);
+	*y2 = _cairo_fixed_to_double (bounder.max_y);
     }
 
-    *x1 = _cairo_fixed_to_double (bounder.min_x);
-    *y1 = _cairo_fixed_to_double (bounder.min_y);
-    *x2 = _cairo_fixed_to_double (bounder.max_x);
-    *y2 = _cairo_fixed_to_double (bounder.max_y);
-
     _cairo_path_bounder_fini (&bounder);
-
-    return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -200,16 +200,32 @@ static int
     cairo_slope_t in_slope, out_slope;
 
     _cairo_slope_init (&in_slope, &in->point, &in->cw);
     _cairo_slope_init (&out_slope, &out->point, &out->cw);
 
     return _cairo_slope_clockwise (&in_slope, &out_slope);
 }
 
+/**
+ * _cairo_slope_compare_sgn
+ *
+ * Return -1, 0 or 1 depending on the relative slopes of
+ * two lines.
+ */
+static int
+_cairo_slope_compare_sgn (double dx1, double dy1, double dx2, double dy2)
+{
+    double  c = (dx1 * dy2 - dx2 * dy1);
+
+    if (c > 0) return 1;
+    if (c < 0) return -1;
+    return 0;
+}
+
 static cairo_status_t
 _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
 {
     int			clockwise = _cairo_stroker_face_clockwise (out, in);
     cairo_point_t	*inpt, *outpt;
     cairo_status_t status;
 
     if (in->cw.x == out->cw.x
@@ -267,19 +283,16 @@ static cairo_status_t
 	return _cairo_traps_tessellate_triangle (stroker->traps, tri);
     }
     case CAIRO_LINE_JOIN_MITER:
     default: {
 	/* dot product of incoming slope vector with outgoing slope vector */
 	double	in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+
 			      (-in->usr_vector.y * out->usr_vector.y));
 	double	ml = stroker->style->miter_limit;
-	double tolerance_squared = stroker->tolerance * stroker->tolerance;
-	double line_width_squared = (stroker->style->line_width *
-				     stroker->style->line_width);
 
 	/* Check the miter limit -- lines meeting at an acute angle
 	 * can generate long miters, the limit converts them to bevel
 	 *
 	 * Consider the miter join formed when two line segments
 	 * meet at an angle psi:
 	 *
 	 *	   /.\
@@ -327,94 +340,27 @@ static cairo_status_t
 	 *				in · out = |in| |out| cos (psi)
 	 *
 	 * in and out are both unit vectors, so:
 	 *
 	 *				in · out = cos (psi)
 	 *
 	 *	2 <= ml² (1 - in · out)
 	 *
-	 *
-	 * That gives us the condition to avoid generating miters that
-	 * are too large from angles that are too large. But we also
-	 * need to avoid generating miters when the angle is very small.
-	 *
-	 * The miter formed from a tiny angle is also tiny, so the
-	 * miter limit is not a concern. But with a tiny angle we will
-	 * be computing the intersection of two lines that are very
-	 * near parallel. Also, the limits of the fixed-point grid on
-	 * the input face coordinates mean that the resulting
-	 * intersection could be wildly wrong. (See the
-	 * get-path-extents test case for a call to cairo_arc that
-	 * results in two problematic faces.)
-	 *
-	 * Fortunately we can also derive an expression for when using
-	 * a bevel join instead of a miter will introduce an error no
-	 * larger than the tolerance. Consider the same join from
-	 * before but with the miter now chopped off and replaced with
-	 * a bevel join. The drawing is zoomed in a bit again, the
-	 * point marked as '*' is the center of the stroke---the point
-	 * where the two line segments of interest intersect:
-	 *
-	 *    ----- .
-	 *    ^     ..
-	 *    |     . .
-	 *    |     .  .
-	 *   1/2    .   .
-	 *  miter   .    .         |
-	 *  length  .     .        |
-	 *    |     .______.    ___v___
-	 *    |     |     . \   1/2 bevel
-	 *    v     |  .     \   width
-	 *    ----  *         \ -------
-	 *	    |          \   ^
-	 *
-	 *
-	 * The length of interest here is the vertical length of the
-	 * miter that is eliminated. It's length can be obtained by
-	 * starting with 1/2 the miter length and the subtracting off
-	 * the vertical length that is included by the bevel join,
-	 * (here termed 1/2 bevel width). To determine this new bevel
-	 * width, we have a small right triangle shown, the hypotenuse
-	 * of which has a length of 1/2 the line width, and the small
-	 * angle at the upper right of the figure is psi/2.
-	 *
-	 * So we have:
-	 *
-	 *	sin (psi/2) = (bevel_width / 2) / (line_width / 2)
-	 *
-	 * And we can determine when the miter is required by
-	 * calculating when the eliminated portion of the miter is
-	 * greater than the tolerance:
-	 *
-	 *	(miter_length / 2) - (bevel_width / 2) > tolerance
-	 *
-	 * Substituting in the above expressions for miter_length and
-	 * bevel_width:
-	 *
-	 *	(line_width/2) / sin (psi/2) - (line_width/2) * sin (psi/2) > tolerance
-	 *	1 / sin(psi/2) - sin (psi/2) > 2 * tolerance / line_width
-	 *	1 / sin²(psi/2) -2 +  sin²(psi/2) > 4 * (tolerance/line_width)²
-	 *
-	 * Use identity: sin²(psi/2) = (1-cos(psi))/2
-
-	 *	2/(1 - cos(psi)) - 2 + (1-cos(psi))/2 > 4 * (tolerance/line_width)²
-	 *	4/(1 - cos(psi)) - 4 + (1-cos(psi)) > 8 * (tolerance/line_width)²
-	 *	4/(1 - cos(psi)) + (1-cos(psi)) > 8 * ((tolerance/line_width)² + 0.5)
 	 */
-	if ((2 <= ml * ml * (1 - in_dot_out)) &&
-	    ((8 * (tolerance_squared / line_width_squared + 0.5)) <
-	     4 / (1 - in_dot_out) + (1 - in_dot_out))
-	    )
+	if (2 <= ml * ml * (1 - in_dot_out))
 	{
 	    double		x1, y1, x2, y2;
 	    double		mx, my;
 	    double		dx1, dx2, dy1, dy2;
 	    cairo_point_t	outer;
 	    cairo_point_t	quad[4];
+	    double		ix, iy;
+	    double		fdx1, fdy1, fdx2, fdy2;
+	    double		mdx, mdy;
 
 	    /*
 	     * we've got the points already transformed to device
 	     * space, but need to do some computation with them and
 	     * also need to transform the slope from user space to
 	     * device space
 	     */
 	    /* outer point of incoming line face */
@@ -442,27 +388,56 @@ static cairo_status_t
 	    my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
 		  (dx1 * dy2 - dx2 * dy1));
 	    if (fabs (dy1) >= fabs (dy2))
 		mx = (my - y1) * dx1 / dy1 + x1;
 	    else
 		mx = (my - y2) * dx2 / dy2 + x2;
 
 	    /*
-	     * Draw the quadrilateral
+	     * When the two outer edges are nearly parallel, slight
+	     * perturbations in the position of the outer points of the lines
+	     * caused by representing them in fixed point form can cause the
+	     * intersection point of the miter to move a large amount. If
+	     * that moves the miter intersection from between the two faces,
+	     * then draw a bevel instead.
 	     */
-	    outer.x = _cairo_fixed_from_double (mx);
-	    outer.y = _cairo_fixed_from_double (my);
+
+	    ix = _cairo_fixed_to_double (in->point.x);
+	    iy = _cairo_fixed_to_double (in->point.y);
+
+	    /* slope of one face */
+	    fdx1 = x1 - ix; fdy1 = y1 - iy;
+
+	    /* slope of the other face */
+	    fdx2 = x2 - ix; fdy2 = y2 - iy;
+
+	    /* slope from the intersection to the miter point */
+	    mdx = mx - ix; mdy = my - iy;
 
-	    quad[0] = in->point;
-	    quad[1] = *inpt;
-	    quad[2] = outer;
-	    quad[3] = *outpt;
+	    /*
+	     * Make sure the miter point line lies between the two
+	     * faces by comparing the slopes
+	     */
+	    if (_cairo_slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
+		_cairo_slope_compare_sgn (fdx2, fdy2, mdx, mdy))
+	    {
+		/*
+		 * Draw the quadrilateral
+		 */
+		outer.x = _cairo_fixed_from_double (mx);
+		outer.y = _cairo_fixed_from_double (my);
 
-	    return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
+		quad[0] = in->point;
+		quad[1] = *inpt;
+		quad[2] = outer;
+		quad[3] = *outpt;
+
+		return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
+	    }
 	}
 	/* fall through ... */
     }
     case CAIRO_LINE_JOIN_BEVEL: {
 	cairo_point_t tri[3];
 	tri[0] = in->point;
 	tri[1] = *inpt;
 	tri[2] = *outpt;
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -86,18 +86,16 @@ static cairo_status_t
     _cairo_status_set_error (&pattern->status, status);
 
     return _cairo_error (status);
 }
 
 static void
 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
 {
-    CAIRO_MUTEX_INITIALIZE ();
-
     pattern->type      = type;
     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
     pattern->status    = CAIRO_STATUS_SUCCESS;
 
     _cairo_user_data_array_init (&pattern->user_data);
 
     if (type == CAIRO_PATTERN_TYPE_SURFACE)
 	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
@@ -208,16 +206,52 @@ void
 	    (cairo_gradient_pattern_t *) pattern;
 
 	if (gradient->stops && gradient->stops != gradient->stops_embedded)
 	    free (gradient->stops);
     } break;
     }
 }
 
+cairo_status_t
+_cairo_pattern_create_copy (cairo_pattern_t	  **pattern,
+			    const cairo_pattern_t  *other)
+{
+    cairo_status_t status;
+
+    if (other->status)
+	return other->status;
+
+    switch (other->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	*pattern = malloc (sizeof (cairo_solid_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	*pattern = malloc (sizeof (cairo_surface_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	*pattern = malloc (sizeof (cairo_linear_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	*pattern = malloc (sizeof (cairo_radial_pattern_t));
+	break;
+    }
+    if (*pattern == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = _cairo_pattern_init_copy (*pattern, other);
+    if (status) {
+	free (*pattern);
+	return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
 void
 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
 			   const cairo_color_t	 *color,
 			   cairo_content_t	  content)
 {
     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
     pattern->color = *color;
     pattern->content = content;
@@ -334,16 +368,18 @@ static void
 static const cairo_pattern_t *
 _cairo_pattern_create_in_error (cairo_status_t status)
 {
     cairo_pattern_t *pattern;
 
     if (status == CAIRO_STATUS_NO_MEMORY)
 	return (cairo_pattern_t *)&_cairo_pattern_nil.base;
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK),
 					   CAIRO_CONTENT_COLOR);
     if (pattern->status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_pattern_set_error (pattern, status);
 
     return pattern;
 }
 
@@ -374,16 +410,18 @@ cairo_pattern_create_rgb (double red, do
     cairo_color_t color;
 
     _cairo_restrict_value (&red,   0.0, 1.0);
     _cairo_restrict_value (&green, 0.0, 1.0);
     _cairo_restrict_value (&blue,  0.0, 1.0);
 
     _cairo_color_init_rgb (&color, red, green, blue);
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     pattern = _cairo_pattern_create_solid (&color,
 					   CAIRO_CONTENT_COLOR);
     if (pattern->status)
 	_cairo_error_throw (pattern->status);
 
     return pattern;
 }
 slim_hidden_def (cairo_pattern_create_rgb);
@@ -418,16 +456,18 @@ cairo_pattern_create_rgba (double red, d
 
     _cairo_restrict_value (&red,   0.0, 1.0);
     _cairo_restrict_value (&green, 0.0, 1.0);
     _cairo_restrict_value (&blue,  0.0, 1.0);
     _cairo_restrict_value (&alpha, 0.0, 1.0);
 
     _cairo_color_init_rgba (&color, red, green, blue, alpha);
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     pattern = _cairo_pattern_create_solid (&color,
 					   CAIRO_CONTENT_COLOR_ALPHA);
     if (pattern->status)
 	_cairo_error_throw (pattern->status);
 
     return pattern;
 }
 slim_hidden_def (cairo_pattern_create_rgba);
@@ -459,16 +499,18 @@ cairo_pattern_create_for_surface (cairo_
 	return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
 
     pattern = malloc (sizeof (cairo_surface_pattern_t));
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *)&_cairo_pattern_nil.base;
     }
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     _cairo_pattern_init_for_surface (pattern, surface);
 
     return &pattern->base;
 }
 slim_hidden_def (cairo_pattern_create_for_surface);
 
 /**
  * cairo_pattern_create_linear:
@@ -502,16 +544,18 @@ cairo_pattern_create_linear (double x0, 
     cairo_linear_pattern_t *pattern;
 
     pattern = malloc (sizeof (cairo_linear_pattern_t));
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     }
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
 
     return &pattern->base.base;
 }
 
 /**
  * cairo_pattern_create_radial:
  * @cx0: x coordinate for the center of the start circle
@@ -547,16 +591,18 @@ cairo_pattern_create_radial (double cx0,
     cairo_radial_pattern_t *pattern;
 
     pattern = malloc (sizeof (cairo_radial_pattern_t));
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     }
 
+    CAIRO_MUTEX_INITIALIZE ();
+
     _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
 
     return &pattern->base.base;
 }
 
 /**
  * cairo_pattern_reference:
  * @pattern: a #cairo_pattern_t
@@ -1777,17 +1823,18 @@ cairo_int_status_t
 	cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
 
 	status = _cairo_pattern_acquire_surface_for_surface (src, dst,
 							     x, y, width, height,
 							     surface_out,
 							     attributes);
     } break;
     default:
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	ASSERT_NOT_REACHED;
+	status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
     }
 
     return status;
 }
 
 /**
  * _cairo_pattern_release_surface:
  * @pattern: a #cairo_pattern_t
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h
@@ -0,0 +1,107 @@
+/* -*- 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 © 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.
+ *
+ * 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 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_OPERATORS_H
+#define CAIRO_PDF_OPERATORS_H
+
+#include "cairo-compiler-private.h"
+#include "cairo-types-private.h"
+
+typedef cairo_status_t
+(*cairo_pdf_operators_use_font_subset_t) (unsigned int  font_id,
+					  unsigned int  subset_id,
+					  void         *closure);
+
+typedef struct _cairo_pdf_operators {
+    cairo_output_stream_t *stream;
+    cairo_matrix_t cairo_to_pdf;
+    cairo_scaled_font_subsets_t *font_subsets;
+    cairo_pdf_operators_use_font_subset_t use_font_subset;
+    void *use_font_subset_closure;
+} cairo_pdf_operators_t;
+
+cairo_private void
+_cairo_pdf_operators_init (cairo_pdf_operators_t       *pdf_operators,
+			   cairo_output_stream_t       *stream,
+			   cairo_matrix_t 		cairo_to_pdf,
+			   cairo_scaled_font_subsets_t *font_subsets);
+
+cairo_private void
+_cairo_pdf_operators_fini (cairo_pdf_operators_t       *pdf_operators);
+
+cairo_private void
+_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t 		     *pdf_operators,
+						cairo_pdf_operators_use_font_subset_t use_font_subset,
+						void				     *closure);
+
+cairo_private void
+_cairo_pdf_operators_set_stream (cairo_pdf_operators_t 	 *pdf_operators,
+				 cairo_output_stream_t   *stream);
+
+
+cairo_private void
+_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
+					      cairo_matrix_t 	     cairo_to_pdf);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_clip (cairo_pdf_operators_t 	*pdf_operators,
+			   cairo_path_fixed_t		*path,
+			   cairo_fill_rule_t		 fill_rule);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operator_stroke (cairo_pdf_operators_t 	*pdf_operators,
+			    cairo_path_fixed_t		*path,
+			    cairo_stroke_style_t	*style,
+			    cairo_matrix_t		*ctm,
+			    cairo_matrix_t		*ctm_inverse);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_fill (cairo_pdf_operators_t 	*pdf_operators,
+			   cairo_path_fixed_t		*path,
+			   cairo_fill_rule_t	 	fill_rule);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
+				  cairo_glyph_t		*glyphs,
+				  int			 num_glyphs,
+				  cairo_scaled_font_t	*scaled_font);
+
+#endif /* CAIRO_PDF_OPERATORS_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c
@@ -0,0 +1,532 @@
+/* -*- 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 © 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.
+ *
+ * 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 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-operators-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-output-stream-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+
+void
+_cairo_pdf_operators_init (cairo_pdf_operators_t	*pdf_operators,
+			   cairo_output_stream_t	*stream,
+			   cairo_matrix_t		 cairo_to_pdf,
+			   cairo_scaled_font_subsets_t  *font_subsets)
+{
+    pdf_operators->stream = stream;
+    pdf_operators->cairo_to_pdf = cairo_to_pdf;
+    pdf_operators->font_subsets = font_subsets;
+    pdf_operators->use_font_subset = NULL;
+    pdf_operators->use_font_subset_closure = NULL;
+}
+
+void
+_cairo_pdf_operators_fini (cairo_pdf_operators_t	*pdf_operators)
+{
+}
+
+void
+_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t		     *pdf_operators,
+						cairo_pdf_operators_use_font_subset_t use_font_subset,
+						void				     *closure)
+{
+    pdf_operators->use_font_subset = use_font_subset;
+    pdf_operators->use_font_subset_closure = closure;
+}
+
+void
+_cairo_pdf_operators_set_stream (cairo_pdf_operators_t	 *pdf_operators,
+				 cairo_output_stream_t   *stream)
+{
+    pdf_operators->stream = stream;
+}
+
+void
+_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
+					      cairo_matrix_t	     cairo_to_pdf)
+{
+    pdf_operators->cairo_to_pdf = cairo_to_pdf;
+}
+
+typedef struct _pdf_path_info {
+    cairo_output_stream_t   *output;
+    cairo_matrix_t	    *cairo_to_pdf;
+    cairo_matrix_t	    *ctm_inverse;
+} pdf_path_info_t;
+
+static cairo_status_t
+_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
+{
+    pdf_path_info_t *info = closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    if (info->cairo_to_pdf)
+        cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
+    if (info->ctm_inverse)
+	cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
+
+    _cairo_output_stream_printf (info->output,
+				 "%f %f m ", x, y);
+
+    return _cairo_output_stream_get_status (info->output);
+}
+
+static cairo_status_t
+_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
+{
+    pdf_path_info_t *info = closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    if (info->cairo_to_pdf)
+        cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
+    if (info->ctm_inverse)
+	cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
+
+    _cairo_output_stream_printf (info->output,
+				 "%f %f l ", x, y);
+
+    return _cairo_output_stream_get_status (info->output);
+}
+
+static cairo_status_t
+_cairo_pdf_path_curve_to (void          *closure,
+			  cairo_point_t *b,
+			  cairo_point_t *c,
+			  cairo_point_t *d)
+{
+    pdf_path_info_t *info = closure;
+    double bx = _cairo_fixed_to_double (b->x);
+    double by = _cairo_fixed_to_double (b->y);
+    double cx = _cairo_fixed_to_double (c->x);
+    double cy = _cairo_fixed_to_double (c->y);
+    double dx = _cairo_fixed_to_double (d->x);
+    double dy = _cairo_fixed_to_double (d->y);
+
+    if (info->cairo_to_pdf) {
+        cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
+        cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
+        cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
+    }
+    if (info->ctm_inverse) {
+	cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
+	cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
+	cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
+    }
+
+    _cairo_output_stream_printf (info->output,
+				 "%f %f %f %f %f %f c ",
+				 bx, by, cx, cy, dx, dy);
+    return _cairo_output_stream_get_status (info->output);
+}
+
+static cairo_status_t
+_cairo_pdf_path_close_path (void *closure)
+{
+    pdf_path_info_t *info = closure;
+
+    _cairo_output_stream_printf (info->output,
+				 "h\r\n");
+
+    return _cairo_output_stream_get_status (info->output);
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_clip (cairo_pdf_operators_t	*pdf_operators,
+			   cairo_path_fixed_t		*path,
+			   cairo_fill_rule_t		 fill_rule)
+{
+    const char *pdf_operator;
+
+    if (! path->has_current_point) {
+	/* construct an empty path */
+	_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
+    } else {
+	pdf_path_info_t info;
+	cairo_status_t status;
+
+	info.output = pdf_operators->stream;
+	info.cairo_to_pdf = &pdf_operators->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);
+	if (status)
+	    return status;
+    }
+
+    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 (pdf_operators->stream,
+				 "%s n\r\n",
+				 pdf_operator);
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static int
+_cairo_pdf_line_cap (cairo_line_cap_t cap)
+{
+    switch (cap) {
+    case CAIRO_LINE_CAP_BUTT:
+	return 0;
+    case CAIRO_LINE_CAP_ROUND:
+	return 1;
+    case CAIRO_LINE_CAP_SQUARE:
+	return 2;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static int
+_cairo_pdf_line_join (cairo_line_join_t join)
+{
+    switch (join) {
+    case CAIRO_LINE_JOIN_MITER:
+	return 0;
+    case CAIRO_LINE_JOIN_ROUND:
+	return 1;
+    case CAIRO_LINE_JOIN_BEVEL:
+	return 2;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static cairo_int_status_t
+_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t	*pdf_operators,
+					cairo_stroke_style_t	*style)
+{
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%f w\r\n",
+				 style->line_width);
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%d J\r\n",
+				 _cairo_pdf_line_cap (style->line_cap));
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%d j\r\n",
+				 _cairo_pdf_line_join (style->line_join));
+
+    if (style->num_dashes) {
+	unsigned int d;
+	_cairo_output_stream_printf (pdf_operators->stream, "[");
+	for (d = 0; d < style->num_dashes; d++)
+	    _cairo_output_stream_printf (pdf_operators->stream, " %f", style->dash[d]);
+	_cairo_output_stream_printf (pdf_operators->stream, "] %f d\r\n",
+				     style->dash_offset);
+    } else {
+	_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\r\n");
+    }
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%f M ",
+				 style->miter_limit);
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+
+cairo_int_status_t
+_cairo_pdf_operator_stroke (cairo_pdf_operators_t	*pdf_operators,
+			    cairo_path_fixed_t		*path,
+			    cairo_stroke_style_t	*style,
+			    cairo_matrix_t		*ctm,
+			    cairo_matrix_t		*ctm_inverse)
+{
+    pdf_path_info_t info;
+    cairo_status_t status;
+    cairo_matrix_t m;
+
+    status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
+    if (status)
+	return status;
+
+    info.output = pdf_operators->stream;
+    info.cairo_to_pdf = NULL;
+    info.ctm_inverse = ctm_inverse;
+
+    cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "q %f %f %f %f %f %f cm\r\n",
+				 m.xx, m.yx, m.xy, m.yy,
+				 m.x0, m.y0);
+
+    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);
+    if (status)
+	return status;
+
+    _cairo_output_stream_printf (pdf_operators->stream, "S Q\r\n");
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_fill (cairo_pdf_operators_t	*pdf_operators,
+			   cairo_path_fixed_t		*path,
+			   cairo_fill_rule_t		fill_rule)
+{
+    const char *pdf_operator;
+    cairo_status_t status;
+    pdf_path_info_t info;
+
+    info.output = pdf_operators->stream;
+    info.cairo_to_pdf = &pdf_operators->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);
+    if (status)
+	return status;
+
+    switch (fill_rule) {
+    case CAIRO_FILL_RULE_WINDING:
+	pdf_operator = "f";
+	break;
+    case CAIRO_FILL_RULE_EVEN_ODD:
+	pdf_operator = "f*";
+	break;
+    default:
+	ASSERT_NOT_REACHED;
+    }
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%s\r\n",
+				 pdf_operator);
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+#define GLYPH_POSITION_TOLERANCE 0.001
+
+cairo_int_status_t
+_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t		*pdf_operators,
+				  cairo_glyph_t			*glyphs,
+				  int				 num_glyphs,
+				  cairo_scaled_font_t		*scaled_font)
+{
+    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;
+
+    for (i = 0; i < num_glyphs; i++)
+	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "BT\r\n");
+
+    if (scaled_font->scale.xy == 0.0 &&
+        scaled_font->scale.yx == 0.0)
+        diagonal = TRUE;
+    else
+        diagonal = FALSE;
+
+    in_TJ = FALSE;
+    for (i = 0; i < num_glyphs; i++) {
+        status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+                                                       scaled_font, glyphs[i].index,
+                                                       &subset_glyph);
+	if (status)
+            return status;
+
+        if (subset_glyph.is_composite)
+            hex_width = 4;
+        else
+            hex_width = 2;
+
+        if (subset_glyph.is_scaled == FALSE) {
+            y = 0.0;
+            cairo_matrix_transform_distance (&scaled_font->scale,
+                                             &subset_glyph.x_advance,
+                                             &y);
+        }
+
+	if (subset_glyph.subset_id != current_subset_id) {
+            if (in_TJ) {
+                _cairo_output_stream_printf (pdf_operators->stream, ">] TJ\r\n");
+                in_TJ = FALSE;
+            }
+	    _cairo_output_stream_printf (pdf_operators->stream,
+					 "/f-%d-%d 1 Tf\r\n",
+					 subset_glyph.font_id,
+					 subset_glyph.subset_id);
+	    if (pdf_operators->use_font_subset) {
+		status = pdf_operators->use_font_subset (subset_glyph.font_id,
+							 subset_glyph.subset_id,
+							 pdf_operators->use_font_subset_closure);
+		if (status)
+		    return status;
+	    }
+        }
+
+        if (subset_glyph.subset_id != current_subset_id || !diagonal) {
+            _cairo_output_stream_printf (pdf_operators->stream,
+                                         "%f %f %f %f %f %f Tm\r\n",
+                                         scaled_font->scale.xx,
+                                         -scaled_font->scale.yx,
+                                         -scaled_font->scale.xy,
+                                         scaled_font->scale.yy,
+                                         glyphs[i].x,
+                                         glyphs[i].y);
+            current_subset_id = subset_glyph.subset_id;
+            Tlm_x = glyphs[i].x;
+            Tlm_y = glyphs[i].y;
+            Tm_x = Tlm_x;
+        }
+
+        if (diagonal) {
+            if (i < num_glyphs - 1 &&
+                fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
+                fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
+            {
+                if (!in_TJ) {
+                    if (i != 0) {
+                        _cairo_output_stream_printf (pdf_operators->stream,
+                                                     "%f %f Td\r\n",
+                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+                                                     (glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
+
+                        Tlm_x = glyphs[i].x;
+                        Tlm_y = glyphs[i].y;
+                        Tm_x = Tlm_x;
+                    }
+                    _cairo_output_stream_printf (pdf_operators->stream,
+                                                 "[<%0*x",
+                                                 hex_width,
+                                                 subset_glyph.subset_glyph_index);
+                    Tm_x += subset_glyph.x_advance;
+                    in_TJ = TRUE;
+                } else {
+                    if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
+                        double delta = glyphs[i].x - Tm_x;
+
+                        _cairo_output_stream_printf (pdf_operators->stream,
+                                                     "> %f <",
+                                                     -1000.0*delta/scaled_font->scale.xx);
+                        Tm_x += delta;
+                    }
+                    _cairo_output_stream_printf (pdf_operators->stream,
+                                                 "%0*x",
+                                                 hex_width,
+                                                 subset_glyph.subset_glyph_index);
+                    Tm_x += subset_glyph.x_advance;
+                }
+            }
+            else
+            {
+                if (in_TJ) {
+                    if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
+                        double delta = glyphs[i].x - Tm_x;
+
+                        _cairo_output_stream_printf (pdf_operators->stream,
+                                                     "> %f <",
+                                                     -1000.0*delta/scaled_font->scale.xx);
+                        Tm_x += delta;
+                    }
+                    _cairo_output_stream_printf (pdf_operators->stream,
+                                                 "%0*x>] TJ\r\n",
+                                                 hex_width,
+                                                 subset_glyph.subset_glyph_index);
+                    Tm_x += subset_glyph.x_advance;
+                    in_TJ = FALSE;
+                } else {
+                    if (i != 0) {
+                        _cairo_output_stream_printf (pdf_operators->stream,
+                                                     "%f %f Td ",
+                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+                                                     (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
+                        Tlm_x = glyphs[i].x;
+                        Tlm_y = glyphs[i].y;
+                        Tm_x = Tlm_x;
+                    }
+                    _cairo_output_stream_printf (pdf_operators->stream,
+                                                 "<%0*x> Tj ",
+                                                 hex_width,
+                                                 subset_glyph.subset_glyph_index);
+                    Tm_x += subset_glyph.x_advance;
+                }
+            }
+        } else {
+            _cairo_output_stream_printf (pdf_operators->stream,
+                                         "<%0*x> Tj\r\n",
+                                         hex_width,
+                                         subset_glyph.subset_glyph_index);
+        }
+    }
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "ET\r\n");
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
--- a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h
@@ -1,13 +1,14 @@
+/* -*- 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 © 2006 Red Hat, Inc
- * Copyright © 2007 Adrian Johnson
+ * Copyright © 2007, 2008 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.
@@ -39,29 +40,62 @@
  */
 
 #ifndef CAIRO_PDF_SURFACE_PRIVATE_H
 #define CAIRO_PDF_SURFACE_PRIVATE_H
 
 #include "cairo-pdf.h"
 
 #include "cairo-surface-private.h"
+#include "cairo-pdf-operators-private.h"
+#include "cairo-path-fixed-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_pattern {
+    cairo_pattern_t *pattern;
+    cairo_pdf_resource_t pattern_res;
+    cairo_pdf_resource_t gstate_res;
+} cairo_pdf_pattern_t;
+
+typedef enum _cairo_pdf_operation {
+    PDF_PAINT,
+    PDF_MASK,
+    PDF_FILL,
+    PDF_STROKE,
+    PDF_SHOW_GLYPHS
+} cairo_pdf_operation_t;
+
+typedef struct _cairo_pdf_smask_group
+{
+    cairo_pdf_resource_t  group_res;
+    cairo_pdf_operation_t operation;
+    cairo_pattern_t	 *source;
+    cairo_pdf_resource_t  source_res;
+    cairo_pattern_t	 *mask;
+    cairo_path_fixed_t	  path;
+    cairo_fill_rule_t	  fill_rule;
+    cairo_stroke_style_t *style;
+    cairo_matrix_t	  ctm;
+    cairo_matrix_t	  ctm_inverse;
+    cairo_glyph_t	 *glyphs;
+    int			  num_glyphs;
+    cairo_scaled_font_t	 *scaled_font;
+} cairo_pdf_smask_group_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;
@@ -69,67 +103,52 @@ struct _cairo_pdf_surface {
     double width;
     double height;
     cairo_matrix_t cairo_to_pdf;
 
     cairo_array_t objects;
     cairo_array_t pages;
     cairo_array_t rgb_linear_functions;
     cairo_array_t alpha_linear_functions;
+    cairo_array_t patterns;
+    cairo_array_t smask_groups;
     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;
 
     cairo_bool_t compress_content;
 
+    cairo_pdf_resource_t content;
+    cairo_pdf_resource_t content_resources;
+    cairo_pdf_group_resources_t resources;
+    cairo_bool_t has_fallback_images;
+
     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;
     } pdf_stream;
 
     struct {
 	cairo_bool_t active;
 	cairo_output_stream_t *stream;
 	cairo_output_stream_t *mem_stream;
 	cairo_output_stream_t *old_output;
-	cairo_pdf_group_resources_t resources;
+	cairo_pdf_resource_t   resource;
 	cairo_bool_t is_knockout;
-	cairo_pdf_resource_t first_object;
     } group_stream;
 
-    struct {
-	cairo_bool_t active;
-	cairo_output_stream_t *stream;
-	cairo_output_stream_t *mem_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_array_t *current_group;
-    cairo_pdf_group_resources_t *current_resources;
-
+    cairo_pdf_operators_t pdf_operators;
     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,13 +1,14 @@
+/* -*- 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 © 2006 Red Hat, Inc
- * Copyright © 2007 Adrian Johnson
+ * Copyright © 2007, 2008 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.
@@ -36,19 +37,19 @@
  *	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-pdf-operators-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:
  *
@@ -82,110 +83,53 @@
  *
  * 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_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 ()
+ *     _cairo_pdf_surface_open_content_stream ()
+ *     _cairo_pdf_surface_close_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.
+ *   The Content Stream contains the text and graphics operators.
  *
  * 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.
+ *   A Group Stream is a Form XObject. It is used for short sequences
+ *   of operators. As the content is very short the group is stored in
+ *   memory until it is closed. This allows some optimization such as
+ *   including the Resource dictionary and stream length inside the
+ *   XObject instead of using an indirect object.
  */
 
-/* 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;
@@ -198,46 +142,39 @@ 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);
+_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
 
 static void
-_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
+_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
+
+static cairo_status_t
+_cairo_pdf_surface_add_font (unsigned int        font_id,
+			     unsigned int        subset_id,
+			     void		*closure);
 
 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_pdf_resource_t    *resource,
                                 cairo_bool_t             compressed,
 				const char		*fmt,
-				...) CAIRO_PRINTF_FORMAT(3, 4);
+				...) CAIRO_PRINTF_FORMAT(4, 5);
 static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t	*surface);
 
 static cairo_status_t
 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
 
 static void
 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
@@ -247,21 +184,16 @@ static cairo_pdf_resource_t
 
 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;
 
@@ -311,60 +243,61 @@ static cairo_surface_t *
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
     _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     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->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
     _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
     _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);
+    _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
+    _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
+    _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
+
+    _cairo_pdf_group_resources_init (&surface->resources);
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
     if (! surface->font_subsets) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	goto BAIL0;
     }
 
     surface->next_available_resource.id = 1;
     surface->pages_resource = _cairo_pdf_surface_new_object (surface);
     if (surface->pages_resource.id == 0)
         goto BAIL1;
 
     surface->compress_content = TRUE;
     surface->pdf_stream.active = FALSE;
     surface->pdf_stream.old_output = NULL;
-    surface->content_stream.active = FALSE;
-    surface->content_stream.stream = NULL;
-    surface->content_stream.mem_stream = NULL;
     surface->group_stream.active = FALSE;
     surface->group_stream.stream = NULL;
     surface->group_stream.mem_stream = NULL;
 
-    surface->current_group = NULL;
-    surface->current_resources = NULL;
-
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
 
     surface->force_fallbacks = FALSE;
 
+    _cairo_pdf_operators_init (&surface->pdf_operators,
+			       surface->output,
+			       surface->cairo_to_pdf,
+			       surface->font_subsets);
+    _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
+						    _cairo_pdf_surface_add_font,
+						    surface);
+
     /* 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);
 
     surface->paginated_surface =  _cairo_paginated_surface_create (
 	                                  &surface->base,
@@ -522,29 +455,45 @@ cairo_pdf_surface_set_size (cairo_surfac
     if (status) {
 	status = _cairo_surface_set_error (surface, status);
 	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);
+    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&pdf_surface->pdf_operators,
+						  pdf_surface->cairo_to_pdf);
     status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
 						width_in_points,
 						height_in_points);
     if (status)
 	status = _cairo_surface_set_error (surface, status);
 }
 
 static void
 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
 {
-    _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);
+    int i, size;
+    cairo_pdf_pattern_t *pattern;
+    cairo_pdf_smask_group_t *group;
+
+    size = _cairo_array_num_elements (&surface->patterns);
+    for (i = 0; i < size; i++) {
+	pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i);
+	cairo_pattern_destroy (pattern->pattern);
+    }
+    _cairo_array_truncate (&surface->patterns, 0);
+
+    size = _cairo_array_num_elements (&surface->smask_groups);
+    for (i = 0; i < size; i++) {
+	_cairo_array_copy_element (&surface->smask_groups, i, &group);
+	_cairo_pdf_smask_group_destroy (group);
+    }
+    _cairo_array_truncate (&surface->smask_groups, 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));
@@ -576,17 +525,17 @@ static void
 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;
+    cairo_pdf_group_resources_t *res = &surface->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;
 	}
@@ -600,42 +549,43 @@ static cairo_status_t
 
     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);
+    return _cairo_array_append (&(surface->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);
+    return _cairo_array_append (&(surface->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);
+    return _cairo_array_append (&(surface->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_surface_add_font (unsigned int        font_id,
+			     unsigned int        subset_id,
+			     void		*closure)
 {
+    cairo_pdf_surface_t *surface = closure;
     cairo_pdf_font_t font;
     int num_fonts, i;
     cairo_status_t status;
-    cairo_pdf_group_resources_t *res = surface->current_resources;
+    cairo_pdf_group_resources_t *res = &surface->resources;
 
     num_fonts = _cairo_array_num_elements (&res->fonts);
     for (i = 0; i < num_fonts; i++) {
 	_cairo_array_copy_element (&res->fonts, i, &font);
 	if (font.font_id == font_id &&
 	    font.subset_id == subset_id)
 	    return CAIRO_STATUS_SUCCESS;
     }
@@ -663,126 +613,233 @@ static cairo_status_t
 
 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;
+
+    font.subset_resource.id = 0;
+    return font.subset_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");
+    _cairo_output_stream_printf (surface->output, "<<\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");
+				     "   /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",
+					 "      /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",
+					 "      /s%d %d 0 R\r\n",
 					 smask->id, smask->id);
 	}
 
 	_cairo_output_stream_printf (surface->output,
-				     "      >>\r\n");
+				     "   >>\r\n");
     }
 
     num_resources = _cairo_array_num_elements (&res->patterns);
     if (num_resources > 0) {
 	_cairo_output_stream_printf (surface->output,
-				     "      /Pattern <<");
+				     "   /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 <<");
+				     "   /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");
+	_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",
+					 "      /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");
     }
 
     _cairo_output_stream_printf (surface->output,
-				 "   >>\r\n");
+				 ">>\r\n");
+}
+
+static cairo_pdf_smask_group_t *
+_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t	*surface)
+{
+    cairo_pdf_smask_group_t	*group;
+
+    group = calloc (1, sizeof (cairo_pdf_smask_group_t));
+    if (group == NULL) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return NULL;
+    }
+
+    group->group_res = _cairo_pdf_surface_new_object (surface);
+    if (group->group_res.id == 0) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	free (group);
+	return NULL;
+    }
+
+    return group;
+}
+
+static void
+_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
+{
+    if (group->operation == PDF_FILL ||	group->operation == PDF_STROKE)
+	_cairo_path_fixed_fini (&group->path);
+    if (group->source)
+	cairo_pattern_destroy (group->source);
+    if (group->mask)
+	cairo_pattern_destroy (group->mask);
+    if (group->scaled_font)
+	cairo_scaled_font_destroy (group->scaled_font);
+    free (group);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
+				    cairo_pdf_smask_group_t *group)
+{
+    return _cairo_array_append (&surface->smask_groups, &group);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
+				    cairo_pattern_t		*pattern,
+				    cairo_pdf_resource_t	*pattern_res,
+				    cairo_pdf_resource_t	*gstate_res)
+{
+    cairo_pdf_pattern_t pdf_pattern;
+    cairo_status_t status;
+
+    /* Solid colors are emitted into the content stream */
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+	pattern_res->id = 0;
+	gstate_res->id = 0;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    /* Gradients with zero stops do not produce any output */
+    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+        pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
+    {
+	cairo_gradient_pattern_t *gradient;
+
+	gradient = (cairo_gradient_pattern_t *) pattern;
+	if (gradient->n_stops == 0)
+	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    pdf_pattern.pattern = cairo_pattern_reference (pattern);
+    pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
+    if (pdf_pattern.pattern_res.id == 0) {
+	cairo_pattern_destroy (pattern);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    pdf_pattern.gstate_res.id = 0;
+
+    /* gradient patterns require an smask object to implement transparency */
+    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+        pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
+        if (_cairo_pattern_is_opaque (pattern) == FALSE) {
+            pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
+	    if (pdf_pattern.gstate_res.id == 0) {
+		cairo_pattern_destroy (pattern);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+        }
+    }
+
+    *pattern_res = pdf_pattern.pattern_res;
+    *gstate_res = pdf_pattern.gstate_res;
+
+    status = _cairo_array_append (&surface->patterns, &pdf_pattern);
+    if (status) {
+	cairo_pattern_destroy (pattern);
+	return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_pdf_resource_t
 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
+				cairo_pdf_resource_t    *resource,
 				cairo_bool_t             compressed,
 				const char		*fmt,
 				...)
 {
     va_list ap;
     cairo_pdf_resource_t self, length;
     cairo_output_stream_t *output = NULL;
 
-    self = _cairo_pdf_surface_new_object (surface);
-    if (self.id == 0)
-	return self;
+    if (resource) {
+	self = *resource;
+	_cairo_pdf_surface_update_object (surface, self);
+    } else {
+	self = _cairo_pdf_surface_new_object (surface);
+	if (self.id == 0)
+	    return self;
+    }
 
     length = _cairo_pdf_surface_new_object (surface);
     if (length.id == 0)
 	return length;
 
     if (compressed) {
 	output = _cairo_deflate_stream_create (surface->output);
 	if (_cairo_output_stream_get_status (output)) {
@@ -816,16 +873,17 @@ static cairo_pdf_resource_t
 				 "stream\r\n");
 
     surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
 
     if (compressed) {
 	assert (surface->pdf_stream.old_output == NULL);
         surface->pdf_stream.old_output = surface->output;
         surface->output = output;
+	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
     }
 
     return surface->pdf_stream.self;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 {
@@ -833,16 +891,17 @@ static cairo_status_t
     long length;
 
     if (! surface->pdf_stream.active)
 	return CAIRO_STATUS_SUCCESS;
 
     if (surface->pdf_stream.compressed) {
 	status = _cairo_output_stream_destroy (surface->output);
 	surface->output = surface->pdf_stream.old_output;
+	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 	surface->pdf_stream.old_output = NULL;
 	_cairo_output_stream_printf (surface->output,
 				     "\r\n");
     }
 
     length = _cairo_output_stream_get_position (surface->output) -
 	surface->pdf_stream.start_offset;
     _cairo_output_stream_printf (surface->output,
@@ -858,33 +917,30 @@ static cairo_status_t
 				 surface->pdf_stream.length.id,
 				 length);
 
     surface->pdf_stream.active = FALSE;
 
     return status;
 }
 
-static cairo_pdf_resource_t
+static void
 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t         *surface,
 					cairo_output_stream_t       *mem_stream,
+					cairo_pdf_resource_t         resource,
 					cairo_pdf_group_resources_t *resources,
 					cairo_bool_t                 is_knockout_group)
 {
-    cairo_pdf_resource_t group;
-
-    group = _cairo_pdf_surface_new_object (surface);
-    if (group.id == 0)
-	return group;
+    _cairo_pdf_surface_update_object (surface, resource);
 
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /XObject\r\n"
 				 "   /Length %d\r\n",
-				 group.id,
+				 resource.id,
 				 _cairo_memory_stream_length (mem_stream));
 
     if (surface->compress_content) {
 	_cairo_output_stream_printf (surface->output,
 				     "   /Filter /FlateDecode\r\n");
     }
 
     _cairo_output_stream_printf (surface->output,
@@ -893,308 +949,211 @@ static cairo_pdf_resource_t
 				 "   /Group <<\r\n"
 				 "      /Type /Group\r\n"
 				 "      /S /Transparency\r\n"
 				 "      /CS /DeviceRGB\r\n",
 				 surface->width,
 				 surface->height);
 
     if (is_knockout_group)
-	_cairo_output_stream_printf (surface->output,
-				     "      /K true\r\n");
+        _cairo_output_stream_printf (surface->output,
+                                     "      /K true\r\n");
 
     _cairo_output_stream_printf (surface->output,
-				 "   >>\r\n");
+				 "   >>\r\n"
+				 "   /Resources\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 cairo_status_t
-_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_open_group (cairo_pdf_surface_t  *surface,
+			       cairo_pdf_resource_t *resource)
 {
     cairo_status_t status;
 
     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.mem_stream = _cairo_memory_stream_create ();
 
     if (surface->compress_content) {
 	surface->group_stream.stream =
 	    _cairo_deflate_stream_create (surface->group_stream.mem_stream);
     } else {
 	surface->group_stream.stream = surface->group_stream.mem_stream;
     }
     status = _cairo_output_stream_get_status (surface->group_stream.stream);
-    if (status)
-	return status;
 
     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;
+    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
+    _cairo_pdf_group_resources_clear (&surface->resources);
+
+    if (resource) {
+	surface->group_stream.resource = *resource;
+    } else {
+	surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
+	if (surface->group_stream.resource.id == 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
     surface->group_stream.is_knockout = FALSE;
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t  *surface,
-					cairo_pdf_resource_t *first_object)
+_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t  *surface)
 {
     cairo_status_t status;
 
-    status = _cairo_pdf_surface_open_group (surface);
+    status = _cairo_pdf_surface_open_group (surface, NULL);
     if (status)
 	return status;
 
     surface->group_stream.is_knockout = TRUE;
-    surface->group_stream.first_object = *first_object;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
 				cairo_pdf_resource_t *group)
 {
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
 
     assert (surface->pdf_stream.active == FALSE);
     assert (surface->group_stream.active == TRUE);
 
     if (surface->compress_content) {
 	status = _cairo_output_stream_destroy (surface->group_stream.stream);
-	if (status)
-	    return status;
+	surface->group_stream.stream = NULL;
 
 	_cairo_output_stream_printf (surface->group_stream.mem_stream,
 				     "\r\n");
     }
     surface->output = surface->group_stream.old_output;
+    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
     surface->group_stream.active = FALSE;
-    *group = _cairo_pdf_surface_write_memory_stream (surface,
-						     surface->group_stream.mem_stream,
-						     &surface->group_stream.resources,
-						     surface->group_stream.is_knockout);
-    if (group->id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    return _cairo_output_stream_close (surface->group_stream.mem_stream);
+    _cairo_pdf_surface_write_memory_stream (surface,
+					    surface->group_stream.mem_stream,
+					    surface->group_stream.resource,
+					    &surface->resources,
+					    surface->group_stream.is_knockout);
+    if (group)
+	*group = surface->group_stream.resource;
+
+    status2 =  _cairo_output_stream_destroy (surface->group_stream.mem_stream);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
+
+    surface->group_stream.mem_stream = NULL;
+    surface->group_stream.stream = NULL;
+
+    return status;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_write_group_list (cairo_pdf_surface_t  *surface,
-				     cairo_array_t        *group_list)
+_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
+					cairo_pdf_resource_t *resource,
+					cairo_bool_t          is_form)
 {
-    int i, len;
-    cairo_pdf_group_element_t *elem;
-    cairo_status_t status;
+    assert (surface->pdf_stream.active == FALSE);
+    assert (surface->group_stream.active == FALSE);
+
+    surface->content_resources = _cairo_pdf_surface_new_object (surface);
+    if (surface->content_resources.id == 0)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    if (is_form) {
+	*resource =
+	    _cairo_pdf_surface_open_stream (surface,
+					    NULL,
+					    surface->compress_content,
+					    "   /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"
+					    "   /Resources %d 0 R\r\n",
+					    surface->width,
+					    surface->height,
+					    surface->content_resources.id);
+	if (resource->id == 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else {
+	surface->content =
+	    _cairo_pdf_surface_open_stream (surface,
+					    NULL,
+					    surface->compress_content,
+					    NULL);
+	if (surface->content.id == 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     _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);
-	status = _cairo_pdf_surface_add_xobject (surface, surface->group_stream.first_object);
-	if (status)
-	    return status;
-    }
-    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);
-	    status = _cairo_pdf_surface_add_xobject (surface, elem->group);
-	    if (status)
-		return status;
-	} else if (elem->type == ELEM_CLIP) {
-	    status = _cairo_pdf_surface_emit_clip (surface, elem->clip_path, elem->fill_rule);
-	    if (status)
-		return status;
-	}
-    }
-    _cairo_output_stream_printf (surface->output, "Q\r\n");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
-{
-    cairo_status_t status;
-
-    if (surface->content_stream.active)
-        return CAIRO_STATUS_SUCCESS;
-
-    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.mem_stream = _cairo_memory_stream_create ();
-
-    if (surface->compress_content) {
-	surface->content_stream.stream =
-	    _cairo_deflate_stream_create (surface->content_stream.mem_stream);
-    } else {
-	surface->content_stream.stream = surface->content_stream.mem_stream;
-    }
-    status = _cairo_output_stream_get_status (surface->content_stream.stream);
-    if (status)
-	return status;
-
-    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;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 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;
-    cairo_status_t status;
-
-    assert (surface->pdf_stream.active == FALSE);
-    assert (surface->content_stream.active == TRUE);
-
-    if (surface->compress_content) {
-	status = _cairo_output_stream_destroy (surface->content_stream.stream);
-	if (status)
-	    return status;
-
-	_cairo_output_stream_printf (surface->content_stream.mem_stream,
-				     "\r\n");
-    }
-    surface->output = surface->content_stream.old_output;
-    surface->content_stream.active = FALSE;
-    if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) {
-	group = _cairo_pdf_surface_write_memory_stream (surface,
-							surface->content_stream.mem_stream,
-							&surface->content_stream.resources,
-							FALSE);
-	if (group.id == 0)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	status = _cairo_pdf_surface_add_group_to_content_stream (surface, group);
-	if (status)
-	    return status;
-    }
-    surface->content_stream.active = FALSE;
-
-    return _cairo_output_stream_close (surface->content_stream.mem_stream);
-}
-
-static cairo_status_t
-_cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_close_content_stream (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.mem_stream) > GROUP_STREAM_LIMIT) {
-	status = _cairo_pdf_surface_stop_content_stream (surface);
-	if (status)
-	    return status;
-
-	status = _cairo_pdf_surface_start_content_stream (surface);
-	if (status)
-	    return status;
-    }
+    assert (surface->pdf_stream.active == TRUE);
+    assert (surface->group_stream.active == FALSE);
+
+    _cairo_output_stream_printf (surface->output, "Q\r\n");
+    status = _cairo_pdf_surface_close_stream (surface);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_update_object (surface, surface->content_resources);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n",
+				 surface->content_resources.id);
+    _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
+    _cairo_output_stream_printf (surface->output,
+				 "endobj\r\n");
 
     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_emit_font_subsets (surface);
+    cairo_status_t status, status2;
+
+    status = surface->base.status;
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = _cairo_pdf_surface_emit_font_subsets (surface);
 
     _cairo_pdf_surface_write_pages (surface);
 
     info = _cairo_pdf_surface_write_info (surface);
     if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     catalog = _cairo_pdf_surface_write_catalog (surface);
@@ -1214,55 +1173,75 @@ static cairo_status_t
 				 info.id);
 
     _cairo_output_stream_printf (surface->output,
 				 "startxref\r\n"
 				 "%ld\r\n"
 				 "%%%%EOF\r\n",
 				 offset);
 
+     _cairo_pdf_operators_fini (&surface->pdf_operators);
+
+    /* close any active streams still open due to fatal errors */
+    status2 = _cairo_pdf_surface_close_stream (surface);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
+
+    if (surface->group_stream.stream != NULL) {
+	status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
+	if (status == CAIRO_STATUS_SUCCESS)
+	    status = status2;
+    }
+    if (surface->group_stream.mem_stream != NULL) {
+	status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
+	if (status == CAIRO_STATUS_SUCCESS)
+	    status = status2;
+    }
+    if (surface->pdf_stream.active)
+	surface->output = surface->pdf_stream.old_output;
+    if (surface->group_stream.active)
+	surface->output = surface->group_stream.old_output;
+
+    /* and finish the pdf surface */
     status2 = _cairo_output_stream_destroy (surface->output);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
+    _cairo_pdf_surface_clear (surface);
+    _cairo_pdf_group_resources_fini (&surface->resources);
+
     _cairo_array_fini (&surface->objects);
     _cairo_array_fini (&surface->pages);
     _cairo_array_fini (&surface->rgb_linear_functions);
     _cairo_array_fini (&surface->alpha_linear_functions);
+    _cairo_array_fini (&surface->patterns);
+    _cairo_array_fini (&surface->smask_groups);
     _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;
     }
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_start_page (void *abstract_surface)
 {
     cairo_status_t status;
     cairo_pdf_surface_t *surface = abstract_surface;
 
-    surface->current_group = &surface->content_group;
-    status = _cairo_pdf_surface_start_content_stream (surface);
+    surface->has_fallback_images = FALSE;
+    _cairo_pdf_group_resources_clear (&surface->resources);
+    status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
     if (status)
 	return status;
 
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void *
 compress_dup (const void *data, unsigned long data_size,
 	      unsigned long *compressed_size)
 {
     void *compressed;
@@ -1373,16 +1352,17 @@ static cairo_status_t
 
     alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
     if (alpha_compressed == NULL) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_ALPHA;
     }
 
     *stream_ret = _cairo_pdf_surface_open_stream (surface,
+						  NULL,
                                                   FALSE,
 						  "   /Type /XObject\r\n"
 						  "   /Subtype /Image\r\n"
 						  "   /Width %d\r\n"
 						  "   /Height %d\r\n"
 						  "   /ColorSpace /DeviceGray\r\n"
 						  "   /BitsPerComponent %d\r\n"
 						  "   /Filter /FlateDecode\r\n",
@@ -1499,23 +1479,25 @@ static cairo_status_t
 				"   /Width %d\r\n"		\
 				"   /Height %d\r\n"		\
 				"   /ColorSpace /DeviceRGB\r\n"	\
 				"   /BitsPerComponent 8\r\n"	\
 				"   /Filter /FlateDecode\r\n"
 
     if (need_smask)
 	*image_ret = _cairo_pdf_surface_open_stream (surface,
+						     NULL,
                                                      FALSE,
 						     IMAGE_DICTIONARY
 						     "   /SMask %d 0 R\r\n",
 						     image->width, image->height,
 						     smask.id);
     else
 	*image_ret = _cairo_pdf_surface_open_stream (surface,
+						     NULL,
                                                      FALSE,
 						     IMAGE_DICTIONARY,
 						     image->width, image->height);
     if (image_ret->id == 0){
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_COMPRESSED;
     }
 
@@ -1572,129 +1554,94 @@ BAIL2:
     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_paginated_mode_t old_paginated_mode;
     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);
-    status = _cairo_pdf_surface_stop_content_stream (surface);
-    if (status)
-	return status;
-
-    _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;
+    old_paginated_mode = surface->paginated_mode;
     surface->width = meta_extents.width;
     surface->height = meta_extents.height;
+    /* Patterns are emitted after fallback images. The paginated mode
+     * needs to be set to _RENDER while the meta surface is replayed
+     * back to this surface.
+     */
+    surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
     cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
-
-    status = _cairo_pdf_surface_start_content_stream (surface);
+    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
+						  surface->cairo_to_pdf);
+
+    _cairo_pdf_group_resources_clear (&surface->resources);
+    status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
     if (status)
-	goto CLEANUP_GROUP;
-
+	return status;
+
+    *resource = surface->content;
     if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
 	if (status)
 	    goto CLEANUP_GROUP;
 
 	_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)
-	goto CLEANUP_GROUP;
-
-    status = _cairo_pdf_surface_stop_content_stream (surface);
-    if (status)
-	goto CLEANUP_GROUP;
-
-    status = _cairo_pdf_surface_open_group (surface);
+    status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
+						CAIRO_META_REGION_NATIVE);
+    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	goto CLEANUP_GROUP;
 
-    status = _cairo_pdf_surface_write_group_list (surface, &group);
-    if (status)
-	goto CLEANUP_GROUP;
-
-    status = _cairo_pdf_surface_close_group (surface, resource);
-    if (status)
-	goto CLEANUP_GROUP;
+    status = _cairo_pdf_surface_close_content_stream (surface);
 
  CLEANUP_GROUP:
-    surface->current_group = old_group;
     surface->width = old_width;
     surface->height = old_height;
+    surface->paginated_mode = old_paginated_mode;
     surface->cairo_to_pdf = old_cairo_to_pdf;
-
-    _cairo_pdf_group_element_array_finish (&group);
-    _cairo_array_fini (&group);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_start_content_stream (surface);
-    if (status)
-	return status;
-
-    _cairo_pdf_surface_pause_content_stream (surface);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-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;
+    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
+						  surface->cairo_to_pdf);
+
+    return status;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	 *surface,
-					 cairo_surface_pattern_t *pattern)
+_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
+					 cairo_pdf_pattern_t	*pdf_pattern)
 {
-    cairo_pdf_resource_t stream;
+    cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
     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 */
     int bbox_x, bbox_y;
 
-    _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);
 	if (status)
@@ -1805,35 +1752,38 @@ static cairo_status_t
 
     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, pattern_height);
     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
-    stream = _cairo_pdf_surface_open_stream (surface,
-					     FALSE,
-					     "   /BBox [0 0 %d %d]\r\n"
-					     "   /XStep %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 << /x%d %d 0 R >> >>\r\n",
-					     bbox_x, bbox_y,
-					     xstep, ystep,
-					     pdf_p2d.xx, pdf_p2d.yx,
-					     pdf_p2d.xy, pdf_p2d.yy,
-					     pdf_p2d.x0, pdf_p2d.y0,
-					     pattern_resource.id,
-					     pattern_resource.id);
-    if (stream.id == 0)
+    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
+    if (_cairo_pdf_surface_open_stream (surface,
+				        &pdf_pattern->pattern_res,
+					FALSE,
+					"   /PatternType 1\r\n"
+					"   /BBox [0 0 %d %d]\r\n"
+					"   /XStep %f\r\n"
+					"   /YStep %f\r\n"
+					"   /TilingType 1\r\n"
+					"   /PaintType 1\r\n"
+					"   /Matrix [ %f %f %f %f %f %f ]\r\n"
+					"   /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
+					bbox_x, bbox_y,
+					xstep, ystep,
+					pdf_p2d.xx, pdf_p2d.yx,
+					pdf_p2d.xy, pdf_p2d.yy,
+					pdf_p2d.x0, pdf_p2d.y0,
+					pattern_resource.id,
+					pattern_resource.id).id == 0)
+    {
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	if (extend == CAIRO_EXTEND_REFLECT) {
 	    _cairo_output_stream_printf (surface->output,
 					 "q 0 0 %d %d re W n /x%d Do Q\r\n"
 					 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n /x%d Do Q\r\n"
 					 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n /x%d Do Q\r\n"
 					 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n /x%d Do Q\r\n",
@@ -1856,23 +1806,16 @@ static cairo_status_t
 				     pattern_width, pattern_height,
 				     pattern_resource.id);
     }
 
     status = _cairo_pdf_surface_close_stream (surface);
     if (status)
 	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;
-    surface->emitted_pattern.alpha = 1.0;
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 typedef struct _cairo_pdf_color_stop {
     double offset;
     double color[4];
     cairo_pdf_resource_t resource;
 } cairo_pdf_color_stop_t;
@@ -1976,17 +1919,17 @@ cairo_pdf_surface_emit_alpha_linear_func
     status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
     *function = res;
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
-                                                unsigned int 	        n_stops,
+                                                unsigned int	        n_stops,
                                                 cairo_pdf_color_stop_t *stops,
                                                 cairo_bool_t	        is_alpha,
                                                 cairo_pdf_resource_t   *function)
 {
     cairo_pdf_resource_t res;
     unsigned int i;
     cairo_status_t status;
 
@@ -2023,36 +1966,36 @@ static cairo_status_t
                                  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");
+				 "]\r\n");
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Bounds [ ");
     for (i = 1; i < n_stops-1; i++)
         _cairo_output_stream_printf (surface->output,
 				     "%f ", stops[i].offset);
     _cairo_output_stream_printf (surface->output,
-		    		 "]\r\n");
+				 "]\r\n");
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Encode [ ");
     for (i = 1; i < n_stops; i++)
         _cairo_output_stream_printf (surface->output,
 				     "0 1 ");
     _cairo_output_stream_printf (surface->output,
-	    			 "]\r\n");
+				 "]\r\n");
 
     _cairo_output_stream_printf (surface->output,
-	    			 ">>\r\n"
+				 ">>\r\n"
 				 "endobj\r\n");
 
     *function = res;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 
@@ -2227,23 +2170,26 @@ static cairo_status_t
 				 ">>\r\n"
 				 "endobj\r\n");
 
     *function = res;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_pdf_resource_t
+static cairo_status_t
 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
-                                           cairo_pdf_resource_t  gradient_mask)
+					   cairo_pdf_resource_t  gstate_resource,
+					   cairo_pdf_resource_t  gradient_mask)
 {
-    cairo_pdf_resource_t xobj_resource, smask_resource, gstate_resource;
+    cairo_pdf_resource_t xobj_resource, smask_resource;
+    cairo_status_t status;
 
     xobj_resource = _cairo_pdf_surface_open_stream (surface,
+						    NULL,
                                                     surface->compress_content,
                                                     "   /Type /XObject\r\n"
                                                     "   /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 >>"
@@ -2256,85 +2202,83 @@ cairo_pdf_surface_emit_transparency_grou
                                                     "         /S /Transparency\r\n"
                                                     "         /CS /DeviceGray\r\n"
                                                     "      >>\r\n",
                                                     surface->width,
                                                     surface->height,
                                                     gradient_mask.id,
                                                     gradient_mask.id);
     if (xobj_resource.id == 0)
-	return xobj_resource;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_output_stream_printf (surface->output,
                                  "q\r\n"
                                  "/a0 gs\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);
 
-    if (_cairo_pdf_surface_close_stream (surface)) {
-	smask_resource.id = 0;
-	return smask_resource;
-    }
+     status = _cairo_pdf_surface_close_stream (surface);
+     if (status)
+	return status;
 
     smask_resource = _cairo_pdf_surface_new_object (surface);
     if (smask_resource.id == 0)
-	return smask_resource;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _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"
                                  ">>\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);
-    if (gstate_resource.id == 0)
-	return gstate_resource;
+    _cairo_pdf_surface_update_object (surface, gstate_resource);
 
     _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_resource.id,
                                  smask_resource.id);
 
-    return gstate_resource;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
-                                        cairo_linear_pattern_t *pattern)
+					cairo_pdf_pattern_t    *pdf_pattern)
 {
-    cairo_pdf_resource_t pattern_resource, smask;
+    cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern;
     cairo_pdf_resource_t color_function, alpha_function;
     double x1, y1, x2, y2;
     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;
     int repeat_begin = 0, repeat_end = 1;
 
-    extend = cairo_pattern_get_extend (&pattern->base.base);
-    _cairo_pdf_surface_pause_content_stream (surface);
+    assert (pattern->base.n_stops != 0);
+
+    extend = cairo_pattern_get_extend (pdf_pattern->pattern);
 
     pat_to_pdf = pattern->base.base.matrix;
     status = cairo_matrix_invert (&pat_to_pdf);
     /* 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);
     first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
@@ -2419,32 +2363,29 @@ static cairo_status_t
 								 &alpha_function,
 								 repeat_begin,
 								 repeat_end);
 	    if (status)
 		return status;
 	}
     }
 
-    pattern_resource = _cairo_pdf_surface_new_object (surface);
-    if (pattern_resource.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
+    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
     _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,
+				 pdf_pattern->pattern_res.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) {
@@ -2455,20 +2396,20 @@ static cairo_status_t
                                      "         /Extend [ false false ]\r\n");
     }
 
     _cairo_output_stream_printf (surface->output,
                                  "      >>\r\n"
                                  ">>\r\n"
                                  "endobj\r\n");
 
-    if (alpha_function.id == 0) {
-         surface->emitted_pattern.smask.id = 0;
-    } else {
-        cairo_pdf_resource_t mask_resource;
+    if (alpha_function.id != 0) {
+	cairo_pdf_resource_t mask_resource;
+
+	assert (pdf_pattern->gstate_res.id != 0);
 
         /* Create pattern for SMask. */
         mask_resource = _cairo_pdf_surface_new_object (surface);
 	if (mask_resource.id == 0)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
         _cairo_output_stream_printf (surface->output,
                                      "%d 0 obj\r\n"
@@ -2500,45 +2441,40 @@ static cairo_status_t
         _cairo_output_stream_printf (surface->output,
                                      "      >>\r\n"
                                      ">>\r\n"
                                      "endobj\r\n");
         status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
         if (status)
             return status;
 
-        smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
-	if (smask.id == 0)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-        surface->emitted_pattern.smask = smask;
+	status = cairo_pdf_surface_emit_transparency_group (surface,
+						            pdf_pattern->gstate_res,
+							    mask_resource);
+	if (status)
+	    return status;
     }
 
-    surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR;
-    surface->emitted_pattern.pattern = pattern_resource;
-    surface->emitted_pattern.alpha = 1.0;
-
-    _cairo_pdf_surface_resume_content_stream (surface);
-
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t    *surface,
-                                        cairo_radial_pattern_t *pattern)
+					cairo_pdf_pattern_t    *pdf_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);
-    _cairo_pdf_surface_pause_content_stream (surface);
+    cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern;
+
+    assert (pattern->base.n_stops != 0);
+
+    extend = cairo_pattern_get_extend (pdf_pattern->pattern);
 
     status = _cairo_pdf_surface_emit_pattern_stops (surface,
                                                     &pattern->base,
                                                     &color_function,
                                                     &alpha_function);
     if (status)
 	return status;
 
@@ -2550,31 +2486,29 @@ static cairo_status_t
     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);
 
-    pattern_resource = _cairo_pdf_surface_new_object (surface);
-    if (pattern_resource.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
 
     _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 3\r\n"
                                  "         /ColorSpace /DeviceRGB\r\n"
                                  "         /Coords [ %f %f %f %f %f %f ]\r\n"
                                  "         /Function %d 0 R\r\n",
-                                 pattern_resource.id,
+				 pdf_pattern->pattern_res.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, r1, x2, y2, r2,
                                  color_function.id);
 
     if (extend == CAIRO_EXTEND_PAD) {
         _cairo_output_stream_printf (surface->output,
@@ -2584,22 +2518,22 @@ static cairo_status_t
                                      "         /Extend [ false false ]\r\n");
     }
 
     _cairo_output_stream_printf (surface->output,
                                  "      >>\r\n"
                                  ">>\r\n"
                                  "endobj\r\n");
 
-    if (alpha_function.id == 0) {
-        surface->emitted_pattern.smask.id = 0;
-    } else {
-        cairo_pdf_resource_t mask_resource;
-
-        /* Create pattern for SMask. */
+    if (alpha_function.id != 0) {
+	cairo_pdf_resource_t mask_resource;
+
+	assert (pdf_pattern->gstate_res.id != 0);
+
+	/* Create pattern for SMask. */
         mask_resource = _cairo_pdf_surface_new_object (surface);
 	if (mask_resource.id == 0)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
         _cairo_output_stream_printf (surface->output,
                                      "%d 0 obj\r\n"
                                      "<< /Type /Pattern\r\n"
                                      "   /PatternType 2\r\n"
@@ -2624,124 +2558,117 @@ static cairo_status_t
                                          "         /Extend [ false false ]\r\n");
         }
 
         _cairo_output_stream_printf (surface->output,
                                      "      >>\r\n"
                                      ">>\r\n"
                                      "endobj\r\n");
 
-        smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
-	if (smask.id == 0)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-        surface->emitted_pattern.smask = smask;
+	status = cairo_pdf_surface_emit_transparency_group (surface,
+						            pdf_pattern->gstate_res,
+							    mask_resource);
+	if (status)
+	    return status;
     }
 
-    surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL;
-    surface->emitted_pattern.pattern = pattern_resource;
-    surface->emitted_pattern.alpha = 1.0;
-
-     _cairo_pdf_surface_resume_content_stream (surface);
-
-     return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
+_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
 {
-    switch (pattern->type) {
+    switch (pdf_pattern->pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	_cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
-        return CAIRO_STATUS_SUCCESS;
+	ASSERT_NOT_REACHED;
+	break;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
-	return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
 
     case CAIRO_PATTERN_TYPE_LINEAR:
-	return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
 
     case CAIRO_PATTERN_TYPE_RADIAL:
-	return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+	return _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
     }
 
     ASSERT_NOT_REACHED;
     return _cairo_error (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_pattern_t     *pattern,
+				   cairo_pdf_resource_t pattern_res,
+				   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) {
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *) pattern;
+
+	status = _cairo_pdf_surface_add_alpha (surface, solid_pattern->color.alpha, &alpha);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output,
-                                     "%f %f %f ",
-                                     surface->emitted_pattern.red,
-                                     surface->emitted_pattern.green,
-                                     surface->emitted_pattern.blue);
-
-        if (is_stroke)
+				     "q %f %f %f ",
+				     solid_pattern->color.red,
+				     solid_pattern->color.green,
+				     solid_pattern->color.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",
                                      alpha);
     } else {
-        if (is_stroke) {
-            _cairo_output_stream_printf (surface->output,
-                                         "/Pattern CS /p%d SCN ",
-                                         surface->emitted_pattern.pattern.id);
-        } else {
-            _cairo_output_stream_printf (surface->output,
-                                         "/Pattern cs /p%d scn ",
-                                         surface->emitted_pattern.pattern.id);
-        }
-        status = _cairo_pdf_surface_add_pattern (surface, surface->emitted_pattern.pattern);
+	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
 	if (status)
 	    return status;
 
-        _cairo_output_stream_printf (surface->output,
-                                     "/a%d gs ",
-                                     alpha);
-
-        _cairo_output_stream_printf (surface->output, "\r\n");
+	if (is_stroke) {
+	    _cairo_output_stream_printf (surface->output,
+					 "q /Pattern CS /p%d SCN ",
+					 pattern_res.id);
+	} else {
+	    _cairo_output_stream_printf (surface->output,
+					 "q /Pattern cs /p%d scn ",
+					 pattern_res.id);
+	}
+	_cairo_output_stream_printf (surface->output,
+				     "/a%d gs\r\n",
+				     alpha);
     }
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
-static cairo_int_status_t
-_cairo_pdf_surface_copy_page (void *abstract_surface)
+static void
+_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
 {
-    cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_int_status_t status;
-
-    status = _cairo_pdf_surface_stop_content_stream (surface);
-    if (status)
-	return status;
-
-    return _cairo_pdf_surface_write_page (surface);
+    _cairo_output_stream_printf (surface->output, "Q\r\n");
 }
 
 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;
 
-    status = _cairo_pdf_surface_stop_content_stream (surface);
+    status = _cairo_pdf_surface_close_content_stream (surface);
     if (status)
 	return status;
 
     status = _cairo_pdf_surface_write_page (surface);
     if (status)
 	return status;
 
     _cairo_pdf_surface_clear (surface);
@@ -2763,156 +2690,31 @@ static cairo_int_status_t
      * may need to come up with a better interface for get_size.
      */
     rectangle->width  = (int) ceil (surface->width);
     rectangle->height = (int) ceil (surface->height);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-typedef struct _pdf_path_info {
-    cairo_output_stream_t   *output;
-    cairo_matrix_t	    *cairo_to_pdf;
-    cairo_matrix_t	    *ctm_inverse;
-} pdf_path_info_t;
-
-static cairo_status_t
-_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
-{
-    pdf_path_info_t *info = closure;
-    double x = _cairo_fixed_to_double (point->x);
-    double y = _cairo_fixed_to_double (point->y);
-
-    if (info->cairo_to_pdf)
-        cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
-    if (info->ctm_inverse)
-	cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
-
-    _cairo_output_stream_printf (info->output,
-				 "%f %f m ", x, y);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
-{
-    pdf_path_info_t *info = closure;
-    double x = _cairo_fixed_to_double (point->x);
-    double y = _cairo_fixed_to_double (point->y);
-
-    if (info->cairo_to_pdf)
-        cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
-    if (info->ctm_inverse)
-	cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
-
-    _cairo_output_stream_printf (info->output,
-				 "%f %f l ", x, y);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_curve_to (void          *closure,
-			  cairo_point_t *b,
-			  cairo_point_t *c,
-			  cairo_point_t *d)
-{
-    pdf_path_info_t *info = closure;
-    double bx = _cairo_fixed_to_double (b->x);
-    double by = _cairo_fixed_to_double (b->y);
-    double cx = _cairo_fixed_to_double (c->x);
-    double cy = _cairo_fixed_to_double (c->y);
-    double dx = _cairo_fixed_to_double (d->x);
-    double dy = _cairo_fixed_to_double (d->y);
-
-    if (info->cairo_to_pdf) {
-        cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
-        cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
-        cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
-    }
-    if (info->ctm_inverse) {
-	cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
-	cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
-	cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
-    }
-
-    _cairo_output_stream_printf (info->output,
-				 "%f %f %f %f %f %f c ",
-				 bx, by, cx, cy, dx, dy);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_close_path (void *closure)
-{
-    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_error (CAIRO_STATUS_NO_MEMORY);
-
-	status = _cairo_path_fixed_init_copy (elem.clip_path, path);
-	if (status) {
-	    _cairo_path_fixed_destroy (elem.clip_path);
-	    return status;
-	}
-    }
-    elem.fill_rule = fill_rule;
-
-    status = _cairo_pdf_surface_stop_content_stream (surface);
-    if (status) {
-	if (elem.clip_path != NULL)
-	    _cairo_path_fixed_destroy (elem.clip_path);
-	return status;
-    }
-
-    status = _cairo_array_append (surface->current_group, &elem);
-    if (status) {
-	if (elem.clip_path != NULL)
-	    _cairo_path_fixed_destroy (elem.clip_path);
-	return status;
-    }
-
-    status = _cairo_pdf_surface_start_content_stream (surface);
-    if (status)
-	return status;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 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;
 
-    return _cairo_pdf_surface_add_clip (surface, path, fill_rule);
+    if (path == NULL) {
+	_cairo_output_stream_printf (surface->output, "Q q\r\n");
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    return _cairo_pdf_operators_clip (&surface->pdf_operators, 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);
 
@@ -2976,32 +2778,41 @@ static void
 static cairo_int_status_t
 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset,
                                            cairo_bool_t                  is_composite,
 					   cairo_pdf_resource_t         *stream)
 {
     const cairo_scaled_font_backend_t *backend;
     unsigned int i, num_bfchar;
+    cairo_int_status_t status;
 
     stream->id = 0;
     if (font_subset->to_unicode == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) {
+    status = _cairo_truetype_create_glyph_to_unicode_map (font_subset);
+    if (status) {
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+
         backend = font_subset->scaled_font->backend;
         if (backend->map_glyphs_to_unicode == NULL)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
-        backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset);
+        status = backend->map_glyphs_to_unicode (font_subset->scaled_font,
+		                                 font_subset);
+	if (status)
+	    return status;
     }
 
     *stream = _cairo_pdf_surface_open_stream (surface,
-					     surface->compress_content,
-					     NULL);
+					      NULL,
+					      surface->compress_content,
+					      NULL);
     if (stream->id == 0)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_output_stream_printf (surface->output,
                                  "/CIDInit /ProcSet findresource begin\r\n"
                                  "12 dict begin\r\n"
                                  "begincmap\r\n"
                                  "/CIDSystemInfo\r\n"
@@ -3066,16 +2877,22 @@ static cairo_status_t
     cairo_pdf_resource_t stream, descriptor, cidfont_dict;
     cairo_pdf_resource_t subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
     unsigned long compressed_length;
     char *compressed;
     unsigned int i;
     cairo_status_t status;
 
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    if (subset_resource.id == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     compressed = compress_dup (subset->data, subset->data_length, &compressed_length);
     if (compressed == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     stream = _cairo_pdf_surface_new_object (surface);
     if (stream.id == 0) {
 	free (compressed);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -3157,19 +2974,16 @@ 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_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",
@@ -3243,16 +3057,21 @@ static cairo_status_t
 {
     cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
     cairo_status_t status;
     unsigned long length, compressed_length;
     char *compressed;
     unsigned int i;
 
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    if (subset_resource.id == 0)
+	return CAIRO_STATUS_SUCCESS;
 
     /* We ignore the zero-trailer and set Length3 to 0. */
     length = subset->header_length + subset->data_length;
     compressed = compress_dup (subset->data, length, &compressed_length);
     if (compressed == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     stream = _cairo_pdf_surface_new_object (surface);
@@ -3311,19 +3130,16 @@ 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_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"
@@ -3362,17 +3178,17 @@ static cairo_status_t
 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
 {
     cairo_status_t status;
     cairo_type1_subset_t subset;
     char name[64];
 
     snprintf (name, sizeof name, "CairoFont-%d-%d",
- 	      font_subset->font_id, font_subset->subset_id);
+	      font_subset->font_id, font_subset->subset_id);
     status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
     if (status)
 	return status;
 
     status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
 
     _cairo_type1_subset_fini (&subset);
     return status;
@@ -3409,16 +3225,22 @@ static cairo_status_t
     cairo_pdf_resource_t subset_resource, to_unicode_stream;
     cairo_status_t status;
     cairo_pdf_font_t font;
     cairo_truetype_subset_t subset;
     unsigned long compressed_length;
     char *compressed;
     unsigned int i;
 
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    if (subset_resource.id == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     status = _cairo_truetype_subset_init (&subset, font_subset);
     if (status)
 	return status;
 
     compressed = compress_dup (subset.data, subset.data_length,
 			       &compressed_length);
     if (compressed == NULL) {
 	_cairo_truetype_subset_fini (&subset);
@@ -3515,19 +3337,16 @@ 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_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",
@@ -3550,70 +3369,16 @@ static cairo_status_t
     status = _cairo_array_append (&surface->fonts, &font);
 
     _cairo_truetype_subset_fini (&subset);
 
     return status;
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_emit_outline_glyph (cairo_pdf_surface_t	*surface,
-				       cairo_scaled_font_t	*scaled_font,
-				       unsigned long		 glyph_index,
-				       cairo_pdf_resource_t	*glyph_ret)
-{
-    cairo_scaled_glyph_t *scaled_glyph;
-    pdf_path_info_t info;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    status = _cairo_scaled_glyph_lookup (scaled_font,
-					 glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_METRICS|
-					 CAIRO_SCALED_GLYPH_INFO_PATH,
-					 &scaled_glyph);
-    if (status)
-	return status;
-
-    *glyph_ret = _cairo_pdf_surface_open_stream (surface,
-						 surface->compress_content,
-						 NULL);
-    if (glyph_ret->id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _cairo_output_stream_printf (surface->output,
-				 "0 0 %f %f %f %f d1\r\n",
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
-				 -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
-
-    info.output = surface->output;
-    info.cairo_to_pdf = &surface->cairo_to_pdf;
-    info.ctm_inverse = NULL;
-
-    status = _cairo_path_fixed_interpret (scaled_glyph->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);
-    if (status) {
-	/* ignore status return as we are on the error path... */
-	_cairo_pdf_surface_close_stream (surface);
-	return status;
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 " f");
-
-    return _cairo_pdf_surface_close_stream (surface);
-}
-
-static cairo_int_status_t
 _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t	*surface,
 				      cairo_scaled_font_t	*scaled_font,
 				      unsigned long		 glyph_index,
 				      cairo_pdf_resource_t	*glyph_ret,
                                       cairo_box_t               *bbox,
                                       double                    *width)
 {
     cairo_scaled_glyph_t *scaled_glyph;
@@ -3635,21 +3400,23 @@ static cairo_int_status_t
     y_advance = scaled_glyph->metrics.y_advance;
     cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
     *bbox = scaled_glyph->bbox;
     *width = x_advance;
 
     image = scaled_glyph->surface;
     if (image->format != CAIRO_FORMAT_A1) {
 	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	if (cairo_surface_status (&image->base))
-	    return cairo_surface_status (&image->base);
+	status = cairo_surface_status (&image->base);
+	if (status)
+	    return status;
     }
 
     *glyph_ret = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
 						 surface->compress_content,
 						 NULL);
     if (glyph_ret->id == 0) {
 	if (image != scaled_glyph->surface)
 	    cairo_surface_destroy (&image->base);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
@@ -3692,88 +3459,79 @@ static cairo_int_status_t
     status = _cairo_pdf_surface_close_stream (surface);
 
     if (image != scaled_glyph->surface)
 	cairo_surface_destroy (&image->base);
 
     return status;
 }
 
-static void
-_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t	*surface,
-			       cairo_scaled_font_t	*scaled_font,
-			       unsigned long		 glyph_index,
-			       cairo_pdf_resource_t	*glyph_ret,
-                               cairo_box_t              *bbox,
-                               double                   *width)
-{
-    cairo_status_t status;
-
-    status = _cairo_pdf_surface_emit_outline_glyph (surface,
-						    scaled_font,
-						    glyph_index,
-						    glyph_ret);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
-						       scaled_font,
-						       glyph_index,
-						       glyph_ret,
-                                                       bbox,
-                                                       width);
-
-    if (status)
-	status = _cairo_surface_set_error (&surface->base, status);
-}
-
 static cairo_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
     cairo_matrix_t matrix;
     double *widths;
     unsigned int i;
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
 
+    if (font_subset->num_glyphs == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
+							    font_subset->font_id,
+							    font_subset->subset_id);
+    if (subset_resource.id == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
     if (glyphs == NULL)
-	return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
     if (widths == NULL) {
         free (glyphs);
-	return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
-	_cairo_pdf_surface_emit_glyph (surface,
-				       font_subset->scaled_font,
-				       font_subset->glyphs[i],
-				       &glyphs[i],
-                                       &bbox,
-                                       &widths[i]);
+        status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
+                                                       font_subset->scaled_font,
+                                                       font_subset->glyphs[i],
+                                                       &glyphs[i],
+                                                       &bbox,
+                                                       &widths[i]);
+	if (status)
+	    break;
+
         if (i == 0) {
             font_bbox.p1.x = bbox.p1.x;
             font_bbox.p1.y = bbox.p1.y;
             font_bbox.p2.x = bbox.p2.x;
             font_bbox.p2.y = bbox.p2.y;
         } else {
             if (bbox.p1.x < font_bbox.p1.x)
                 font_bbox.p1.x = bbox.p1.x;
             if (bbox.p1.y < font_bbox.p1.y)
                 font_bbox.p1.y = bbox.p1.y;
             if (bbox.p2.x > font_bbox.p2.x)
                 font_bbox.p2.x = bbox.p2.x;
             if (bbox.p2.y > font_bbox.p2.y)
                 font_bbox.p2.y = bbox.p2.y;
         }
     }
+    if (status) {
+	free (glyphs);
+	free (widths);
+	return status;
+    }
 
     encoding = _cairo_pdf_surface_new_object (surface);
     if (encoding.id == 0) {
 	free (glyphs);
 	free (widths);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
@@ -3812,19 +3570,16 @@ static cairo_status_t
     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 	                                                font_subset, FALSE,
 							&to_unicode_stream);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
 	free (widths);
 	return status;
     }
 
-    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"
@@ -3986,158 +3741,343 @@ 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_pdf_surface_write_mask_group (cairo_pdf_surface_t	*surface,
+				     cairo_pdf_smask_group_t	*group)
 {
-    const char *pdf_operator;
-
-    if (path == NULL) {
-	_cairo_output_stream_printf (surface->output, "Q q\r\n");
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    if (! path->has_current_point) {
-	/* construct an empty path */
-	_cairo_output_stream_printf (surface->output, "0 0 m ");
+    cairo_pdf_resource_t mask_group;
+    cairo_pdf_resource_t smask;
+    cairo_pdf_smask_group_t *smask_group;
+    cairo_pdf_resource_t pattern_res, gstate_res;
+    cairo_status_t status;
+
+    /* Create mask group */
+    status = _cairo_pdf_surface_open_group (surface, NULL);
+    if (status)
+	return status;
+
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res);
+    if (status)
+	return status;
+
+    if (gstate_res.id != 0) {
+	smask_group = _cairo_pdf_surface_create_smask_group (surface);
+	if (smask_group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	smask_group->operation = PDF_PAINT;
+	smask_group->source = cairo_pattern_reference (group->mask);
+	smask_group->source_res = pattern_res;
+	status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (smask_group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
+	if (status)
+	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     gstate_res.id,
+				     smask_group->group_res.id);
     } else {
-	pdf_path_info_t info;
-	cairo_status_t status;
-
-	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);
+	status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
+	if (status)
+	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "0 0 %f %f re f\r\n",
+				     surface->width, surface->height);
+
+	_cairo_pdf_surface_unselect_pattern (surface);
+    }
+
+    status = _cairo_pdf_surface_close_group (surface, &mask_group);
+    if (status)
+	return status;
+
+    /* Create source group */
+    status = _cairo_pdf_surface_open_group (surface, &group->source_res);
+    if (status)
+	return status;
+
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res);
+    if (status)
+	return status;
+
+    if (gstate_res.id != 0) {
+	smask_group = _cairo_pdf_surface_create_smask_group (surface);
+	if (smask_group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	smask_group->operation = PDF_PAINT;
+	smask_group->source = cairo_pattern_reference (group->source);
+	smask_group->source_res = pattern_res;
+	status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (smask_group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
+	if (status)
+	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "q /s%d gs /x%d Do Q\r\n",
+				     gstate_res.id,
+				     smask_group->group_res.id);
+    } else {
+	status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
 	if (status)
 	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "0 0 %f %f re f\r\n",
+				     surface->width, surface->height);
+
+	_cairo_pdf_surface_unselect_pattern (surface);
     }
 
-    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;
-    }
+    status = _cairo_pdf_surface_close_group (surface, NULL);
+    if (status)
+	return status;
+
+    /* Create an smask based on the alpha component of mask_group */
+    smask = _cairo_pdf_surface_new_object (surface);
+    if (smask.id == 0)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_output_stream_printf (surface->output,
-				 "%s n\r\n",
-				 pdf_operator);
+				 "%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 */
+    _cairo_pdf_surface_update_object (surface, group->group_res);
+    _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",
+				 group->group_res.id,
+				 smask.id);
+
+    return _cairo_output_stream_get_status (surface->output);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
+				      cairo_pdf_smask_group_t *group)
+{
+    cairo_status_t status;
+
+    /* _mask is a special case that requires two groups - source
+     * and mask as well as a smask and gstate dictionary */
+    if (group->operation == PDF_MASK)
+	return _cairo_pdf_surface_write_mask_group (surface, group);
+
+    status = _cairo_pdf_surface_open_group (surface, &group->group_res);
+    if (status)
+	return status;
+
+    status = _cairo_pdf_surface_select_pattern (surface,
+						group->source,
+						group->source_res,
+						group->operation == PDF_STROKE);
+    if (status)
+	return status;
+
+    switch (group->operation) {
+    case PDF_PAINT:
+	_cairo_output_stream_printf (surface->output,
+				     "0 0 %f %f re f\r\n",
+				     surface->width, surface->height);
+	break;
+    case PDF_MASK:
+	ASSERT_NOT_REACHED;
+	break;
+    case PDF_FILL:
+	status = _cairo_pdf_operators_fill (&surface->pdf_operators,
+					    &group->path,
+					    group->fill_rule);
+	break;
+    case PDF_STROKE:
+	status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
+					     &group->path,
+					     group->style,
+					     &group->ctm,
+					     &group->ctm_inverse);
+	break;
+    case PDF_SHOW_GLYPHS:
+	status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
+						   group->glyphs,
+						   group->num_glyphs,
+						   group->scaled_font);
+	break;
+    }
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_unselect_pattern (surface);
+
+    return _cairo_pdf_surface_close_group (surface, NULL);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
+{
+    cairo_pdf_pattern_t pattern;
+    cairo_pdf_smask_group_t *group;
+    int pattern_index, group_index;
+    cairo_status_t status;
+
+    /* Writing out PDF_MASK groups will cause additional smask groups
+     * to be appended to surface->smask_groups. Additional patterns
+     * may also be appended to surface->patterns.
+     *
+     * Writing meta surface patterns will cause additional patterns
+     * and groups to be appended.
+     */
+    pattern_index = 0;
+    group_index = 0;
+    while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) ||
+	   (group_index < _cairo_array_num_elements (&surface->smask_groups)))
+    {
+	for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
+	    _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
+	    status = _cairo_pdf_surface_write_smask_group (surface, group);
+	    if (status)
+		return status;
+	}
+
+	for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) {
+	    _cairo_array_copy_element (&surface->patterns, pattern_index, &pattern);
+	    status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
+	    if (status)
+		return status;
+	}
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
 {
+    cairo_pdf_resource_t page, knockout, res;
     cairo_status_t status;
-    cairo_pdf_resource_t page;
-    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;
-
-    status = _cairo_pdf_surface_open_group (surface);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_write_group_list (surface, &surface->content_group);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_close_group (surface, &content_group);
-    if (status)
-	return status;
-
-    if (has_fallback_images) {
-	status = _cairo_pdf_surface_open_knockout_group (surface, &content_group);
+    int i, len;
+
+    _cairo_pdf_group_resources_clear (&surface->resources);
+    if (surface->has_fallback_images) {
+	status = _cairo_pdf_surface_open_knockout_group (surface);
 	if (status)
 	    return status;
 
-	status = _cairo_pdf_surface_write_group_list (surface, &surface->knockout_group);
+	len = _cairo_array_num_elements (&surface->knockout_group);
+	for (i = 0; i < len; i++) {
+	    _cairo_array_copy_element (&surface->knockout_group, i, &res);
+	    _cairo_output_stream_printf (surface->output,
+					 "/x%d Do\r\n",
+					 res.id);
+	    status = _cairo_pdf_surface_add_xobject (surface, res);
+	    if (status)
+		return status;
+	}
+	_cairo_output_stream_printf (surface->output,
+				     "/x%d Do\r\n",
+				     surface->content.id);
+	status = _cairo_pdf_surface_add_xobject (surface, surface->content);
 	if (status)
 	    return status;
 
-	status = _cairo_pdf_surface_close_group (surface, &knockout_group);
+	status = _cairo_pdf_surface_close_group (surface, &knockout);
+	if (status)
+	    return status;
+
+	_cairo_pdf_group_resources_clear (&surface->resources);
+	status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, FALSE);
+	if (status)
+	    return status;
+
+	_cairo_output_stream_printf (surface->output,
+				     "/x%d Do\r\n",
+				     knockout.id);
+	status = _cairo_pdf_surface_add_xobject (surface, knockout);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_surface_close_content_stream (surface);
 	if (status)
 	    return status;
     }
 
-    page_content = _cairo_pdf_surface_open_stream (surface,
-						   FALSE,
-						   "   /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);
-    if (page_content.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _cairo_output_stream_printf (surface->output,
-				 "/x%d Do\r\n",
-				 has_fallback_images ? knockout_group.id : content_group.id);
-    status = _cairo_pdf_surface_close_stream (surface);
-    if (status)
-	return status;
-
     page = _cairo_pdf_surface_new_object (surface);
     if (page.id == 0)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Page\r\n"
 				 "   /Parent %d 0 R\r\n"
 				 "   /MediaBox [ 0 0 %f %f ]\r\n"
-				 "   /Contents [ %d 0 R ]\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"
+				 "   /Resources %d 0 R\r\n"
 				 ">>\r\n"
 				 "endobj\r\n",
 				 page.id,
 				 surface->pages_resource.id,
 				 surface->width,
 				 surface->height,
-				 page_content.id,
-				 has_fallback_images ? knockout_group.id : content_group.id,
-				 has_fallback_images ? knockout_group.id : content_group.id);
+				 surface->content.id,
+				 surface->content_resources.id);
 
     status = _cairo_array_append (&surface->pages, &page);
     if (status)
 	return status;
 
+    status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
+    if (status)
+	return status;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
 {
     cairo_extend_t extend;
 
@@ -4228,771 +4168,436 @@ static cairo_int_status_t
 				      cairo_pattern_t      *pattern)
 {
     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 (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) {
 	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_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)
+    if (op == CAIRO_OPERATOR_OVER)
 	return CAIRO_STATUS_SUCCESS;
 
+    /* The SOURCE operator is only if there is nothing painted
+     * underneath. */
+    if (op == CAIRO_OPERATOR_SOURCE)
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+
     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;
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface,
-				 cairo_operator_t op)
+_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status;
 
-    if (op == CAIRO_OPERATOR_OVER)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (op == CAIRO_OPERATOR_SOURCE) {
-	surface->current_group = &surface->knockout_group;
-	status = _cairo_pdf_surface_stop_content_stream (surface);
-	if (status)
-	    return status;
-
-	status = _cairo_pdf_surface_start_content_stream (surface);
-	if (status)
-	    return status;
-
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    status = _cairo_pdf_surface_close_content_stream (surface);
+    if (status)
+	return status;
+
+    status = _cairo_array_append (&surface->knockout_group, &surface->content);
+    if (status)
+	return status;
+
+    surface->has_fallback_images = TRUE;
+    _cairo_pdf_group_resources_clear (&surface->resources);
+    return _cairo_pdf_surface_open_content_stream (surface,
+						   &surface->content,
+						   TRUE);
 }
 
 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 smask_group = {0}; /* squelch bogus compiler warning */
     cairo_status_t status;
-
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    cairo_pdf_smask_group_t *group;
+    cairo_pdf_resource_t pattern_res, gstate_res;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
+    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+	status = _cairo_pdf_surface_start_fallback (surface);
+	if (status)
+	    return status;
+    }
 
     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) {
-	_cairo_pdf_surface_pause_content_stream (surface);
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "q ");
-    }
-
-    status = _cairo_pdf_surface_select_pattern (surface, FALSE);
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
 
-    _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) {
-	status = _cairo_pdf_surface_close_group (surface, &smask_group);
+    if (gstate_res.id != 0) {
+	group = _cairo_pdf_surface_create_smask_group (surface);
+	if (group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	group->operation = PDF_PAINT;
+	group->source = cairo_pattern_reference (source);
+	group->source_res = pattern_res;
+	status = _cairo_pdf_surface_add_smask_group (surface, group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_resume_content_stream (surface);
+	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+	if (status)
+	    return status;
+
 	_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);
+				     gstate_res.id,
+				     group->group_res.id);
+    } else {
+	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "Q\r\n");
+
+	_cairo_output_stream_printf (surface->output,
+				     "0 0 %f %f re f\r\n",
+				     surface->width, surface->height);
+
+	_cairo_pdf_surface_unselect_pattern (surface);
     }
 
-    status = _cairo_output_stream_get_status (surface->output);
-    if (status)
-        return status;
-
-    return _cairo_pdf_surface_check_content_stream_size (surface);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 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;
-    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_pdf_smask_group_t *group;
     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;
+    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+	status = _cairo_pdf_surface_start_fallback (surface);
+	if (status)
+	    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)
+    group = _cairo_pdf_surface_create_smask_group (surface);
+    if (group == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    group->operation = PDF_MASK;
+    group->source = cairo_pattern_reference (source);
+    group->mask = cairo_pattern_reference (mask);
+    group->source_res = _cairo_pdf_surface_new_object (surface);
+    if (group->source_res.id == 0) {
+	_cairo_pdf_smask_group_destroy (group);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    status = _cairo_pdf_surface_add_smask_group (surface, group);
+    if (status) {
+	_cairo_pdf_smask_group_destroy (group);
 	return status;
-
-    _cairo_pdf_surface_pause_content_stream (surface);
-
-    status = _cairo_pdf_surface_open_group (surface);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_select_pattern (surface, FALSE);
-    if (status)
-	return status;
-
-    _cairo_output_stream_printf (surface->output,
-				 "0 0 %f %f re f\r\n",
-				 surface->width, surface->height);
-    status = _cairo_pdf_surface_close_group (surface, &mask_group);
+    }
+
+    status = _cairo_pdf_surface_add_smask (surface, group->group_res);
     if (status)
 	return status;
 
-    if (surface->emitted_pattern.smask.id != 0) {
-	group = mask_group;
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-
-	_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;
-
-	status = _cairo_pdf_surface_close_group (surface, &mask_group);
-	if (status)
-	    return status;
-    }
-
-    /* Create source group */
-    status = _cairo_pdf_surface_emit_pattern (surface, source);
-    if (status)
-	return status;
-
-    _cairo_pdf_surface_pause_content_stream (surface);
-
-    status = _cairo_pdf_surface_open_group (surface);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_select_pattern (surface, FALSE);
+    status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
     if (status)
 	return status;
 
     _cairo_output_stream_printf (surface->output,
-				 "0 0 %f %f re f\r\n",
-				 surface->width, surface->height);
-    status = _cairo_pdf_surface_close_group (surface, &source_group);
-    if (status)
-	return status;
-
-    if (surface->emitted_pattern.smask.id != 0) {
-	group = source_group;
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-
-	_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;
-
-	status =_cairo_pdf_surface_close_group (surface, &source_group);
-	if (status)
-	    return status;
-    }
-
-    /* Create an smask based on the alpha component of mask_group */
-    smask = _cairo_pdf_surface_new_object (surface);
-    if (smask.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _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);
-    if (gstate.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _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;
-    case CAIRO_LINE_CAP_ROUND:
-	return 1;
-    case CAIRO_LINE_CAP_SQUARE:
-	return 2;
-    default:
-	ASSERT_NOT_REACHED;
-	return 0;
-    }
-}
-
-static int
-_cairo_pdf_line_join (cairo_line_join_t join)
-{
-    switch (join) {
-    case CAIRO_LINE_JOIN_MITER:
-	return 0;
-    case CAIRO_LINE_JOIN_ROUND:
-	return 1;
-    case CAIRO_LINE_JOIN_BEVEL:
-	return 2;
-    default:
-	ASSERT_NOT_REACHED;
-	return 0;
-    }
-}
-
-static cairo_status_t
-_cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t	*surface,
-				      cairo_stroke_style_t	*style)
-{
-    _cairo_output_stream_printf (surface->output,
-				 "%f w\r\n",
-				 style->line_width);
-
-    _cairo_output_stream_printf (surface->output,
-				 "%d J\r\n",
-				 _cairo_pdf_line_cap (style->line_cap));
-
-    _cairo_output_stream_printf (surface->output,
-				 "%d j\r\n",
-				 _cairo_pdf_line_join (style->line_join));
-
-    if (style->num_dashes) {
-	unsigned int d;
-	_cairo_output_stream_printf (surface->output, "[");
-	for (d = 0; d < style->num_dashes; d++)
-	    _cairo_output_stream_printf (surface->output, " %f", style->dash[d]);
-	_cairo_output_stream_printf (surface->output, "] %f d\r\n",
-				     style->dash_offset);
-    } else {
-	_cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n");
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 "%f M ",
-				 style->miter_limit);
+				 group->group_res.id,
+				 group->source_res.id);
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
 _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
-    pdf_path_info_t info;
     cairo_status_t status;
-    cairo_matrix_t m;
+    cairo_pdf_smask_group_t *group;
+    cairo_pdf_resource_t pattern_res, gstate_res;
 
     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) {
-	_cairo_pdf_surface_pause_content_stream (surface);
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "q ");
-    }
-
-    status = _cairo_pdf_surface_select_pattern (surface, TRUE);
-    if (status)
-	return status;
-
-    status = _cairo_pdf_surface_emit_stroke_style (surface,
-						   style);
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
 
-    info.output = surface->output;
-    info.cairo_to_pdf = NULL;
-    info.ctm_inverse = ctm_inverse;
-
-    cairo_matrix_multiply (&m, ctm, &surface->cairo_to_pdf);
-    _cairo_output_stream_printf (surface->output,
-				 "q %f %f %f %f %f %f cm\r\n",
-				 m.xx, m.yx, m.xy, m.yy,
-				 m.x0, m.y0);
-
-    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);
-    if (status)
-	return status;
-
-    _cairo_output_stream_printf (surface->output, "S Q\r\n");
-
-    if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_close_group (surface, &smask_group);
+    if (gstate_res.id != 0) {
+	group = _cairo_pdf_surface_create_smask_group (surface);
+	if (group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	group->operation = PDF_STROKE;
+	group->source = cairo_pattern_reference (source);
+	group->source_res = pattern_res;
+	status = _cairo_path_fixed_init_copy (&group->path, path);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	group->style = style;
+	group->ctm = *ctm;
+	group->ctm_inverse = *ctm_inverse;
+	status = _cairo_pdf_surface_add_smask_group (surface, group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_resume_content_stream (surface);
+	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+	if (status)
+	    return status;
+
 	_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);
+				     gstate_res.id,
+				     group->group_res.id);
+    } else {
+	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
 	if (status)
 	    return status;
-	status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+
+	status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
+					     path,
+					     style,
+					     ctm,
+					     ctm_inverse);
 	if (status)
 	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "Q\r\n");
+
+	_cairo_pdf_surface_unselect_pattern (surface);
     }
 
-    status = _cairo_output_stream_get_status (surface->output);
-    if (status)
-	return status;
-
-    return _cairo_pdf_surface_check_content_stream_size (surface);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 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 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)
+    cairo_pdf_smask_group_t *group;
+    cairo_pdf_resource_t pattern_res, gstate_res;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
+    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+	status = _cairo_pdf_surface_start_fallback (surface);
+	if (status)
+	    return status;
+    }
 
     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) {
-	_cairo_pdf_surface_pause_content_stream (surface);
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "q ");
-    }
-
-    status = _cairo_pdf_surface_select_pattern (surface, FALSE);
-    if (status)
-	return status;
-
-    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);
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
 
-    switch (fill_rule) {
-    case CAIRO_FILL_RULE_WINDING:
-	pdf_operator = "f";
-	break;
-    case CAIRO_FILL_RULE_EVEN_ODD:
-	pdf_operator = "f*";
-	break;
-    default:
-	ASSERT_NOT_REACHED;
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 "%s\r\n",
-				 pdf_operator);
-
-    if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_close_group (surface, &smask_group);
+    if (gstate_res.id != 0) {
+	group = _cairo_pdf_surface_create_smask_group (surface);
+	if (group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	group->operation = PDF_FILL;
+	group->source = cairo_pattern_reference (source);
+	group->source_res = pattern_res;
+	status = _cairo_path_fixed_init_copy (&group->path, path);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	group->fill_rule = fill_rule;
+	status = _cairo_pdf_surface_add_smask_group (surface, group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_resume_content_stream (surface);
+	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+	if (status)
+	    return status;
+
 	_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);
+				     gstate_res.id,
+				     group->group_res.id);
+    } else {
+	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "Q\r\n");
+
+	status = _cairo_pdf_operators_fill (&surface->pdf_operators,
+					    path,
+					    fill_rule);
+	if (status)
+	    return status;
+
+	_cairo_pdf_surface_unselect_pattern (surface);
     }
 
-    status = _cairo_output_stream_get_status (surface->output);
-    if (status)
-	return status;
-
-    return _cairo_pdf_surface_check_content_stream_size (surface);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
-#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 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;
+    cairo_pdf_smask_group_t *group;
+    cairo_pdf_resource_t pattern_res, gstate_res;
 
     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) {
-	_cairo_pdf_surface_pause_content_stream (surface);
-	status = _cairo_pdf_surface_open_group (surface);
-	if (status)
-	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "q ");
-    }
-
-    status = _cairo_pdf_surface_select_pattern (surface, FALSE);
+    pattern_res.id = 0;
+    gstate_res.id = 0;
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
 
-    _cairo_output_stream_printf (surface->output,
-				 "BT\r\n");
-
-    if (scaled_font->scale.xy == 0.0 &&
-        scaled_font->scale.yx == 0.0)
-        diagonal = TRUE;
-    else
-        diagonal = FALSE;
-
-    in_TJ = FALSE;
-    for (i = 0; i < num_glyphs; i++) {
-        status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
-                                                       scaled_font, glyphs[i].index,
-                                                       &subset_glyph);
-	if (status)
-            return status;
-
-        if (subset_glyph.is_composite)
-            hex_width = 4;
-        else
-            hex_width = 2;
-
-        if (subset_glyph.is_scaled == FALSE) {
-            y = 0.0;
-            cairo_matrix_transform_distance (&scaled_font->scale,
-                                             &subset_glyph.x_advance,
-                                             &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,
-					 "/f-%d-%d 1 Tf\r\n",
-					 subset_glyph.font_id,
-					 subset_glyph.subset_id);
-	    status = _cairo_pdf_surface_add_font (surface,
-					          subset_glyph.font_id,
-						  subset_glyph.subset_id);
-	    if (status)
-		return status;
-        }
-
-        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,
-                                         scaled_font->scale.yy,
-                                         glyphs[i].x,
-                                         surface->height - glyphs[i].y);
-            current_subset_id = subset_glyph.subset_id;
-            Tlm_x = glyphs[i].x;
-            Tlm_y = glyphs[i].y;
-            Tm_x = Tlm_x;
-        }
-
-        if (diagonal) {
-            if (i < num_glyphs - 1 &&
-                fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
-                fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
-            {
-                if (!in_TJ) {
-                    if (i != 0) {
-                        _cairo_output_stream_printf (surface->output,
-                                                     "%f %f Td\r\n",
-                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
-                                                     -(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
-
-                        Tlm_x = glyphs[i].x;
-                        Tlm_y = glyphs[i].y;
-                        Tm_x = Tlm_x;
-                    }
-                    _cairo_output_stream_printf (surface->output,
-                                                 "[<%0*x",
-                                                 hex_width,
-                                                 subset_glyph.subset_glyph_index);
-                    Tm_x += subset_glyph.x_advance;
-                    in_TJ = TRUE;
-                } else {
-                    if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
-                        double delta = glyphs[i].x - Tm_x;
-
-                        _cairo_output_stream_printf (surface->output,
-                                                     "> %f <",
-                                                     -1000.0*delta/scaled_font->scale.xx);
-                        Tm_x += delta;
-                    }
-                    _cairo_output_stream_printf (surface->output,
-                                                 "%0*x",
-                                                 hex_width,
-                                                 subset_glyph.subset_glyph_index);
-                    Tm_x += subset_glyph.x_advance;
-                }
-            }
-            else
-            {
-                if (in_TJ) {
-                    if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
-                        double delta = glyphs[i].x - Tm_x;
-
-                        _cairo_output_stream_printf (surface->output,
-                                                     "> %f <",
-                                                     -1000.0*delta/scaled_font->scale.xx);
-                        Tm_x += delta;
-                    }
-                    _cairo_output_stream_printf (surface->output,
-                                                 "%0*x>] TJ\r\n",
-                                                 hex_width,
-                                                 subset_glyph.subset_glyph_index);
-                    Tm_x += subset_glyph.x_advance;
-                    in_TJ = FALSE;
-                } else {
-                    if (i != 0) {
-                        _cairo_output_stream_printf (surface->output,
-                                                     "%f %f Td ",
-                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
-                                                     (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
-                        Tlm_x = glyphs[i].x;
-                        Tlm_y = glyphs[i].y;
-                        Tm_x = Tlm_x;
-                    }
-                    _cairo_output_stream_printf (surface->output,
-                                                 "<%0*x> Tj ",
-                                                 hex_width,
-                                                 subset_glyph.subset_glyph_index);
-                    Tm_x += subset_glyph.x_advance;
-                }
-            }
-        } else {
-            _cairo_output_stream_printf (surface->output,
-                                         "<%0*x> Tj\r\n",
-                                         hex_width,
-                                         subset_glyph.subset_glyph_index);
-        }
-    }
-
-    _cairo_output_stream_printf (surface->output,
-				 "ET\r\n");
-
-    if (surface->emitted_pattern.smask.id != 0) {
-	status = _cairo_pdf_surface_close_group (surface, &smask_group);
+    if (gstate_res.id != 0) {
+	group = _cairo_pdf_surface_create_smask_group (surface);
+	if (group == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	group->operation = PDF_SHOW_GLYPHS;
+	group->source = cairo_pattern_reference (source);
+	group->source_res = pattern_res;
+	group->glyphs = glyphs;
+	group->num_glyphs = num_glyphs;
+	group->scaled_font = cairo_scaled_font_reference (scaled_font);
+	status = _cairo_pdf_surface_add_smask_group (surface, group);
+	if (status) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return status;
+	}
+
+	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_resume_content_stream (surface);
+	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+	if (status)
+	    return status;
 
 	_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);
+				     gstate_res.id,
+				     group->group_res.id);
+    } else {
+	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
-    } else {
-	_cairo_output_stream_printf (surface->output, "Q\r\n");
+
+	status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
+						   glyphs,
+						   num_glyphs,
+						   scaled_font);
+	if (status)
+	    return status;
+
+	_cairo_pdf_surface_unselect_pattern (surface);
     }
 
-    status = _cairo_output_stream_get_status (surface->output);
-    if (status)
-	return status;
-
-    return _cairo_pdf_surface_check_content_stream_size (surface);
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static void
 _cairo_pdf_surface_set_paginated_mode (void			*abstract_surface,
 				       cairo_paginated_mode_t	 paginated_mode)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
 
@@ -5006,17 +4611,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_pdf_surface_copy_page,
+    NULL,  /* _cairo_pdf_surface_copy_page */
     _cairo_pdf_surface_show_page,
     NULL, /* set_clip_region */
     _cairo_pdf_surface_intersect_clip_path,
     _cairo_pdf_surface_get_extents,
     NULL, /* old_show_glyphs */
     _cairo_pdf_surface_get_font_options,
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
--- a/gfx/cairo/cairo/src/cairo-png.c
+++ b/gfx/cairo/cairo/src/cairo-png.c
@@ -270,18 +270,24 @@ stdio_write_func (png_structp png, png_b
 cairo_status_t
 cairo_surface_write_to_png (cairo_surface_t	*surface,
 			    const char		*filename)
 {
     FILE *fp;
     cairo_status_t status;
 
     fp = fopen (filename, "wb");
-    if (fp == NULL)
-	return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
+    if (fp == NULL) {
+	switch (errno) {
+	case ENOMEM:
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	default:
+	    return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
+	}
+    }
 
     status = write_png (surface, stdio_write_func, fp);
 
     if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
 
     return status;
 }
--- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h
@@ -73,13 +73,14 @@ typedef struct cairo_ps_surface {
 
     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_ps_level_t ps_level;
+    cairo_ps_level_t ps_level_used;
 
     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
@@ -42,22 +42,28 @@
 #include "cairoint.h"
 #include "cairo-ps.h"
 #include "cairo-ps-surface-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
 
+#include <stdio.h>
 #include <ctype.h>
 #include <time.h>
 #include <zlib.h>
+#include <errno.h>
 
 #define DEBUG_PS 0
 
+#ifndef HAVE_CTIME_R
+#define ctime_r(T, BUF) ctime (T)
+#endif
+
 typedef enum _cairo_image_transparency {
     CAIRO_IMAGE_IS_OPAQUE,
     CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
     CAIRO_IMAGE_HAS_ALPHA
 } cairo_image_transparency_t;
 
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
@@ -313,50 +319,51 @@ static cairo_status_t
 	status = status2;
 
     return status;
 }
 
 static void
 _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 {
+    char ctime_buf[26];
     time_t now;
     char **comments;
     int i, num_comments;
-    const char *level;
+    int level;
     const char *eps_header = "";
 
     now = time (NULL);
 
-    if (surface->ps_level == CAIRO_PS_LEVEL_2)
-	level = "2";
+    if (surface->ps_level_used == CAIRO_PS_LEVEL_2)
+	level = 2;
     else
-	level = "3";
+	level = 3;
 
     if (surface->eps)
 	eps_header = " EPSF-3.0";
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%!PS-Adobe-3.0%s\n"
 				 "%%%%Creator: cairo %s (http://cairographics.org)\n"
 				 "%%%%CreationDate: %s"
 				 "%%%%Pages: %d\n"
 				 "%%%%BoundingBox: %d %d %d %d\n",
 				 eps_header,
 				 cairo_version_string (),
-				 ctime (&now),
+				 ctime_r (&now, ctime_buf),
 				 surface->num_pages,
 				 surface->bbox_x1,
 				 surface->bbox_y1,
 				 surface->bbox_x2,
 				 surface->bbox_y2);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%DocumentData: Clean7Bit\n"
-				 "%%%%LanguageLevel: %s\n",
+				 "%%%%LanguageLevel: %d\n",
 				 level);
 
     num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
     comments = _cairo_array_index (&surface->dsc_header_comments, 0);
     for (i = 0; i < num_comments; i++) {
 	_cairo_output_stream_printf (surface->final_stream,
 				     "%s\n", comments[i]);
 	free (comments[i]);
@@ -370,16 +377,24 @@ static void
 				 "%%%%BeginProlog\n");
 
     if (surface->eps) {
 	_cairo_output_stream_printf (surface->final_stream,
 				     "/cairo_eps_state save def\n"
 				     "/dict_count countdictstack def\n"
 				     "/op_count count 1 sub def\n"
 				     "userdict begin\n");
+    } else {
+	_cairo_output_stream_printf (surface->final_stream,
+				     "/languagelevel where{pop languagelevel}{1}ifelse %d lt{/Helvetica\n"
+				     "findfont 12 scalefont setfont 50 500 moveto\n"
+				     "(This print job requires a PostScript Language Level %d printer.)show\n"
+				     "showpage quit}if\n",
+				     level,
+				     level);
     }
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "/C{curveto}bind def\n"
 				 "/F{fill}bind def\n"
 				 "/G{setgray}bind def\n"
 				 "/L{lineto}bind def\n"
 				 "/M{moveto}bind def\n"
@@ -564,80 +579,92 @@ static cairo_status_t
     _cairo_truetype_subset_fini (&subset);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t	*surface,
 					   cairo_scaled_font_t	*scaled_font,
-					   unsigned long	 glyph_index)
+					   unsigned long	 glyph_index,
+					   cairo_box_t          *bbox)
 {
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_status_t status;
 
     status = _cairo_scaled_glyph_lookup (scaled_font,
 					 glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_PATH,
 					 &scaled_glyph);
     if (status)
 	return status;
 
+    *bbox = scaled_glyph->bbox;
     _cairo_output_stream_printf (surface->final_stream,
 				 "0 0 %f %f %f %f setcachedevice\n",
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 				 -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
 				 -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 
     /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
     status = _cairo_ps_surface_emit_path (surface,
 					  surface->final_stream,
 					  scaled_glyph->path,
 					  CAIRO_LINE_CAP_ROUND);
+    if (status)
+	return status;
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "F\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t	*surface,
 					  cairo_scaled_font_t	*scaled_font,
-					  unsigned long	 glyph_index)
+					  unsigned long	 glyph_index,
+					  cairo_box_t           *bbox)
 {
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_status_t status;
     cairo_image_surface_t *image;
     unsigned char *row, *byte;
     int rows, cols;
+    double x_advance, y_advance;
 
     status = _cairo_scaled_glyph_lookup (scaled_font,
 					 glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					 &scaled_glyph);
     if (status)
 	return status;
 
+    *bbox = scaled_glyph->bbox;
+    x_advance = scaled_glyph->metrics.x_advance;
+    y_advance = scaled_glyph->metrics.y_advance;
+    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
+
     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 (surface->final_stream,
-				 "0 0 %f %f %f %f setcachedevice\n",
+				 "%f 0 %f %f %f %f setcachedevice\n",
+				 x_advance,
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
+				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
-				 - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
+				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "<<\n"
 				 "   /ImageType 1\n"
 				 "   /Width %d\n"
 				 "   /Height %d\n"
 				 "   /ImageMatrix [%f %f %f %f %f %f]\n"
 				 "   /Decode [1 0]\n"
@@ -673,30 +700,35 @@ static cairo_int_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
 			      cairo_scaled_font_t	*scaled_font,
 			      unsigned long		 scaled_font_glyph_index,
-			      unsigned int		 subset_glyph_index)
+			      unsigned int		 subset_glyph_index,
+			      cairo_box_t               *bbox)
 {
-    cairo_status_t	    status;
+    cairo_status_t	    status = CAIRO_STATUS_SUCCESS;
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "\t\t{ %% %d\n", subset_glyph_index);
 
-    status = _cairo_ps_surface_emit_outline_glyph_data (surface,
-							scaled_font,
-							scaled_font_glyph_index);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
-							   scaled_font,
-							   scaled_font_glyph_index);
+    if (subset_glyph_index != 0) {
+	status = _cairo_ps_surface_emit_outline_glyph_data (surface,
+							    scaled_font,
+							    scaled_font_glyph_index,
+							    bbox);
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	    status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
+							       scaled_font,
+							       scaled_font_glyph_index,
+							       bbox);
+    }
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "\t\t}\n");
 
     if (status)
 	status = _cairo_surface_set_error (&surface->base, status);
 
     return status;
@@ -706,57 +738,94 @@ static cairo_status_t
 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
 
 
 {
     cairo_status_t status;
     cairo_matrix_t matrix;
     unsigned int i;
+    cairo_box_t font_bbox = {{0,0},{0,0}};
+    cairo_box_t bbox = {{0,0},{0,0}};
 
 #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);
     /* _cairo_scaled_font_init ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
     _cairo_output_stream_printf (surface->final_stream,
-				 "\t/FontType\t3\n"
-				 "\t/FontMatrix\t[%f %f %f %f 0 0]\n"
-				 "\t/Encoding\t[0]\n"
-				 "\t/FontBBox\t[0 0 10 10]\n"
-				 "\t/Glyphs [\n",
+				 "8 dict begin\n"
+				 "/FontType 3 def\n"
+				 "/FontMatrix [%f %f %f %f 0 0] def\n"
+				 "/Encoding 256 array def\n"
+				 "0 1 255 { Encoding exch /.notdef put } for\n",
 				 matrix.xx,
 				 matrix.yx,
 				 -matrix.xy,
 				 -matrix.yy);
 
+    for (i = 1; i < font_subset->num_glyphs; i++) {
+	if (font_subset->glyph_names != NULL) {
+	    _cairo_output_stream_printf (surface->final_stream,
+					 "Encoding %d /%s put\n",
+					 i, font_subset->glyph_names[i]);
+	} else {
+	    _cairo_output_stream_printf (surface->final_stream,
+					 "Encoding %d /g%d put\n", i, i);
+	}
+    }
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "/Glyphs [\n");
+
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	status = _cairo_ps_surface_emit_glyph (surface,
 				               font_subset->scaled_font,
-					       font_subset->glyphs[i], i);
+					       font_subset->glyphs[i], i,
+					       &bbox);
 	if (status)
 	    return status;
+
+        if (i == 0) {
+            font_bbox.p1.x = bbox.p1.x;
+            font_bbox.p1.y = bbox.p1.y;
+            font_bbox.p2.x = bbox.p2.x;
+            font_bbox.p2.y = bbox.p2.y;
+        } else {
+            if (bbox.p1.x < font_bbox.p1.x)
+                font_bbox.p1.x = bbox.p1.x;
+            if (bbox.p1.y < font_bbox.p1.y)
+                font_bbox.p1.y = bbox.p1.y;
+            if (bbox.p2.x > font_bbox.p2.x)
+                font_bbox.p2.x = bbox.p2.x;
+            if (bbox.p2.y > font_bbox.p2.y)
+                font_bbox.p2.y = bbox.p2.y;
+        }
     }
 
     _cairo_output_stream_printf (surface->final_stream,
-				 "\t]\n"
-				 "\t/BuildChar {\n"
-				 "\t\texch /Glyphs get\n"
-				 "\t\texch get exec\n"
-				 "\t}\n"
-				 ">> definefont pop\n");
+				 "] def\n"
+				 "/FontBBox [%f %f %f %f] def\n"
+				 "/BuildChar {\n"
+				 "  exch /Glyphs get\n"
+				 "  exch get exec\n"
+				 "} bind def\n"
+				 "currentdict\n"
+				 "end\n"
+				 "/CairoFont-%d-%d exch definefont pop\n",
+				 _cairo_fixed_to_double (font_bbox.p1.x),
+				 _cairo_fixed_to_double (font_bbox.p1.y),
+				 _cairo_fixed_to_double (font_bbox.p2.x),
+				 _cairo_fixed_to_double (font_bbox.p2.y),
+				 font_subset->font_id,
+				 font_subset->subset_id);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t	*font_subset,
 				            void			*closure)
 {
@@ -825,25 +894,30 @@ static cairo_status_t
 
 BAIL:
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
     surface->font_subsets = NULL;
 
     return status;
 }
 
-static void
+static cairo_status_t
 _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
 {
     char    buf[4096];
     int	    n;
 
+    if (ferror (surface->tmpfile) != 0)
+	return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
+
     rewind (surface->tmpfile);
     while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
 	_cairo_output_stream_write (surface->final_stream, buf, n);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface)
 {
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%Trailer\n");
 
@@ -873,30 +947,40 @@ static cairo_surface_t *
     }
 
     _cairo_surface_init (&surface->base, &cairo_ps_surface_backend,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     surface->final_stream = stream;
 
     surface->tmpfile = tmpfile ();
-    if (surface->tmpfile == NULL)
+    if (surface->tmpfile == NULL) {
+	switch (errno) {
+	case ENOMEM:
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    break;
+	default:
+	    status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
+	    break;
+	}
 	goto CLEANUP_SURFACE;
+    }
 
     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
     status = _cairo_output_stream_get_status (surface->stream);
     if (status)
 	goto CLEANUP_TMPFILE;
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
     if (! surface->font_subsets)
 	goto CLEANUP_OUTPUT_STREAM;
 
     surface->eps = FALSE;
     surface->ps_level = CAIRO_PS_LEVEL_3;
+    surface->ps_level_used = CAIRO_PS_LEVEL_2;
     surface->width  = width;
     surface->height = height;
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
     surface->force_fallbacks = FALSE;
     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
 
     surface->num_pages = 0;
 
@@ -1431,21 +1515,26 @@ static cairo_status_t
     cairo_status_t status, status2;
     cairo_ps_surface_t *surface = abstract_surface;
     int i, num_comments;
     char **comments;
 
     _cairo_ps_surface_emit_header (surface);
 
     status = _cairo_ps_surface_emit_font_subsets (surface);
-
-    _cairo_ps_surface_emit_body (surface);
+    if (status)
+	goto CLEANUP;
+
+    status = _cairo_ps_surface_emit_body (surface);
+    if (status)
+	goto CLEANUP;
 
     _cairo_ps_surface_emit_footer (surface);
 
+CLEANUP:
     status2 = _cairo_output_stream_destroy (surface->stream);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
     fclose (surface->tmpfile);
 
     status2 = _cairo_output_stream_destroy (surface->final_stream);
     if (status == CAIRO_STATUS_SUCCESS)
@@ -1510,17 +1599,16 @@ color_is_gray (double red, double green,
     return (fabs (red - green) < epsilon &&
 	    fabs (red - blue) < epsilon);
 }
 
 static cairo_status_t
 _analyze_image_transparency (cairo_image_surface_t      *image,
 			     cairo_image_transparency_t *transparency)
 {
-    cairo_status_t status;
     int x, y;
 
     if (image->format == CAIRO_FORMAT_RGB24) {
 	*transparency = CAIRO_IMAGE_IS_OPAQUE;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     if (image->format != CAIRO_FORMAT_ARGB32) {
@@ -1542,19 +1630,18 @@ static cairo_status_t
 	    if (a > 0 && a < 255) {
 		*transparency = CAIRO_IMAGE_HAS_ALPHA;
 		return CAIRO_STATUS_SUCCESS;
 	    } else if (a == 0) {
 		*transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
 	    }
 	}
     }
-    status = CAIRO_STATUS_SUCCESS;
-
-    return status;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t      *surface,
 						       cairo_surface_pattern_t *pattern)
 {
     cairo_image_surface_t  *image;
     void		   *image_extra;
@@ -1575,20 +1662,22 @@ static cairo_int_status_t
 	goto RELEASE_SOURCE;
 
     switch (transparency) {
     case CAIRO_IMAGE_IS_OPAQUE:
 	status = CAIRO_STATUS_SUCCESS;
 	break;
 
     case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
-	if (surface->ps_level == CAIRO_PS_LEVEL_2)
+	if (surface->ps_level == CAIRO_PS_LEVEL_2) {
 	    status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
-	else
+	} else {
+	    surface->ps_level_used = CAIRO_PS_LEVEL_3;
 	    status = CAIRO_STATUS_SUCCESS;
+	}
 	break;
 
     case CAIRO_IMAGE_HAS_ALPHA:
 	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 	break;
     }
 
 RELEASE_SOURCE:
@@ -1641,16 +1730,17 @@ static cairo_bool_t
 _gradient_pattern_supported (cairo_ps_surface_t    *surface,
 			     cairo_pattern_t *pattern)
 {
     cairo_extend_t extend;
 
     if (surface->ps_level == CAIRO_PS_LEVEL_2)
 	return FALSE;
 
+    surface->ps_level_used = CAIRO_PS_LEVEL_3;
     extend = cairo_pattern_get_extend (pattern);
 
     if (extend == CAIRO_EXTEND_REPEAT ||
         extend == CAIRO_EXTEND_REFLECT) {
         return FALSE;
     }
 
     /* Radial gradients are currently only supported when one circle
@@ -1701,39 +1791,43 @@ static cairo_int_status_t
 
     if (! pattern_supported (surface, pattern))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (!(op == CAIRO_OPERATOR_SOURCE ||
 	  op == CAIRO_OPERATOR_OVER))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (op == CAIRO_OPERATOR_SOURCE)
-	return CAIRO_STATUS_SUCCESS;
-
     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;
-	else
-	    return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
-									   surface_pattern);
     }
 
+    if (op == CAIRO_OPERATOR_SOURCE)
+	return CAIRO_STATUS_SUCCESS;
+
     /* 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 (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+
+	return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
+								       surface_pattern);
+    }
+
     if (_cairo_pattern_is_opaque (pattern))
 	return CAIRO_STATUS_SUCCESS;
     else
 	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 }
 
 static cairo_bool_t
 _cairo_ps_surface_operation_supported (cairo_ps_surface_t    *surface,
@@ -1884,20 +1978,18 @@ static cairo_status_t
     if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
 	background_color = CAIRO_COLOR_WHITE;
     else
 	background_color = CAIRO_COLOR_BLACK;
 
     opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
 					 image->width,
 					 image->height);
-    if (opaque->status) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return status;
-    }
+    if (opaque->status)
+	return opaque->status;
 
     _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
 
     status = _cairo_surface_fill_rectangle (opaque,
 					    CAIRO_OPERATOR_SOURCE,
 					    background_color,
 					    0, 0,
 					    image->width, image->height);
@@ -1925,18 +2017,18 @@ fail:
     _cairo_pattern_fini (&pattern.base);
     cairo_surface_destroy (opaque);
 
     return status;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
-				      unsigned char 	    *data,
-				      unsigned long 	     length)
+				      unsigned char	    *data,
+				      unsigned long	     length)
 {
     cairo_output_stream_t *base85_stream, *string_array_stream;
     cairo_status_t status, status2;
 
     string_array_stream = _string_array_stream_create (surface->stream);
     status = _cairo_output_stream_get_status (string_array_stream);
     if (status)
 	return status;
@@ -1957,17 +2049,17 @@ static cairo_status_t
 
     return status;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 			      cairo_image_surface_t *image,
 			      const char	    *name,
-			      cairo_operator_t 	     op)
+			      cairo_operator_t	     op)
 {
     cairo_status_t status;
     unsigned char *rgb, *rgb_compressed;
     unsigned long rgb_size, rgb_compressed_size;
     unsigned char *mask = NULL, *mask_compressed = NULL;
     unsigned long mask_size = 0, mask_compressed_size = 0;
     cairo_image_surface_t *opaque_image = NULL;
     int x, y, i;
@@ -1983,20 +2075,24 @@ static cairo_status_t
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white (or black for CONTENT_COLOR
        surfaces) RGB surface to eliminate it. */
 
     if (op == CAIRO_OPERATOR_SOURCE ||
 	transparency == CAIRO_IMAGE_HAS_ALPHA ||
 	(transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA &&
-	 surface->ps_level == CAIRO_PS_LEVEL_2)) {
-	_cairo_ps_surface_flatten_image_transparency (surface,
-						      image,
-						      &opaque_image);
+	 surface->ps_level == CAIRO_PS_LEVEL_2))
+    {
+	status = _cairo_ps_surface_flatten_image_transparency (surface,
+							       image,
+							       &opaque_image);
+	if (status)
+	    return status;
+
 	use_mask = FALSE;
     } else if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
 	opaque_image = image;
 	use_mask = FALSE;
     } else {
 	use_mask = TRUE;
     }
 
@@ -2188,29 +2284,29 @@ bail1:
     return status;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_image_surface (cairo_ps_surface_t      *surface,
 				      cairo_surface_pattern_t *pattern,
 				      int                     *width,
 				      int                     *height,
-				      cairo_operator_t 	       op)
+				      cairo_operator_t	       op)
 {
     cairo_image_surface_t  *image;
     void		   *image_extra;
     cairo_status_t          status;
 
     status = _cairo_surface_acquire_source_image (pattern->surface,
 						  &image,
 						  &image_extra);
     if (status)
 	return status;
 
-    _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op);
+    status = _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op);
     if (status)
 	goto fail;
 
     *width = image->width;
     *height = image->height;
 
 fail:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
@@ -2243,36 +2339,38 @@ static cairo_status_t
     if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 	surface->content = CAIRO_CONTENT_COLOR;
 	_cairo_output_stream_printf (surface->stream,
 				     "0 G 0 0 %f %f rectfill\n",
 				     surface->width,
 				     surface->height);
     }
 
-    status = _cairo_meta_surface_replay (meta_surface, &surface->base);
+    status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
+						CAIRO_META_REGION_NATIVE);
+    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	return status;
 
     _cairo_output_stream_printf (surface->stream,
 				 "grestore\n"
 				 "} bind def\n");
     surface->content = old_content;
     surface->width = old_width;
     surface->height = old_height;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t 	*surface,
-					const cairo_color_t 	*color,
-					double 			*red,
-					double 			*green,
-					double 			*blue)
+_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t	*surface,
+					const cairo_color_t	*color,
+					double			*red,
+					double			*green,
+					double			*blue)
 {
     *red = color->red;
     *green = color->green;
     *blue = color->blue;
 
     if (!CAIRO_COLOR_IS_OPAQUE(color)) {
 	if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
 	    uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
@@ -2304,17 +2402,17 @@ static void
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f %f R\n",
 				     red, green, blue);
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 					cairo_surface_pattern_t *pattern,
-					cairo_operator_t 	 op)
+					cairo_operator_t	 op)
 {
     cairo_status_t status;
     int pattern_width = 0; /* squelch bogus compiler warning */
     int pattern_height = 0; /* squelch bogus compiler warning */
     double xstep, ystep;
     cairo_matrix_t inverse = pattern->base.matrix;
 
     status = cairo_matrix_invert (&inverse);
@@ -2322,19 +2420,23 @@ static cairo_status_t
     assert (status == CAIRO_STATUS_SUCCESS);
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	cairo_surface_t *meta_surface = pattern->surface;
 	cairo_rectangle_int_t pattern_extents;
 
 	status = _cairo_ps_surface_emit_meta_surface (surface,
 						      meta_surface);
+	if (status)
+	    return status;
+
 	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_ps_surface_emit_image_surface (surface,
 						       pattern,
 						       &pattern_width,
 						       &pattern_height,
 						       op);
@@ -2470,17 +2572,17 @@ static cairo_status_t
 _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 				      cairo_gradient_pattern_t *pattern)
 {
     cairo_ps_color_stop_t *allstops, *stops;
     unsigned int i, n_stops;
 
     allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
     if (allstops == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     stops = &allstops[1];
     n_stops = pattern->n_stops;
 
     for (i = 0; i < n_stops; i++) {
 	double red, green, blue;
 
 	_cairo_ps_surface_flatten_transparency (surface,
@@ -2526,16 +2628,19 @@ static cairo_status_t
 _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t     *surface,
 				       cairo_linear_pattern_t *pattern)
 {
     double x1, y1, x2, y2;
     cairo_extend_t extend;
     cairo_status_t status;
     cairo_matrix_t inverse = pattern->base.base.matrix;
 
+    if (pattern->base.n_stops == 0)
+        return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     status = cairo_matrix_invert (&inverse);
     if (status)
 	return status;
 
     x1 = _cairo_fixed_to_double (pattern->p1.x);
     y1 = _cairo_fixed_to_double (pattern->p1.y);
@@ -2581,16 +2686,19 @@ static cairo_status_t
 _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t     *surface,
 				       cairo_radial_pattern_t *pattern)
 {
     double x1, y1, x2, y2, r1, r2;
     cairo_extend_t extend;
     cairo_status_t status;
     cairo_matrix_t inverse = pattern->base.base.matrix;
 
+    if (pattern->base.n_stops == 0)
+        return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     status = cairo_matrix_invert (&inverse);
     if (status)
 	return status;
 
     x1 = _cairo_fixed_to_double (pattern->c1.x);
     y1 = _cairo_fixed_to_double (pattern->c1.y);
@@ -2653,21 +2761,27 @@ static cairo_status_t
 	status = _cairo_ps_surface_emit_surface_pattern (surface,
 							 (cairo_surface_pattern_t *) pattern,
 							 op);
 	if (status)
 	    return status;
 	break;
 
     case CAIRO_PATTERN_TYPE_LINEAR:
-	_cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+	status = _cairo_ps_surface_emit_linear_pattern (surface,
+					  (cairo_linear_pattern_t *) pattern);
+	if (status)
+	    return status;
 	break;
 
     case CAIRO_PATTERN_TYPE_RADIAL:
-	_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+	status = _cairo_ps_surface_emit_radial_pattern (surface,
+					  (cairo_radial_pattern_t *) pattern);
+	if (status)
+	    return status;
 	break;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_intersect_clip_path (void		   *abstract_surface,
@@ -2772,16 +2886,19 @@ static cairo_int_status_t
 
     status = _cairo_pattern_get_extents (source, &pattern_extents);
     if (status)
 	return status;
 
     _cairo_rectangle_intersect (&extents, &pattern_extents);
 
     status = _cairo_ps_surface_emit_pattern (surface, source, op);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+        return CAIRO_STATUS_SUCCESS;
+
     if (status)
 	return status;
 
     _cairo_output_stream_printf (stream, "%d %d M\n",
 				 extents.x, extents.y);
     _cairo_output_stream_printf (stream, "%d %d L\n",
 				 extents.x + extents.width,
 				 extents.y);
@@ -2915,23 +3032,34 @@ static cairo_int_status_t
 		 * Set i to -2 so it will get incremented to 0. */
 		if (i == 2)
 		    i = -2;
 	    }
 	}
     }
 
     status = _cairo_ps_surface_emit_pattern (surface, source, op);
-    if (status)
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+        return CAIRO_STATUS_SUCCESS;
+
+    if (status) {
+	if (dash != style->dash)
+	    free (dash);
 	return status;
+    }
 
     _cairo_output_stream_printf (stream,
 				 "gsave\n");
     status = _cairo_ps_surface_emit_path (surface, stream, path,
 					  style->line_cap);
+    if (status) {
+	if (dash != style->dash)
+	    free (dash);
+	return status;
+    }
 
     /*
      * Switch to user space to set line parameters
      */
     _cairo_output_stream_printf (stream,
 				 "[%f %f %f %f 0 0] concat\n",
 				 ctm->xx, ctm->yx, ctm->xy, ctm->yy);
     /* line width */
@@ -2958,17 +3086,18 @@ static cairo_int_status_t
 
     /* miter limit */
     _cairo_output_stream_printf (stream, "%f setmiterlimit\n",
 				 style->miter_limit);
     _cairo_output_stream_printf (stream,
 				 "stroke\n");
     _cairo_output_stream_printf (stream,
 				 "grestore\n");
-    return status;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_fill (void		*abstract_surface,
 		 cairo_operator_t	 op,
 		 cairo_pattern_t	*source,
 		 cairo_path_fixed_t	*path,
 		 cairo_fill_rule_t	 fill_rule,
@@ -2986,16 +3115,19 @@ static cairo_int_status_t
     assert (_cairo_ps_surface_operation_supported (surface, op, source));
 
 #if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_fill\n");
 #endif
 
     status = _cairo_ps_surface_emit_pattern (surface, source, op);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+        return CAIRO_STATUS_SUCCESS;
+
     if (status)
 	return status;
 
     /* 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);
     if (status)
 	return status;
@@ -3055,29 +3187,33 @@ static cairo_int_status_t
 #endif
 
     if (num_glyphs <= 0)
         return CAIRO_STATUS_SUCCESS;
 
     num_glyphs_unsigned = num_glyphs;
 
     status = _cairo_ps_surface_emit_pattern (surface, source, op);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+        return CAIRO_STATUS_SUCCESS;
+
     if (status)
 	return status;
 
     glyph_ids = _cairo_malloc_ab (num_glyphs_unsigned, sizeof (cairo_ps_glyph_id_t));
     if (glyph_ids == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     for (i = 0; i < num_glyphs_unsigned; i++) {
         status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
                                                        scaled_font, glyphs[i].index,
                                                        &subset_glyph);
         if (status)
             goto fail;
+
         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,
@@ -3144,17 +3280,17 @@ static cairo_int_status_t
                     else
                         _cairo_output_stream_printf (word_wrap,
                                                      "%f ", glyphs[j + 1].y - glyphs[j].y);
                 }
                 _cairo_output_stream_printf (word_wrap, "] yS\n");
             } else {
                 for (j = i; j < last+1; j++) {
                     if (j == num_glyphs_unsigned - 1)
-                        _cairo_output_stream_printf (word_wrap, "0 ");
+                        _cairo_output_stream_printf (word_wrap, "0 0 ");
                     else
                         _cairo_output_stream_printf (word_wrap,
                                                      "%f %f ",
                                                      glyphs[j + 1].x - glyphs[j].x,
                                                      glyphs[j + 1].y - glyphs[j].y);
                 }
                 _cairo_output_stream_printf (word_wrap, "] xyS\n");
             }
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -1,12 +1,12 @@
 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright  2006, 2007 Mozilla Corporation
+ * Copyright � 2006, 2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -52,16 +52,18 @@
 #undef QUARTZ_DEBUG
 
 #ifdef QUARTZ_DEBUG
 #define ND(_x)	fprintf _x
 #else
 #define ND(_x)	do {} while(0)
 #endif
 
+#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0)
+
 /* This method is private, but it exists.  Its params are are exposed
  * as args to the NS* method, but not as CG.
  */
 enum PrivateCGCompositeMode {
     kPrivateCGCompositeClear		= 0,
     kPrivateCGCompositeCopy		= 1,
     kPrivateCGCompositeSourceOver	= 2,
     kPrivateCGCompositeSourceIn		= 3,
@@ -79,40 +81,49 @@ typedef enum PrivateCGCompositeMode Priv
 CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
 CG_EXTERN void CGContextResetCTM (CGContextRef);
 CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform);
 CG_EXTERN void CGContextResetClip (CGContextRef);
 CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
 
 /* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
  * has all the stuff we care about, just some of it isn't exported in the SDK.
- */ 
+ */
 #ifndef kCGBitmapByteOrder32Host
 #define USE_10_3_WORKAROUNDS
 #define kCGBitmapAlphaInfoMask 0x1F
 #define kCGBitmapByteOrderMask 0x7000
 #define kCGBitmapByteOrder32Host 0
 
 typedef uint32_t CGBitmapInfo;
 
 /* public in 10.4, present in 10.3.9 */
 CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
 CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
 #endif
 
 /* missing in 10.3.9 */
 extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import));
 
+/* 10.5-only optimization */
+extern void CGContextDrawTiledImage (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import));
+
 /*
  * Utility functions
  */
 
 static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest);
 static void quartz_image_to_png (CGImageRef, char *dest);
 
+static cairo_quartz_surface_t *
+_cairo_quartz_surface_create_internal (CGContextRef cgContext,
+				       cairo_content_t content,
+				       unsigned int width,
+				       unsigned int height);
+
 /* CoreGraphics limitation with flipped CTM surfaces: height must be less than signed 16-bit max */
 
 #define CG_MAX_HEIGHT   SHRT_MAX
 #define CG_MAX_WIDTH    USHRT_MAX
 
 /* is the desired size of the surface within bounds? */
 static cairo_bool_t verify_surface_size(int width, int height)
 {
@@ -155,17 +166,17 @@ static cairo_status_t
 
 static cairo_status_t
 _cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
 {
     //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
     quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
     double x = _cairo_fixed_to_double (point->x);
     double y = _cairo_fixed_to_double (point->y);
-    
+
     if (stroke->ctm_inverse)
 	cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
 
     if (CGContextIsPathEmpty (stroke->cgContext))
 	CGContextMoveToPoint (stroke->cgContext, x, y);
     else
 	CGContextAddLineToPoint (stroke->cgContext, x, y);
     return CAIRO_STATUS_SUCCESS;
@@ -362,104 +373,16 @@ CreateGradientFunction (cairo_gradient_p
     return CGFunctionCreate (gpat,
 			     1,
 			     input_value_range,
 			     4,
 			     output_value_ranges,
 			     &callbacks);
 }
 
-static cairo_int_status_t
-_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat,
-						CGShadingRef *shading)
-{
-    cairo_matrix_t mat;
-    double x0, y0;
-
-    if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&