b=446323, Upgrade cairo to 1.6.4-350-g1a9809b; r=vlad
authorVladimir Vukicevic <vladimir@pobox.com>
Sun, 20 Jul 2008 14:15:22 -0700
changeset 16122 5305b356a7b12c61d7b0896909c917b73dd6eae4
parent 16121 37f174b079502f575bc5c6defbf29620f07cf94e
child 16123 970e86f6eb563a53b0440320fe7a99342762c196
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs446323
milestone1.9.1a1pre
b=446323, Upgrade cairo to 1.6.4-350-g1a9809b; r=vlad
config/system-headers
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface-private.h
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-arc.c
gfx/cairo/cairo/src/cairo-array.c
gfx/cairo/cairo/src/cairo-base85-stream.c
gfx/cairo/cairo/src/cairo-bentley-ottmann.c
gfx/cairo/cairo/src/cairo-beos.h
gfx/cairo/cairo/src/cairo-cache.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-compiler-private.h
gfx/cairo/cairo/src/cairo-debug.c
gfx/cairo/cairo/src/cairo-debug.h
gfx/cairo/cairo/src/cairo-deflate-stream.c
gfx/cairo/cairo/src/cairo-deprecated.h
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-directfb.h
gfx/cairo/cairo/src/cairo-fixed-private.h
gfx/cairo/cairo/src/cairo-font-face.c
gfx/cairo/cairo/src/cairo-font-options.c
gfx/cairo/cairo/src/cairo-ft-font.c
gfx/cairo/cairo/src/cairo-ft-private.h
gfx/cairo/cairo/src/cairo-ft.h
gfx/cairo/cairo/src/cairo-glitz-surface.c
gfx/cairo/cairo/src/cairo-glitz.h
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-hash.c
gfx/cairo/cairo/src/cairo-hull.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-lzw.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-meta-surface-private.h
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-misc.c
gfx/cairo/cairo/src/cairo-mutex-impl-private.h
gfx/cairo/cairo/src/cairo-mutex-private.h
gfx/cairo/cairo/src/cairo-mutex-type-private.h
gfx/cairo/cairo/src/cairo-mutex.c
gfx/cairo/cairo/src/cairo-os2-private.h
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-os2.h
gfx/cairo/cairo/src/cairo-output-stream-private.h
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-fixed.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-pdf.h
gfx/cairo/cairo/src/cairo-pen.c
gfx/cairo/cairo/src/cairo-png.c
gfx/cairo/cairo/src/cairo-polygon.c
gfx/cairo/cairo/src/cairo-private.h
gfx/cairo/cairo/src/cairo-ps-surface-private.h
gfx/cairo/cairo/src/cairo-ps-surface.c
gfx/cairo/cairo/src/cairo-ps.h
gfx/cairo/cairo/src/cairo-quartz-font.c
gfx/cairo/cairo/src/cairo-quartz-image-surface.c
gfx/cairo/cairo/src/cairo-quartz-image.h
gfx/cairo/cairo/src/cairo-quartz-private.h
gfx/cairo/cairo/src/cairo-quartz-surface.c
gfx/cairo/cairo/src/cairo-quartz.h
gfx/cairo/cairo/src/cairo-rectangle.c
gfx/cairo/cairo/src/cairo-region-private.h
gfx/cairo/cairo/src/cairo-region.c
gfx/cairo/cairo/src/cairo-rename.h
gfx/cairo/cairo/src/cairo-scaled-font-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-svg.h
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h
gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-unicode.c
gfx/cairo/cairo/src/cairo-user-font-private.h
gfx/cairo/cairo/src/cairo-user-font.c
gfx/cairo/cairo/src/cairo-wideint-type-private.h
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-win32.h
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xcb-xrender.h
gfx/cairo/cairo/src/cairo-xcb.h
gfx/cairo/cairo/src/cairo-xlib-display.c
gfx/cairo/cairo/src/cairo-xlib-private.h
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo-xlib-visual.c
gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
gfx/cairo/cairo/src/cairo-xlib-xrender.h
gfx/cairo/cairo/src/cairo-xlib.h
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/filterpublic.awk
gfx/cairo/cairo/src/test-meta-surface.c
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/libpixman/src/Makefile.in
gfx/cairo/libpixman/src/pixman-access.c
gfx/cairo/libpixman/src/pixman-combine.c
gfx/cairo/libpixman/src/pixman-combine32.c
gfx/cairo/libpixman/src/pixman-combine32.h
gfx/cairo/libpixman/src/pixman-combine64.c
gfx/cairo/libpixman/src/pixman-combine64.h
gfx/cairo/libpixman/src/pixman-compose.c
gfx/cairo/libpixman/src/pixman-compute-region.c
gfx/cairo/libpixman/src/pixman-edge.c
gfx/cairo/libpixman/src/pixman-image.c
gfx/cairo/libpixman/src/pixman-mmx.c
gfx/cairo/libpixman/src/pixman-pict.c
gfx/cairo/libpixman/src/pixman-private.h
gfx/cairo/libpixman/src/pixman-region.c
gfx/cairo/libpixman/src/pixman-region16.c
gfx/cairo/libpixman/src/pixman-region32.c
gfx/cairo/libpixman/src/pixman-remap.h
gfx/cairo/libpixman/src/pixman-source.c
gfx/cairo/libpixman/src/pixman-sse.c
gfx/cairo/libpixman/src/pixman-sse.h
gfx/cairo/libpixman/src/pixman-transformed.c
gfx/cairo/libpixman/src/pixman-trap.c
gfx/cairo/libpixman/src/pixman-utils.c
gfx/cairo/libpixman/src/pixman-version.h
gfx/cairo/libpixman/src/pixman-vmx.c
gfx/cairo/libpixman/src/pixman-vmx.h
gfx/cairo/libpixman/src/pixman.h
--- a/config/system-headers
+++ b/config/system-headers
@@ -191,16 +191,17 @@ files.h
 Files.h
 FindDirectory.h
 Finder.h
 FinderRegistry.h
 FixMath.h
 float.h
 Folders.h
 fontconfig/fontconfig.h
+fontconfig/fcfreetype.h
 Font.h
 Fonts.h
 fp.h
 fpieee.h
 frame/log.h
 frame/req.h
 freetype/freetype.h
 freetype/ftcache.h
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,51 +2,31 @@ 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.6.4 - 1.6.4)
-  pixman (0.10.x - pixman-0.10.0-8-g0b207ae)
-  glitz 0.5.2 (cvs - 2006-01-10)
+  cairo (1.6.4-350-g1a9809b)
+  pixman (pixman-0.11.8-7-gdb3fb5e)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
 ==== Patches ====
 
 Some specific things:
 
-cairo git commit ea6dbfd36f2182fda16cb82bca92007e0f7b8d77 - 
-  [cairo-meta-surface] Save and restore the original clip.
-
-cairo git commit d96fdd58abf8d6c8692dbb08ec54cdd80accba79 -
-  win32: Fix broken printing of type1 fonts
-
-cairo git commit 547e2f552cff264b943803d3a1ff03d05bde35c0
-  Fix win32-printing show_glyphs analysis for Type 1 fonts
-
-cairo git commit 158d24412bba99a4f57907d7fd22a86aae6e87af
-  Make win32-printing surface work with bitmap fonts
-
-cairo git commit d35d6eec24c1b7ab0a49149a51bf65ea8e223203
-  Fix win32 bitmap font metrics when device scale != 1
-
 max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
 
 win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
 
 nonfatal-assertions.patch: Make assertions non-fatal
 
 buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583.
 
-clip-clone.patch: _cairo_clip_init_deep_copy should pass 0,0 as the
-source coordinates to clone from since it wants an exact copy of the
-source's clipping surface
-
 ==== pixman patches ====
 
 endian.patch: include cairo-platform.h for endian macros
 
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -113,26 +113,28 @@ CSRCS   = \
         cairo-skiplist.c \
         cairo-slope.c \
         cairo-spline.c \
         cairo-stroke-style.c \
         cairo-surface.c \
         cairo-surface-fallback.c \
         cairo-traps.c \
         cairo-unicode.c \
+	cairo-user-font.c \
         cairo-wideint.c \
         $(NULL)
 
 EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
 
 # cairo-type1-subset.c should be here, but it's only supported on freetype platforms
 
 PSPDF_BASE_CSRCS = \
 	cairo-base85-stream.c \
 	cairo-type1-fallback.c \
+	cairo-type3-glyph-surface.c \
 	cairo-truetype-subset.c \
 	cairo-cff-subset.c \
 	$(NULL)
 
 PDF_CSRCS = \
 	cairo-pdf-surface.c \
 	cairo-pdf-operators.c \
 	$(NULL)
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -37,25 +37,37 @@
 
 #include "cairoint.h"
 
 cairo_private cairo_surface_t *
 _cairo_analysis_surface_create (cairo_surface_t		*target,
 				int			 width,
 				int			 height);
 
+cairo_private void
+_cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
+				 cairo_matrix_t  *ctm);
+
+cairo_private void
+_cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
+				 cairo_matrix_t  *ctm);
+
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *surface);
 
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_unsupported (cairo_surface_t *surface);
 
 cairo_private cairo_bool_t
 _cairo_analysis_surface_has_supported (cairo_surface_t *surface);
 
 cairo_private cairo_bool_t
 _cairo_analysis_surface_has_unsupported (cairo_surface_t *surface);
 
 cairo_private void
 _cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
 					  cairo_box_t     *bbox);
 
+
+cairo_private cairo_surface_t *
+_cairo_null_surface_create (cairo_content_t content);
+
 #endif /* CAIRO_ANALYSIS_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -79,17 +79,17 @@ static cairo_int_status_t
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
     surface_pattern = (cairo_surface_pattern_t *) pattern;
     assert (_cairo_surface_is_meta (surface_pattern->surface));
 
     old_width = surface->width;
     old_height = surface->height;
     old_clip = surface->current_clip;
     status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     surface->width = meta_extents.width;
     surface->height = meta_extents.height;
     surface->current_clip.x = 0;
     surface->current_clip.y = 0;
     surface->current_clip.width = surface->width;
     surface->current_clip.height = surface->height;
@@ -135,56 +135,41 @@ static cairo_int_status_t
 	    return CAIRO_STATUS_SUCCESS;
 	}
 	else
 	{
 	    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 	}
     }
 
+    _cairo_box_from_rectangle (&bbox, rect);
+
     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);
+	_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
 
-	x2 = ceil (x2) - rect->x;
-	y2 = ceil (y2) - rect->y;
-	if (x2 <= 0 || y2 <= 0) {
+	if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
 	    /* Even though the operation is not visible we must be
 	     * careful to not allow unsupported operations to be
 	     * replayed to the backend during
 	     * CAIRO_PAGINATED_MODE_RENDER */
 	    if (backend_status == CAIRO_STATUS_SUCCESS ||
 		backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
 	    {
 		return CAIRO_STATUS_SUCCESS;
 	    }
 	    else
 	    {
 		return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 	    }
 	}
 
-	rect->width  = x2;
-	rect->height = y2;
+	_cairo_box_round_to_rectangle (&bbox, rect);
     }
 
-    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;
     } else {
 	if (bbox.p1.x < surface->page_bbox.p1.x)
 	    surface->page_bbox.p1.x = bbox.p1.x;
 	if (bbox.p1.y < surface->page_bbox.p1.y)
 	    surface->page_bbox.p1.y = bbox.p1.y;
@@ -248,16 +233,18 @@ static cairo_int_status_t
 static cairo_status_t
 _cairo_analysis_surface_finish (void *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
     _cairo_region_fini (&surface->supported_region);
     _cairo_region_fini (&surface->fallback_region);
 
+    cairo_surface_destroy (surface->target);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 					     cairo_path_fixed_t *path,
 					     cairo_fill_rule_t   fill_rule,
 					     double		 tolerance,
@@ -314,17 +301,17 @@ static cairo_int_status_t
 	backend_status = (*surface->target->backend->paint) (surface->target, op,
                                                              source);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
@@ -372,17 +359,17 @@ static cairo_int_status_t
 										       mask);
 	    if (backend_status != CAIRO_STATUS_SUCCESS &&
 		backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
 		return backend_status;
 	}
     }
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
@@ -427,17 +414,17 @@ static cairo_int_status_t
 							      ctm, ctm_inverse,
 							      tolerance, antialias);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
@@ -506,17 +493,17 @@ static cairo_int_status_t
 						    source, path, fill_rule,
 						    tolerance, antialias);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
@@ -564,36 +551,130 @@ static cairo_int_status_t
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_operator_t	   op,
 				     cairo_pattern_t	  *source,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
-				     cairo_scaled_font_t  *scaled_font)
+				     cairo_scaled_font_t  *scaled_font,
+				     int                  *remaining_glyphs)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
 
-    if (!surface->target->backend->show_glyphs)
-	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    else
+    /* Adapted from _cairo_surface_show_glyphs */
+    if (surface->target->backend->show_glyphs)
 	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
-							   source,
-							   glyphs, num_glyphs,
-							   scaled_font);
+								   source,
+								   glyphs, num_glyphs,
+								   scaled_font,
+								   remaining_glyphs);
+    else if (surface->target->backend->show_text_glyphs)
+	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
+								     source,
+								     NULL, 0,
+								     glyphs, num_glyphs,
+								     NULL, 0,
+								     FALSE,
+								     scaled_font);
+    else
+	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
 									       source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status)
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &source_extents);
+    }
+
+    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
+							  glyphs,
+							  num_glyphs,
+							  &glyph_extents);
+	if (status)
+	    return status;
+
+	_cairo_rectangle_intersect (&extents, &glyph_extents);
+    }
+
+    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+
+    return status;
+}
+
+static cairo_bool_t
+_cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
+{
+    cairo_analysis_surface_t *surface = abstract_surface;
+
+    return _cairo_surface_has_show_text_glyphs (surface->target);
+}
+
+static cairo_int_status_t
+_cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
+					  cairo_operator_t	     op,
+					  cairo_pattern_t	    *source,
+					  const char		    *utf8,
+					  int			     utf8_len,
+					  cairo_glyph_t		    *glyphs,
+					  int			     num_glyphs,
+					  const cairo_text_cluster_t *clusters,
+					  int			     num_clusters,
+					  cairo_bool_t		     backward,
+					  cairo_scaled_font_t	    *scaled_font)
+{
+    cairo_analysis_surface_t *surface = abstract_surface;
+    cairo_status_t	     status, backend_status;
+    cairo_rectangle_int_t    extents, glyph_extents;
+
+    /* Adapted from _cairo_surface_show_glyphs */
+    backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (surface->target->backend->show_text_glyphs)
+	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
+								     source,
+								     utf8, utf8_len,
+								     glyphs, num_glyphs,
+								     clusters, num_clusters,
+								     backward,
+								     scaled_font);
+    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
+	int remaining_glyphs = num_glyphs;
+	backend_status = surface->target->backend->show_glyphs (surface->target, op,
+								source,
+								glyphs, num_glyphs,
+								scaled_font,
+								&remaining_glyphs);
+	glyphs += num_glyphs - remaining_glyphs;
+	num_glyphs = remaining_glyphs;
+	if (remaining_glyphs == 0)
+	    backend_status = CAIRO_STATUS_SUCCESS;
+    }
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+									       source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
@@ -645,16 +726,19 @@ static const cairo_surface_backend_t cai
     _cairo_analysis_surface_mask,
     _cairo_analysis_surface_stroke,
     _cairo_analysis_surface_fill,
     _cairo_analysis_surface_show_glyphs,
     NULL, /* snapshot */
     NULL, /* is_similar */
     NULL, /* reset */
     NULL, /* fill_stroke */
+    NULL, /* create_solid_pattern_surface */
+    _cairo_analysis_surface_has_show_text_glyphs,
+    _cairo_analysis_surface_show_text_glyphs
 };
 
 cairo_surface_t *
 _cairo_analysis_surface_create (cairo_surface_t		*target,
 				int			 width,
 				int			 height)
 {
     cairo_analysis_surface_t *surface;
@@ -668,31 +752,64 @@ cairo_surface_t *
     _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->target = cairo_surface_reference (target);
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
+
+    surface->page_bbox.p1.x = 0;
+    surface->page_bbox.p1.y = 0;
+    surface->page_bbox.p2.x = 0;
+    surface->page_bbox.p2.y = 0;
+
     _cairo_region_init (&surface->supported_region);
     _cairo_region_init (&surface->fallback_region);
 
-    surface->current_clip.x = 0;
-    surface->current_clip.y = 0;
-    surface->current_clip.width = width;
-    surface->current_clip.height = height;
+    if (width == -1 && height == -1) {
+	surface->current_clip.x      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.y      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+	surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    } else {
+	surface->current_clip.x = 0;
+	surface->current_clip.y = 0;
+	surface->current_clip.width = width;
+	surface->current_clip.height = height;
+    }
 
     return &surface->base;
 }
 
+cairo_private void
+_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
+				 cairo_matrix_t  *ctm)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    surface->ctm = *ctm;
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
+}
+
+cairo_private void
+_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
+				 cairo_matrix_t  *ctm)
+{
+    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+
+    *ctm = surface->ctm;
+}
+
+
 cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
     return &surface->supported_region;
 }
 
@@ -723,8 +840,113 @@ cairo_bool_t
 void
 _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface,
 					  cairo_box_t     *bbox)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
     *bbox = surface->page_bbox;
 }
+
+/* null surface type: a surface that does nothing (has no side effects, yay!) */
+
+static cairo_int_status_t
+_return_success (void)
+{
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* These typedefs are just to silence the compiler... */
+typedef cairo_int_status_t
+(*_set_clip_region_func)	(void			*surface,
+				 cairo_region_t		*region);
+typedef cairo_int_status_t
+(*_paint_func)			(void			*surface,
+			         cairo_operator_t	 op,
+				 cairo_pattern_t	*source);
+
+typedef cairo_int_status_t
+(*_mask_func)			(void			*surface,
+			         cairo_operator_t	 op,
+				 cairo_pattern_t	*source,
+				 cairo_pattern_t	*mask);
+
+typedef cairo_int_status_t
+(*_stroke_func)			(void			*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);
+
+typedef cairo_int_status_t
+(*_fill_func)			(void			*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);
+
+typedef cairo_int_status_t
+(*_show_glyphs_func)		(void			*surface,
+			         cairo_operator_t	 op,
+				 cairo_pattern_t	*source,
+				 cairo_glyph_t		*glyphs,
+				 int			 num_glyphs,
+				 cairo_scaled_font_t	*scaled_font,
+				 int			*remaining_glyphs);
+
+static const cairo_surface_backend_t cairo_null_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+
+    NULL, /* create_similar */
+    NULL, /* finish */
+    NULL, /* acquire_source_image */
+    NULL, /* release_source_image */
+    NULL, /* acquire_dest_image */
+    NULL, /* release_dest_image */
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    (_set_clip_region_func) _return_success, /* set_clip_region */
+    NULL, /* intersect_clip_path */
+    NULL, /* get_extents */
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+    (_paint_func) _return_success,	    /* paint */
+    (_mask_func) _return_success,	    /* mask */
+    (_stroke_func) _return_success,	    /* stroke */
+    (_fill_func) _return_success,	    /* fill */
+    (_show_glyphs_func) _return_success,    /* show_glyphs */
+    NULL, /* snapshot */
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL, /* fill_stroke */
+    NULL, /* create_solid_pattern_surface */
+    NULL, /* has_show_text_glyphs */
+    NULL  /* show_text_glyphs */
+};
+
+cairo_surface_t *
+_cairo_null_surface_create (cairo_content_t content)
+{
+    cairo_surface_t *surface;
+
+    surface = malloc (sizeof (cairo_surface_t));
+    if (surface == NULL) {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    _cairo_surface_init (surface, &cairo_null_surface_backend, content);
+
+    return surface;
+}
--- a/gfx/cairo/cairo/src/cairo-arc.c
+++ b/gfx/cairo/cairo/src/cairo-arc.c
@@ -176,23 +176,25 @@ static void
 _cairo_arc_in_direction (cairo_t	  *cr,
 			 double		   xc,
 			 double		   yc,
 			 double		   radius,
 			 double		   angle_min,
 			 double		   angle_max,
 			 cairo_direction_t dir)
 {
+    if (cairo_status (cr))
+        return;
+
     while (angle_max - angle_min > 4 * M_PI)
 	angle_max -= 2 * M_PI;
 
     /* Recurse if drawing arc larger than pi */
     if (angle_max - angle_min > M_PI) {
 	double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
-	/* XXX: Something tells me this block could be condensed. */
 	if (dir == CAIRO_DIRECTION_FORWARD) {
 	    _cairo_arc_in_direction (cr, xc, yc, radius,
 				     angle_min, angle_mid,
 				     dir);
 
 	    _cairo_arc_in_direction (cr, xc, yc, radius,
 				     angle_mid, angle_max,
 				     dir);
@@ -200,17 +202,17 @@ static void
 	    _cairo_arc_in_direction (cr, xc, yc, radius,
 				     angle_mid, angle_max,
 				     dir);
 
 	    _cairo_arc_in_direction (cr, xc, yc, radius,
 				     angle_min, angle_mid,
 				     dir);
 	}
-    } else {
+    } else if (angle_max != angle_min) {
 	cairo_matrix_t ctm;
 	int i, segments;
 	double angle, angle_step;
 
 	cairo_get_matrix (cr, &ctm);
 	segments = _arc_segments_needed (angle_max - angle_min,
 					 radius, &ctm,
 					 cairo_get_tolerance (cr));
--- a/gfx/cairo/cairo/src/cairo-array.c
+++ b/gfx/cairo/cairo/src/cairo-array.c
@@ -231,17 +231,17 @@ void
  * Append a single item onto the array by growing the array by at
  * least one element, then copying element_size bytes from @element
  * into the array. The address of the resulting object within the
  * array can be determined with:
  *
  * _cairo_array_index (array, _cairo_array_num_elements (array) - 1);
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
+ * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
  * operation.
  **/
 cairo_status_t
 _cairo_array_append (cairo_array_t	*array,
 		     const void		*element)
 {
     assert (! array->is_snapshot);
 
@@ -251,17 +251,17 @@ cairo_status_t
 /**
  * _cairo_array_append:
  *
  * Append one or more items onto the array by growing the array by
  * @num_elements, then copying @num_elements * element_size bytes from
  * @elements into the array.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
+ * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
  * operation.
  **/
 cairo_status_t
 _cairo_array_append_multiple (cairo_array_t	*array,
 			      const void	*elements,
 			      int		 num_elements)
 {
     cairo_status_t status;
@@ -282,17 +282,17 @@ cairo_status_t
  * _cairo_array_allocate:
  *
  * Allocate space at the end of the array for @num_elements additional
  * elements, providing the address of the new memory chunk in
  * @elements. This memory will be unitialized, but will be accounted
  * for in the return value of _cairo_array_num_elements().
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
+ * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
  * operation.
  **/
 cairo_status_t
 _cairo_array_allocate (cairo_array_t	 *array,
 		       unsigned int	  num_elements,
 		       void		**elements)
 {
     cairo_status_t status;
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -1,9 +1,10 @@
-/* cairo_output_stream.c: Output stream abstraction
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -503,17 +503,17 @@ det64_128 (cairo_int64_t a,
 
     return _cairo_int128_sub (ad, bc);
 }
 
 /* Compute the intersection of two lines as defined by two edges. The
  * result is provided as a coordinate pair of 128-bit integers.
  *
  * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
- * CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
+ * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
  */
 static cairo_bo_status_t
 intersect_lines (cairo_bo_edge_t		*a,
 		 cairo_bo_edge_t		*b,
 		 cairo_bo_intersect_point_t	*intersection)
 {
     cairo_int64_t a_det, b_det;
 
@@ -1209,17 +1209,17 @@ static cairo_status_t
 			int32_t			 top,
 			cairo_fill_rule_t	 fill_rule,
 			cairo_bo_traps_t	*bo_traps)
 {
     cairo_status_t status;
     int in_out = 0;
     cairo_bo_edge_t *edge;
 
-    for (edge = head; edge && edge->next; edge = edge->next) {
+    for (edge = head; edge; edge = edge->next) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING) {
 	    if (edge->reversed)
 		in_out++;
 	    else
 		in_out--;
 	    if (in_out == 0) {
 		status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
 		if (status)
@@ -1410,19 +1410,19 @@ update_minmax(cairo_fixed_t *inout_min,
 {
     if (v < *inout_min)
 	*inout_min = v;
     if (v > *inout_max)
 	*inout_max = v;
 }
 
 cairo_status_t
-_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	*traps,
-					   cairo_polygon_t	*polygon,
-					   cairo_fill_rule_t	 fill_rule)
+_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
+					   const cairo_polygon_t *polygon,
+					   cairo_fill_rule_t	  fill_rule)
 {
     int intersections;
     cairo_status_t status;
     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;
--- a/gfx/cairo/cairo/src/cairo-beos.h
+++ b/gfx/cairo/cairo/src/cairo-beos.h
@@ -31,17 +31,17 @@
  * <cbiesinger@web.de>
  *
  * Contributor(s):
  */
 
 #ifndef CAIRO_BEOS_H
 #define CAIRO_BEOS_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_BEOS_SURFACE
 
 #include <View.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -291,17 +291,17 @@ static void
  * @cache: a cache
  * @entry: an entry to be inserted
  *
  * Insert @entry into the cache. If an entry exists in the cache with
  * a matching key, then the old entry will be removed first, (and the
  * entry_destroy() callback will be called on it).
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
+ * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
  **/
 cairo_status_t
 _cairo_cache_insert (cairo_cache_t	 *cache,
 		     cairo_cache_entry_t *entry)
 {
     cairo_status_t status;
 
     _cairo_cache_shrink_to_accommodate (cache, entry->size);
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -269,23 +269,23 @@ cairo_status_t
 cairo_status_t
 _cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
 				cairo_operator_t              op,
 				cairo_surface_t               *dst,
 				int                           dst_x,
 				int                           dst_y,
 				const cairo_rectangle_int_t *extents)
 {
-    cairo_pattern_union_t pattern;
+    cairo_surface_pattern_t pattern;
     cairo_status_t status;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
+    _cairo_pattern_init_for_surface (&pattern, clip->surface);
 
     status = _cairo_surface_composite (op,
 				       &pattern.base,
 				       NULL,
 				       dst,
 				       extents->x - clip->surface_rect.x,
 				       extents->y - clip->surface_rect.y,
 				       0, 0,
@@ -480,18 +480,17 @@ static cairo_status_t
 	bounded by the mask.
 
     */
 
     surface = _cairo_surface_create_similar_solid (target,
 						   CAIRO_CONTENT_ALPHA,
 						   surface_rect.width,
 						   surface_rect.height,
-						   CAIRO_COLOR_TRANSPARENT,
-						   &pattern.base);
+						   CAIRO_COLOR_TRANSPARENT);
     if (surface->status) {
 	_cairo_pattern_fini (&pattern.base);
 	return surface->status;
     }
 
     /* Render the new clipping path into the new mask surface. */
 
     _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
@@ -625,17 +624,17 @@ void
         cairo_clip_path_t *clip_path = clip->path;
 	cairo_matrix_t matrix;
 
 	cairo_matrix_init_translate (&matrix,
 				     _cairo_fixed_to_double (tx),
 				     _cairo_fixed_to_double (ty));
 
         while (clip_path) {
-            _cairo_path_fixed_device_transform (&clip_path->path, &matrix);
+            _cairo_path_fixed_transform (&clip_path->path, &matrix);
             clip_path = clip_path->prev;
         }
     }
 }
 
 static cairo_status_t
 _cairo_clip_path_reapply_clip_path (cairo_clip_t      *clip,
                                     cairo_clip_path_t *clip_path)
@@ -673,17 +672,18 @@ cairo_status_t
 	    if (status)
 		goto BAIL;
 
 	    clip->has_region = TRUE;
         }
 
         if (other->surface) {
             status = _cairo_surface_clone_similar (target, other->surface,
-					           0, 0,
+					           0,
+						   0,
 						   other->surface_rect.width,
 						   other->surface_rect.height,
 						   &clip->surface);
 	    if (status)
 		goto BAIL;
 
             clip->surface_rect = other->surface_rect;
         }
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -106,17 +106,17 @@ CAIRO_BEGIN_DECLS
 #else
 # define CAIRO_FUNCTION_ALIAS(old, new)
 #endif
 
 #ifndef __GNUC__
 #define __attribute__(x)
 #endif
 
-#if defined(__WIN32__) || defined(_MSC_VER)
+#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
 #define snprintf _snprintf
 #endif
 
 #ifdef _MSC_VER
 #undef inline
 #define inline __inline
 #endif
 
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -56,20 +56,20 @@
  * objects, this call is likely to cause a crash, (eg. an assertion
  * failure due to a hash table being destroyed when non-empty).
  **/
 void
 cairo_debug_reset_static_data (void)
 {
     CAIRO_MUTEX_INITIALIZE ();
 
-    _cairo_font_reset_static_data ();
+    _cairo_font_face_reset_static_data ();
 
 #if CAIRO_HAS_FT_FONT
     _cairo_ft_font_reset_static_data ();
 #endif
 
-    _cairo_pattern_reset_static_data ();
+    _cairo_scaled_font_reset_static_data ();
 
-    _cairo_scaled_font_reset_static_data ();
+    _cairo_pattern_reset_static_data ();
 
     CAIRO_MUTEX_FINALIZE ();
 }
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-debug.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- *	Carl D. Worth <cworth@cworth.org>
- */
-
-#ifndef CAIRO_DEBUG_H
-#define CAIRO_DEBUG_H
-
-#include <cairo-features.h>
-#include <stdio.h>
-
-CAIRO_BEGIN_DECLS
-
-struct _cairo_path_fixed;
-struct _cairo_traps;
-struct _cairo_trapezoid;
-struct _cairo_clip;
-
-cairo_public void
-cairo_debug_reset_static_data (void);
-
-cairo_public void
-cairo_debug_dump_clip (struct _cairo_clip *clip,
-                       FILE *fp);
-cairo_public void
-cairo_debug_dump_path (struct _cairo_path_fixed *path,
-                       FILE *fp);
-
-cairo_public void
-cairo_debug_dump_traps (struct _cairo_traps *traps,
-                        FILE *fp);
-
-cairo_public void
-cairo_debug_dump_trapezoid_array (struct _cairo_trapezoid *traps,
-                                  int num_traps,
-                                  FILE *fp);
-
-CAIRO_END_DECLS
-
-#endif /* CAIRO_H */
--- a/gfx/cairo/cairo/src/cairo-deflate-stream.c
+++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c
@@ -1,9 +1,10 @@
-/* cairo_deflate_stream.c: Output stream abstraction
+/* -*- 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 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
--- a/gfx/cairo/cairo/src/cairo-deprecated.h
+++ b/gfx/cairo/cairo/src/cairo-deprecated.h
@@ -47,18 +47,16 @@
  * Additionally, the support for the RGB16_565 format was never
  * completely implemented. So while this format value is currently
  * deprecated, it may eventually acquire complete support in the future.
  */
 #define CAIRO_FORMAT_RGB16_565 4
 
 #define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
 
-#ifndef _CAIROINT_H_
-
 /* Obsolete functions. These definitions exist to coerce the compiler
  * into providing a little bit of guidance with its error
  * messages. The idea is to help users port their old code without
  * having to dig through lots of documentation.
  *
  * The first set of REPLACED_BY functions is for functions whose names
  * have just been changed. So fixing these up is mechanical, (and
  * automated by means of the cairo/util/cairo-api-update script.
@@ -132,11 +130,9 @@
 #define cairo_set_target_ps		cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create
 #define cairo_set_target_quartz		cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create
 #define cairo_set_target_win32		cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create
 #define cairo_set_target_xcb		cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create
 #define cairo_set_target_drawable	cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create
 #define cairo_get_status_string		cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
 #define cairo_status_string		cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
 
-#endif
-
 #endif /* CAIRO_DEPRECATED_H */
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -1601,17 +1601,18 @@ static void
 }
 
 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_scaled_font_t *scaled_font,
+				     int		 *remaining_glyphs)
 {
     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;
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -42,17 +42,17 @@
  *
  *  %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>
+#include "cairo.h"
 
 #ifdef  CAIRO_HAS_DIRECTFB_SURFACE
 
 #include <directfb.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-fixed-private.h
@@ -221,13 +221,24 @@ static inline cairo_fixed_16_16_t
 
 static inline cairo_fixed_t
 _cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
 {
     cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
     return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
 }
 
+/* computes a * b / c */
+static inline cairo_fixed_t
+_cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
+{
+    cairo_int64_t ab  = _cairo_int32x32_64_mul (a, b);
+    cairo_int64_t c64 = _cairo_int32_to_int64 (c);
+    cairo_int64_t quo = _cairo_int64_divrem (ab, c64).quo;
+
+    return _cairo_int64_to_int32(quo);
+}
+
 #else
 # error Please define multiplication and other operands for your fixed-point type size
 #endif
 
 #endif /* CAIRO_FIXED_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -58,16 +58,18 @@ const cairo_font_face_t _cairo_font_face
 
 cairo_status_t
 _cairo_font_face_set_error (cairo_font_face_t *font_face,
 	                    cairo_status_t     status)
 {
     if (status == CAIRO_STATUS_SUCCESS)
 	return status;
 
+    /* Don't overwrite an existing error. This preserves the first
+     * error, which is the most significant. */
     _cairo_status_set_error (&font_face->status, status);
 
     return _cairo_error (status);
 }
 
 void
 _cairo_font_face_init (cairo_font_face_t               *font_face,
 		       const cairo_font_face_backend_t *backend)
@@ -127,17 +129,18 @@ cairo_font_face_destroy (cairo_font_face
 	    CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
 	return;
 
     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
 
     if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
 	return;
 
-    font_face->backend->destroy (font_face);
+    if (font_face->backend->destroy)
+	font_face->backend->destroy (font_face);
 
     /* We allow resurrection to deal with some memory management for the
      * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
      * need to effectively mutually reference each other
      */
     if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
 	return;
 
@@ -529,17 +532,17 @@ void
 	return;
 
     unscaled_font->backend->destroy (unscaled_font);
 
     free (unscaled_font);
 }
 
 void
-_cairo_font_reset_static_data (void)
+_cairo_font_face_reset_static_data (void)
 {
     _cairo_scaled_font_map_destroy ();
 
     /* We manually acquire the lock rather than calling
      * cairo_toy_font_face_hash_table_lock simply to avoid
      * creating the table only to destroy it again. */
     CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
     _cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
--- a/gfx/cairo/cairo/src/cairo-font-options.c
+++ b/gfx/cairo/cairo/src/cairo-font-options.c
@@ -90,17 +90,16 @@ cairo_font_options_create (void)
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_font_options_t *) &_cairo_font_options_nil;
     }
 
     _cairo_font_options_init_default (options);
 
     return options;
 }
-slim_hidden_def (cairo_font_options_create);
 
 /**
  * cairo_font_options_copy:
  * @original: a #cairo_font_options_t
  *
  * Allocates a new font options object copying the option values from
  *  @original.
  *
@@ -139,17 +138,16 @@ cairo_font_options_copy (const cairo_fon
 void
 cairo_font_options_destroy (cairo_font_options_t *options)
 {
     if (cairo_font_options_status (options))
 	return;
 
     free (options);
 }
-slim_hidden_def (cairo_font_options_destroy);
 
 /**
  * cairo_font_options_status:
  * @options: a #cairo_font_options_t
  *
  * Checks whether an error has previously occurred for this
  * font options object
  *
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -1,8 +1,9 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2000 Keith Packard
  * Copyright © 2005 Red Hat, Inc
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
@@ -86,17 +87,17 @@ typedef struct _cairo_ft_font_transform 
  * just create a one-off version with a permanent face value.
  */
 
 typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
 
 struct _cairo_ft_unscaled_font {
     cairo_unscaled_font_t base;
 
-    cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
+    cairo_bool_t from_face; /* was the FT_Face provided by user? */
     FT_Face face;	    /* provided or cached face */
 
     /* only set if from_face is false */
     char *filename;
     int id;
 
     /* We temporarily scale the unscaled font as needed */
     cairo_bool_t have_scale;
@@ -277,27 +278,32 @@ static cairo_ft_unscaled_font_map_t *
 static void
 _cairo_ft_unscaled_font_map_unlock (void)
 {
     CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
 }
 
 static void
 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
+				  cairo_bool_t              from_face,
 				  char			   *filename,
-				  int			    id)
+				  int			    id,
+				  FT_Face		    face)
 {
     unsigned long hash;
 
+    key->from_face = from_face;
     key->filename = filename;
     key->id = id;
-
-    /* 1607 is just an arbitrary prime. */
+    key->face = face;
+
     hash = _cairo_hash_string (filename);
+    /* the constants are just arbitrary primes */
     hash += ((unsigned long) id) * 1607;
+    hash += ((unsigned long) face) * 2137;
 
     key->base.hash_entry.hash = hash;
 }
 
 /**
  * _cairo_ft_unscaled_font_init:
  *
  * Initialize a #cairo_ft_unscaled_font_t.
@@ -315,56 +321,48 @@ static void
  * Note that the code handles these two flavors in very distinct
  * ways. For example there is a hash_table mapping
  * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
  * parallel in the from_face case, (where the calling code would have
  * to do its own mapping to ensure similar sharing).
  **/
 static cairo_status_t
 _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
+			      cairo_bool_t              from_face,
 			      const char	       *filename,
 			      int			id,
 			      FT_Face			face)
 {
     _cairo_unscaled_font_init (&unscaled->base,
 			       &cairo_ft_unscaled_font_backend);
 
-    if (face) {
+    if (from_face) {
 	unscaled->from_face = TRUE;
-	unscaled->face = face;
-	unscaled->filename = NULL;
-	unscaled->id = 0;
+	_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
     } else {
 	char *filename_copy;
 
 	unscaled->from_face = FALSE;
 	unscaled->face = NULL;
 
 	filename_copy = strdup (filename);
 	if (filename_copy == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
+	_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
     }
 
     unscaled->have_scale = FALSE;
     CAIRO_MUTEX_INIT (unscaled->mutex);
     unscaled->lock_count = 0;
 
     unscaled->faces = NULL;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-cairo_bool_t
-_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
-{
-    return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
-}
-
 /**
  * _cairo_ft_unscaled_font_fini:
  *
  * Free all data associated with a #cairo_ft_unscaled_font_t.
  *
  * CAUTION: The unscaled->face field must be %NULL before calling this
  * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
  * count of these faces (font_map->num_open_faces) so it maintains the
@@ -386,45 +384,51 @@ static void
 
 static int
 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
 				    const void *key_b)
 {
     const cairo_ft_unscaled_font_t *unscaled_a = key_a;
     const cairo_ft_unscaled_font_t *unscaled_b = key_b;
 
-    return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
-	    unscaled_a->id == unscaled_b->id);
+    if (unscaled_a->id == unscaled_b->id &&
+	unscaled_a->from_face == unscaled_b->from_face)
+    {
+        if (unscaled_a->from_face)
+	    return unscaled_a->face == unscaled_b->face;
+
+	if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
+	    return TRUE;
+	else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
+	    return FALSE;
+	else
+	    return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
+    }
+
+    return FALSE;
 }
 
 /* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
  * pattern.  Returns a new reference to the unscaled font.
  */
 static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
+_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
+					 char *filename,
+					 int id,
+					 FT_Face font_face)
 {
     cairo_ft_unscaled_font_t key, *unscaled;
     cairo_ft_unscaled_font_map_t *font_map;
     cairo_status_t status;
-    FcChar8 *fc_filename;
-    char *filename;
-    int id;
-
-    if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
-	goto UNWIND;
-    filename = (char *) fc_filename;
-
-    if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
-	goto UNWIND;
 
     font_map = _cairo_ft_unscaled_font_map_lock ();
     if (font_map == NULL)
 	goto UNWIND;
 
-    _cairo_ft_unscaled_font_init_key (&key, filename, id);
+    _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
 
     /* Return existing unscaled font if it exists in the hash table. */
     if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
 				  (cairo_hash_entry_t **) &unscaled))
     {
 	_cairo_unscaled_font_reference (&unscaled->base);
 	_cairo_ft_unscaled_font_map_unlock ();
 	return unscaled;
@@ -432,17 +436,17 @@ static cairo_ft_unscaled_font_t *
 
     /* Otherwise create it and insert into hash table. */
     unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
     if (unscaled == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	goto UNWIND_FONT_MAP_LOCK;
     }
 
-    status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
+    status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
     if (status)
 	goto UNWIND_UNSCALED_MALLOC;
 
     status = _cairo_hash_table_insert (font_map->hash_table,
 				       &unscaled->base.hash_entry);
     if (status)
 	goto UNWIND_UNSCALED_FONT_INIT;
 
@@ -455,67 +459,76 @@ UNWIND_UNSCALED_FONT_INIT:
 UNWIND_UNSCALED_MALLOC:
     free (unscaled);
 UNWIND_FONT_MAP_LOCK:
     _cairo_ft_unscaled_font_map_unlock ();
 UNWIND:
     return NULL;
 }
 
+
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
+{
+    FT_Face font_face = NULL;
+    char *filename = NULL;
+    int id = 0;
+
+    if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
+	FcChar8 *fc_filename = NULL;
+
+	if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
+	    goto UNWIND;
+	filename = (char *) fc_filename;
+
+	if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
+	    goto UNWIND;
+    }
+
+    return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
+
+UNWIND:
+    return NULL;
+}
+
 static cairo_ft_unscaled_font_t *
 _cairo_ft_unscaled_font_create_from_face (FT_Face face)
 {
-    cairo_status_t status;
-    cairo_ft_unscaled_font_t *unscaled;
-
-    unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
-    if (unscaled == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
-
-    status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
-    if (status) {
-	free (unscaled);
-	return NULL;
-    }
-
-    return unscaled;
+    return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
 }
 
 static void
 _cairo_ft_unscaled_font_destroy (void *abstract_font)
 {
     cairo_ft_unscaled_font_t *unscaled  = abstract_font;
+    cairo_ft_unscaled_font_map_t *font_map;
 
     if (unscaled == NULL)
 	return;
 
+    font_map = _cairo_ft_unscaled_font_map_lock ();
+    /* All created objects must have been mapped in the font map. */
+    assert (font_map != NULL);
+
+    _cairo_hash_table_remove (font_map->hash_table,
+			      &unscaled->base.hash_entry);
+
     if (unscaled->from_face) {
 	/* See comments in _ft_font_face_destroy about the "zombie" state
 	 * for a _ft_font_face.
 	 */
 	if (unscaled->faces && !unscaled->faces->unscaled)
 	    cairo_font_face_destroy (&unscaled->faces->base);
-
-	unscaled->face = NULL;
     } else {
-	cairo_ft_unscaled_font_map_t *font_map;
-
-	font_map = _cairo_ft_unscaled_font_map_lock ();
-	/* All created objects must have been mapped in the font map. */
-	assert (font_map != NULL);
-
-	_cairo_hash_table_remove (font_map->hash_table,
-				  &unscaled->base.hash_entry);
-
 	_font_map_release_face_lock_held (font_map, unscaled);
-
-	_cairo_ft_unscaled_font_map_unlock ();
     }
+    unscaled->face = NULL;
+
+    _cairo_ft_unscaled_font_map_unlock ();
+
     _cairo_ft_unscaled_font_fini (unscaled);
 }
 
 static cairo_bool_t
 _has_unlocked_face (void *entry)
 {
     cairo_ft_unscaled_font_t *unscaled = entry;
 
@@ -574,30 +587,30 @@ FT_Face
     }
 
     unscaled->face = face;
 
     font_map->num_open_faces++;
 
     return face;
 }
-slim_hidden_def (cairo_ft_scaled_font_lock_face);
+
 
 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
  */
 void
 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
 {
     assert (unscaled->lock_count > 0);
 
     unscaled->lock_count--;
 
     CAIRO_MUTEX_UNLOCK (unscaled->mutex);
 }
-slim_hidden_def (cairo_ft_scaled_font_unlock_face);
+
 
 static cairo_status_t
 _compute_transform (cairo_ft_font_transform_t *sf,
 		    cairo_matrix_t      *scale)
 {
     cairo_status_t status;
     double x_scale, y_scale;
     cairo_matrix_t normalized = *scale;
@@ -606,17 +619,17 @@ static cairo_status_t
      * use as character scale values. These influence the way freetype
      * chooses hints, as well as selecting different bitmaps in
      * hand-rendered fonts. We also copy the normalized matrix to
      * freetype's transformation.
      */
 
     status = _cairo_matrix_compute_scale_factors (scale,
 						  &x_scale, &y_scale,
-						  /* XXX */ 1);
+						  1);
     if (status)
 	return status;
 
     /* FreeType docs say this about x_scale and y_scale:
      * "A character width or height smaller than 1pt is set to 1pt;"
      * So, we cap them from below at 1.0 and let the FT transform
      * take care of sub-1.0 scaling. */
     if (x_scale < 1.0)
@@ -1269,17 +1282,17 @@ static const cairo_unscaled_font_backend
 /* #cairo_ft_scaled_font_t */
 
 typedef struct _cairo_ft_scaled_font {
     cairo_scaled_font_t base;
     cairo_ft_unscaled_font_t *unscaled;
     cairo_ft_options_t ft_options;
 } cairo_ft_scaled_font_t;
 
-const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
+const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
 
 /* The load flags passed to FT_Load_Glyph control aspects like hinting and
  * antialiasing. Here we compute them from the fields of a FcPattern.
  */
 static void
 _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
 {
     FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
@@ -1514,17 +1527,17 @@ static cairo_status_t
     scaled_font->unscaled = unscaled;
 
     _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);
+				      &_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);
@@ -1592,17 +1605,17 @@ static cairo_status_t
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return status;
 }
 
 cairo_bool_t
 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
 {
-    return scaled_font->backend == &cairo_ft_scaled_font_backend;
+    return scaled_font->backend == &_cairo_ft_scaled_font_backend;
 }
 
 static cairo_status_t
 _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t	      *toy_face,
 				  const cairo_matrix_t	      *font_matrix,
 				  const cairo_matrix_t	      *ctm,
 				  const cairo_font_options_t  *font_options,
 				  cairo_scaled_font_t	     **font)
@@ -2164,59 +2177,55 @@ static cairo_int_status_t
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 #endif
 
     return status;
 }
 
 static cairo_int_status_t
-_cairo_ft_map_glyphs_to_unicode (void	                    *abstract_font,
-                                 cairo_scaled_font_subset_t *font_subset)
+_cairo_ft_index_to_ucs4(void	        *abstract_font,
+			unsigned long    index,
+			uint32_t	*ucs4)
 {
     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;
+    FT_ULong  charcode;
+    FT_UInt   gindex;
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
 	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);
+    *ucs4 = (uint32_t) -1;
+    charcode = FT_Get_First_Char(face, &gindex);
+    while (gindex != 0) {
+	charcode = FT_Get_Next_Char (face, charcode, &gindex);
+	if (gindex == index) {
+	    *ucs4 = charcode;
+	    break;
+	}
     }
+
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
+const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
     NULL,			/* text_to_glyphs */
     _cairo_ft_ucs4_to_index,
     NULL, 			/* show_glyphs */
     _cairo_ft_load_truetype_table,
-    _cairo_ft_map_glyphs_to_unicode,
+    _cairo_ft_index_to_ucs4
 };
 
 /* #cairo_ft_font_face_t */
 
 static void
 _cairo_ft_font_face_destroy (void *abstract_face)
 {
     cairo_ft_font_face_t *font_face = abstract_face;
@@ -2287,16 +2296,20 @@ static cairo_status_t
     /* The handling of font options is different depending on how the
      * font face was created. When the user creates a font face with
      * cairo_ft_font_face_create_for_ft_face(), then the load flags
      * passed in augment the load flags for the options.  But for
      * cairo_ft_font_face_create_for_pattern(), the load flags are
      * derived from a pattern where the user has called
      * cairo_ft_font_options_substitute(), so *just* use those load
      * flags and ignore the options.
+     *
+     * XXX two points about the above comment:
+     * 1. I don't see how the comment is relevant here,
+     * 2. What if the face is coming from FC_FT_FACE of a pattern?
      */
 
     ft_options = font_face->ft_options;
 
     return  _cairo_ft_scaled_font_create (font_face->unscaled,
 					  &font_face->base,
 					  font_matrix, ctm,
 					  options, ft_options,
@@ -2482,24 +2495,35 @@ cairo_ft_font_options_substitute (const 
  *   release your reference to the pattern with FcPatternDestroy() if
  *   you no longer need to access it.
  *
  * Creates a new font face for the FreeType font backend based on a
  * fontconfig pattern. This font can then be used with
  * cairo_set_font_face() or cairo_scaled_font_create(). The
  * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
  * also for the FreeType backend and can be used with functions such
- * as cairo_ft_font_lock_face().
+ * as cairo_ft_scaled_font_lock_face().
  *
  * Font rendering options are represented both here and when you
  * call cairo_scaled_font_create(). Font options that have a representation
  * in a #FcPattern must be passed in here; to modify #FcPattern
  * appropriately to reflect the options in a #cairo_font_options_t, call
  * cairo_ft_font_options_substitute().
  *
+ * The pattern's FC_FT_FACE element is inspected first and if that is set,
+ * that will be the FreeType font face associated with the returned cairo
+ * font face.  Otherwise the FC_FILE and FC_INDEX elements of @pattern are
+ * used to load a font face from file.
+ *
+ * If the FC_FT_FACE element of @pattern is set, the user is responsible
+ * for making sure that the referenced FT_Face remains valid for the life
+ * time of the returned #cairo_font_face_t.  See
+ * cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
+ * the life time of the FT_Face to that of the cairo font-face.
+ *
  * Return value: a newly created #cairo_font_face_t. Free with
  *  cairo_font_face_destroy() when you are done using it.
  **/
 cairo_font_face_t *
 cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
 {
     cairo_ft_unscaled_font_t *unscaled;
     cairo_font_face_t *font_face;
@@ -2534,17 +2558,33 @@ cairo_ft_font_face_create_for_pattern (F
  *   are useful. You should not pass any of the flags affecting
  *   the load target, such as %FT_LOAD_TARGET_LIGHT.
  *
  * Creates a new font face for the FreeType font backend from a
  * pre-opened FreeType face. This font can then be used with
  * cairo_set_font_face() or cairo_scaled_font_create(). The
  * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
  * also for the FreeType backend and can be used with functions such
- * as cairo_ft_font_lock_face().
+ * as cairo_ft_scaled_font_lock_face().
+ *
+ * As an example, here is how one might correctly couple the lifetime of
+ * the FreeType face object to the #cairo_font_face_t:
+ *
+ * <informalexample><programlisting>
+ * static const cairo_user_data_key_t key;
+ *
+ * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+ * status = cairo_font_face_set_user_data (font_face, &key,
+ *                                ft_face, (cairo_destroy_func_t) FT_Done_Face);
+ * if (status) {
+ *    cairo_font_face_destroy (font_face);
+ *    FT_Done_Face (ft_face);
+ *    return ERROR;
+ * }
+ * </programlisting></informalexample>
  *
  * Return value: a newly created #cairo_font_face_t. Free with
  *  cairo_font_face_destroy() when you are done using it.
  **/
 cairo_font_face_t *
 cairo_ft_font_face_create_for_ft_face (FT_Face         face,
 				       int             load_flags)
 {
@@ -2568,26 +2608,26 @@ cairo_ft_font_face_create_for_ft_face (F
     return font_face;
 }
 
 /**
  * cairo_ft_scaled_font_lock_face:
  * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
  *   object can be created by calling cairo_scaled_font_create() on a
  *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
- *   cairo_ft_font_face_create_for_face()).
+ *   cairo_ft_font_face_create_for_ft_face()).
  *
- * cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
+ * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
  * backend font and scales it appropriately for the font. You must
- * release the face with cairo_ft_font_unlock_face()
+ * release the face with cairo_ft_scaled_font_unlock_face()
  * when you are done using it.  Since the #FT_Face object can be
  * shared between multiple #cairo_scaled_font_t objects, you must not
  * lock any other font objects until you unlock this one. A count is
- * kept of the number of times cairo_ft_font_lock_face() is
- * called. cairo_ft_font_unlock_face() must be called the same number
+ * kept of the number of times cairo_ft_scaled_font_lock_face() is
+ * called. cairo_ft_scaled_font_unlock_face() must be called the same number
  * of times.
  *
  * You must be careful when using this function in a library or in a
  * threaded application, because freetype's design makes it unsafe to
  * call freetype functions simultaneously from multiple threads, (even
  * if using distinct FT_Face objects). Because of this, application
  * code that acquires an FT_Face object with this call must add it's
  * own locking to protect any use of that object, (and which also must
@@ -2600,16 +2640,21 @@ cairo_ft_font_face_create_for_ft_face (F
  **/
 FT_Face
 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
     FT_Face face;
     cairo_status_t status;
 
+    if (! _cairo_scaled_font_is_ft (abstract_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return NULL;
+    }
+
     if (scaled_font->base.status)
 	return NULL;
 
     face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
     if (face == NULL) {
 	status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
@@ -2642,16 +2687,21 @@ cairo_ft_scaled_font_lock_face (cairo_sc
  *
  * Releases a face obtained with cairo_ft_scaled_font_lock_face().
  **/
 void
 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
 
+    if (! _cairo_scaled_font_is_ft (abstract_font)) {
+	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+	return;
+    }
+
     if (scaled_font->base.status)
 	return;
 
     /* Note: We released the unscaled font's mutex at the end of
      * cairo_ft_scaled_font_lock_face, so we have to acquire it again
      * as _cairo_ft_unscaled_font_unlock_face expects it to be held
      * when we call into it. */
     CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
--- a/gfx/cairo/cairo/src/cairo-ft-private.h
+++ b/gfx/cairo/cairo/src/cairo-ft-private.h
@@ -32,29 +32,26 @@
  * Contributor(s):
  *      Graydon Hoare <graydon@redhat.com>
  *	Owen Taylor <otaylor@redhat.com>
  */
 
 #ifndef CAIRO_FT_PRIVATE_H
 #define CAIRO_FT_PRIVATE_H
 
-#include <cairo-ft.h>
-#include <cairoint.h>
+#include "cairo-ft.h"
+#include "cairoint.h"
 
 #if CAIRO_HAS_FT_FONT
 
 CAIRO_BEGIN_DECLS
 
 typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t;
 
 cairo_private cairo_bool_t
-_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font);
-
-cairo_private cairo_bool_t
 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font);
 
 /* These functions are needed by the PDF backend, which needs to keep track of the
  * the different fonts-on-disk used by a document, so it can embed them
  */
 cairo_private cairo_unscaled_font_t *
 _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *scaled_font);
 
@@ -62,15 +59,12 @@ cairo_private FT_Face
 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
 
 cairo_private void
 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
 
 cairo_private cairo_bool_t
 _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
 
-slim_hidden_proto (cairo_ft_scaled_font_lock_face);
-slim_hidden_proto (cairo_ft_scaled_font_unlock_face);
-
 CAIRO_END_DECLS
 
 #endif /* CAIRO_HAS_FT_FONT */
 #endif /* CAIRO_FT_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-ft.h
+++ b/gfx/cairo/cairo/src/cairo-ft.h
@@ -32,17 +32,17 @@
  * Contributor(s):
  *      Graydon Hoare <graydon@redhat.com>
  *	Owen Taylor <otaylor@redhat.com>
  */
 
 #ifndef CAIRO_FT_H
 #define CAIRO_FT_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_FT_FONT
 
 /* Fontconfig/Freetype platform-specific font interface */
 
 #include <fontconfig/fontconfig.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -953,17 +953,17 @@ static cairo_int_status_t
 				       unsigned int		        width,
 				       unsigned int		        height,
 				       cairo_glitz_surface_t	    **src_out,
 				       cairo_glitz_surface_t	    **mask_out,
 				       cairo_glitz_surface_attributes_t *sattr,
 				       cairo_glitz_surface_attributes_t *mattr)
 {
     cairo_int_status_t	  status;
-    cairo_pattern_union_t tmp;
+    cairo_solid_pattern_t tmp;
 
     /* If src and mask are both solid, then the mask alpha can be
      * combined into src and mask can be ignored. */
 
     /* XXX: This optimization assumes that there is no color
      * information in mask, so this will need to change when we
      * support RENDER-style 4-channel masks. */
 
@@ -972,20 +972,17 @@ static cairo_int_status_t
     {
 	cairo_color_t combined;
 	cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
 	cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
 
 	combined = src_solid->color;
 	_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
 
-	_cairo_pattern_init_solid (&tmp.solid, &combined,
-				   CAIRO_COLOR_IS_OPAQUE (&combined) ?
-				   CAIRO_CONTENT_COLOR :
-				   CAIRO_CONTENT_COLOR_ALPHA);
+	_cairo_pattern_init_solid (&tmp, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
 	mask = NULL;
     } else {
 	status = _cairo_pattern_init_copy (&tmp.base, src);
 	if (status)
 	    return status;
     }
 
@@ -1159,18 +1156,17 @@ static cairo_int_status_t
     default:
 	if (_glitz_ensure_target (dst->surface))
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	src = (cairo_glitz_surface_t *)
 	    _cairo_surface_create_similar_solid (&dst->base,
 						 CAIRO_CONTENT_COLOR_ALPHA,
 						 1, 1,
-						 (cairo_color_t *) color,
-						 NULL);
+						 (cairo_color_t *) color);
 	if (src->base.status)
 	    return src->base.status;
 
 	glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
 
 	while (n_rects--)
 	{
 	    glitz_composite (_glitz_operator (op),
--- a/gfx/cairo/cairo/src/cairo-glitz.h
+++ b/gfx/cairo/cairo/src/cairo-glitz.h
@@ -32,17 +32,17 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_GLITZ_H
 #define CAIRO_GLITZ_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_GLITZ_SURFACE
 
 #include <glitz.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -59,17 +59,18 @@ static cairo_status_t
 
 static void
 _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
 
 static void
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
-                                           cairo_glyph_t       *transformed_glyphs);
+                                           cairo_glyph_t       *transformed_glyphs,
+					   int		       *num_transformed_glyphs);
 
 cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
 		    cairo_surface_t *target)
 {
     cairo_status_t status;
 
     gstate->next = NULL;
@@ -198,99 +199,71 @@ void
 
     cairo_surface_destroy (gstate->original_target);
     gstate->original_target = NULL;
 
     cairo_pattern_destroy (gstate->source);
     gstate->source = NULL;
 }
 
-static void
-_cairo_gstate_destroy (cairo_gstate_t *gstate)
-{
-    _cairo_gstate_fini (gstate);
-    free (gstate);
-}
-
-/**
- * _cairo_gstate_clone:
- * @other: a #cairo_gstate_t to be copied, not %NULL.
- *
- * Create a new #cairo_gstate_t setting all graphics state parameters
- * to the same values as contained in @other. gstate->next will be set
- * to %NULL and may be used by the caller to chain #cairo_gstate_t
- * objects together.
- *
- * Return value: a new #cairo_gstate_t or %NULL if there is insufficient
- * memory.
- **/
-static cairo_status_t
-_cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
-{
-    cairo_status_t status;
-    cairo_gstate_t *gstate;
-
-    assert (other != NULL);
-
-    gstate = malloc (sizeof (cairo_gstate_t));
-    if (gstate == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = _cairo_gstate_init_copy (gstate, other);
-    if (status) {
-	free (gstate);
-	return status;
-    }
-
-    *out = gstate;
-    return CAIRO_STATUS_SUCCESS;
-}
-
 /**
  * _cairo_gstate_save:
  * @gstate: input/output gstate pointer
  *
  * Makes a copy of the current state of @gstate and saves it
  * to @gstate->next, then put the address of the newly allcated
  * copy into @gstate.  _cairo_gstate_restore() reverses this.
  **/
 cairo_status_t
-_cairo_gstate_save (cairo_gstate_t **gstate)
+_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
 {
-    cairo_gstate_t *top = NULL;
+    cairo_gstate_t *top;
     cairo_status_t status;
 
-    status = _cairo_gstate_clone (*gstate, &top);
-    if (status)
+    top = *freelist;
+    if (top == NULL) {
+	top = malloc (sizeof (cairo_gstate_t));
+	if (top == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else
+	*freelist = top->next;
+
+    status = _cairo_gstate_init_copy (top, *gstate);
+    if (status) {
+	top->next = *freelist;
+	*freelist = top;
 	return status;
+    }
 
     top->next = *gstate;
     *gstate = top;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_gstate_restore:
  * @gstate: input/output gstate pointer
  *
  * Reverses the effects of one _cairo_gstate_save() call.
  **/
 cairo_status_t
-_cairo_gstate_restore (cairo_gstate_t **gstate)
+_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
 {
     cairo_gstate_t *top;
 
     top = *gstate;
     if (top->next == NULL)
 	return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);
 
     *gstate = top->next;
 
-    _cairo_gstate_destroy (top);
+    _cairo_gstate_fini (top);
+    top->next = *freelist;
+    *freelist = top;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_gstate_redirect_target:
  * @gstate: a #cairo_gstate_t
  * @child: the new child target
@@ -817,25 +790,26 @@ static cairo_status_t
     cairo_surface_pattern_t *surface_pattern;
     cairo_surface_t *surface;
     cairo_status_t status;
 
     status = _cairo_pattern_init_copy (pattern, original);
     if (status)
 	return status;
 
-    _cairo_pattern_transform (pattern, ctm_inverse);
-
+    /* apply device_transform first so that it is transformed by ctm_inverse */
     if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
         surface_pattern = (cairo_surface_pattern_t *) original;
         surface = surface_pattern->surface;
         if (_cairo_surface_has_device_transform (surface))
             _cairo_pattern_transform (pattern, &surface->device_transform);
     }
 
+    _cairo_pattern_transform (pattern, ctm_inverse);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_gstate_copy_transformed_source (cairo_gstate_t  *gstate,
 				       cairo_pattern_t *pattern)
 {
     return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
@@ -1169,31 +1143,42 @@ cairo_status_t
 cairo_status_t
 _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     return _cairo_clip_clip (&gstate->clip,
 			     path, gstate->fill_rule, gstate->tolerance,
 			     gstate->antialias, gstate->target);
 }
 
+static cairo_status_t
+_cairo_gstate_int_clip_extents (cairo_gstate_t        *gstate,
+				cairo_rectangle_int_t *extents)
+{
+    cairo_status_t status;
+
+    status = _cairo_surface_get_extents (gstate->target, extents);
+    if (status)
+        return status;
+
+    status = _cairo_clip_intersect_to_rectangle (&gstate->clip, extents);
+
+    return status;
+}
+
 cairo_status_t
 _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
 		            double         *x1,
 		            double         *y1,
         		    double         *x2,
         		    double         *y2)
 {
     cairo_rectangle_int_t extents;
     cairo_status_t status;
     
-    status = _cairo_surface_get_extents (gstate->target, &extents);
-    if (status)
-        return status;
-
-    status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
+    status = _cairo_gstate_int_clip_extents (gstate, &extents);
     if (status)
         return status;
 
     if (x1)
 	*x1 = extents.x;
     if (y1)
 	*y1 = extents.y;
     if (x2)
@@ -1508,20 +1493,31 @@ cairo_status_t
 
     cairo_scaled_font_glyph_extents (gstate->scaled_font,
 				     glyphs, num_glyphs,
 				     extents);
 
     return cairo_scaled_font_status (gstate->scaled_font);
 }
 
+cairo_bool_t
+_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
+{
+    return _cairo_surface_has_show_text_glyphs (gstate->target);
+}
+
 cairo_status_t
-_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
-			   const cairo_glyph_t *glyphs,
-			   int num_glyphs)
+_cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
+				const char		   *utf8,
+				int			    utf8_len,
+				const cairo_glyph_t	   *glyphs,
+				int			    num_glyphs,
+				const cairo_text_cluster_t *clusters,
+				int			    num_clusters,
+				cairo_bool_t		    backward)
 {
     cairo_status_t status;
     cairo_pattern_union_t source_pattern;
     cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1538,28 +1534,67 @@ cairo_status_t
 	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);
+                                               transformed_glyphs, &num_glyphs);
+
+    if (!num_glyphs)
+	goto CLEANUP_GLYPHS;
 
     status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
     if (status)
 	goto CLEANUP_GLYPHS;
 
-    status = _cairo_surface_show_glyphs (gstate->target,
-					 gstate->op,
-					 &source_pattern.base,
-					 transformed_glyphs,
-					 num_glyphs,
-					 gstate->scaled_font);
+    /* For really huge font sizes, we can just do path;fill instead of
+     * show_glyphs, as show_glyphs would put excess pressure on the cache,
+     * and moreover, not all components below us correctly handle huge font
+     * sizes.  I wanted to set the limit at 256.  But alas, seems like cairo's
+     * rasterizer is something like ten times slower than freetype's for huge
+     * sizes.  So, no win just yet.  For now, do it for insanely-huge sizes,
+     * just to make sure we don't make anyone unhappy.  When we get a really
+     * fast rasterizer in cairo, we may want to readjust this.
+     *
+     * Needless to say, do this only if show_text_glyphs is not available. */
+    if (_cairo_gstate_has_show_text_glyphs (gstate) ||
+	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
+	status = _cairo_surface_show_text_glyphs (gstate->target,
+						  gstate->op,
+						  &source_pattern.base,
+						  utf8, utf8_len,
+						  transformed_glyphs, num_glyphs,
+						  clusters, num_clusters,
+						  backward,
+						  gstate->scaled_font);
+    } else {
+	cairo_path_fixed_t path;
+
+	_cairo_path_fixed_init (&path);
+
+	CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
+	status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
+						transformed_glyphs, num_glyphs,
+						&path);
+	CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
+
+	if (status == CAIRO_STATUS_SUCCESS)
+	  status = _cairo_surface_fill (gstate->target,
+					gstate->op,
+					&source_pattern.base,
+					&path,
+					CAIRO_FILL_RULE_WINDING,
+					gstate->tolerance,
+					gstate->scaled_font->options.antialias);
+
+	_cairo_path_fixed_fini (&path);
+    }
 
     _cairo_pattern_fini (&source_pattern.base);
 
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       free (transformed_glyphs);
 
     return status;
@@ -1582,17 +1617,17 @@ cairo_status_t
     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);
+                                               transformed_glyphs, NULL);
 
     CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
 					    path);
     CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
     if (transformed_glyphs != stack_transformed_glyphs)
@@ -1618,63 +1653,126 @@ cairo_antialias_t
 
 /**
  * _cairo_gstate_transform_glyphs_to_backend:
  * @gstate: a #cairo_gstate_t
  * @glyphs: the array of #cairo_glyph_t objects to be transformed
  * @num_glyphs: the number of elements in @glyphs
  * @transformed_glyphs: a pre-allocated array of at least @num_glyphs
  * #cairo_glyph_t objects
+ * @num_transformed_glyphs: the number of elements in @transformed_glyphs
+ * after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be
+ * dropped
  *
  * Transform an array of glyphs to backend space by first adding the offset
  * of the font matrix, then transforming from user space to backend space.
  * The result of the transformation is placed in @transformed_glyphs.
+ *
+ * This also uses information from the scaled font and the surface to
+ * cull/drop glyphs that will not be visible.
  **/
 static void
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
-                                           cairo_glyph_t *transformed_glyphs)
+                                           cairo_glyph_t       *transformed_glyphs,
+					   int		       *num_transformed_glyphs)
 {
-    int i;
+    int i, j;
     cairo_matrix_t *ctm = &gstate->ctm;
+    cairo_matrix_t *font_matrix = &gstate->font_matrix;
     cairo_matrix_t *device_transform = &gstate->target->device_transform;
+    cairo_bool_t drop = FALSE;
+    double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+    if (num_transformed_glyphs != NULL) {
+	cairo_rectangle_int_t surface_extents;
+	double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
+
+	drop = TRUE;
+
+	if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
+	    drop = FALSE; /* unbounded surface */
+	else {
+	    if (surface_extents.width == 0 || surface_extents.height == 0) {
+	      /* No visible area.  Don't draw anything */
+	      *num_transformed_glyphs = 0;
+	      return;
+	    }
+	    /* XXX We currently drop any glyphs that has its position outside
+	     * of the surface boundaries by a safety margin depending on the
+	     * font scale.  This however can fail in extreme cases where the
+	     * font has really long swashes for example...  We can correctly
+	     * handle that by looking the glyph up and using its device bbox
+	     * to device if it's going to be visible, but I'm not inclined to
+	     * do that now.
+	     */
+	    x1 = surface_extents.x - 2*scale;
+	    y1 = surface_extents.y - 2*scale;
+	    x2 = surface_extents.x + surface_extents.width  + scale;
+	    y2 = surface_extents.y + surface_extents.height + scale;
+	}
+
+	if (!drop)
+	    *num_transformed_glyphs = num_glyphs;
+    } else
+	num_transformed_glyphs = &j;
+
+#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
 
     if (_cairo_matrix_is_identity (ctm) &&
         _cairo_matrix_is_identity (device_transform) &&
-	gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
+	font_matrix->x0 == 0 && font_matrix->y0 == 0)
     {
-        memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+	if (!drop)
+	    memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+	else {
+	    for (j = 0, i = 0; i < num_glyphs; i++)
+	    {
+		transformed_glyphs[j].index = glyphs[i].index;
+		transformed_glyphs[j].x = glyphs[i].x;
+		transformed_glyphs[j].y = glyphs[i].y;
+		if (KEEP_GLYPH (transformed_glyphs[j]))
+		    j++;
+	    }
+	    *num_transformed_glyphs = j;
+	}
     }
     else if (_cairo_matrix_is_translation (ctm) &&
              _cairo_matrix_is_translation (device_transform))
     {
-        double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
-        double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
+        double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
+        double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
 
-        for (i = 0; i < num_glyphs; i++)
+        for (j = 0, i = 0; i < num_glyphs; i++)
         {
-            transformed_glyphs[i].index = glyphs[i].index;
-            transformed_glyphs[i].x = glyphs[i].x + tx;
-            transformed_glyphs[i].y = glyphs[i].y + ty;
+            transformed_glyphs[j].index = glyphs[i].index;
+            transformed_glyphs[j].x = glyphs[i].x + tx;
+            transformed_glyphs[j].y = glyphs[i].y + ty;
+	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+		j++;
         }
+	*num_transformed_glyphs = j;
     }
     else
     {
         cairo_matrix_t aggregate_transform;
 
         cairo_matrix_init_translate (&aggregate_transform,
                                      gstate->font_matrix.x0,
                                      gstate->font_matrix.y0);
         cairo_matrix_multiply (&aggregate_transform,
                                &aggregate_transform, ctm);
         cairo_matrix_multiply (&aggregate_transform,
                                &aggregate_transform, device_transform);
 
-        for (i = 0; i < num_glyphs; i++)
+        for (j = 0, i = 0; i < num_glyphs; i++)
         {
-            transformed_glyphs[i] = glyphs[i];
+            transformed_glyphs[j] = glyphs[i];
             cairo_matrix_transform_point (&aggregate_transform,
-                                          &transformed_glyphs[i].x,
-                                          &transformed_glyphs[i].y);
+                                          &transformed_glyphs[j].x,
+                                          &transformed_glyphs[j].y);
+	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+		j++;
         }
+	*num_transformed_glyphs = j;
     }
 }
--- a/gfx/cairo/cairo/src/cairo-hash.c
+++ b/gfx/cairo/cairo/src/cairo-hash.c
@@ -291,17 +291,17 @@ static cairo_hash_entry_t **
  * _cairo_hash_table_resize:
  * @hash_table: a hash table
  *
  * Resize the hash table if the number of entries has gotten much
  * bigger or smaller than the ideal number of entries for the current
  * size.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if out of memory.
+ * %CAIRO_STATUS_NO_MEMORY if out of memory.
  **/
 static cairo_status_t
 _cairo_hash_table_resize  (cairo_hash_table_t *hash_table)
 {
     cairo_hash_table_t tmp;
     cairo_hash_entry_t **entry;
     unsigned long new_size, i;
 
@@ -396,17 +396,17 @@ cairo_bool_t
  * entries in the hash table in a pseudo-random order. Walking
  * linearly would favor entries following gaps in the hash table. We
  * could also call rand() repeatedly, which works well for almost-full
  * tables, but degrades when the table is almost empty, or predicate
  * returns %TRUE for most entries.
  *
  * Return value: a random live entry or %NULL if there are no entries
  * that match the given predicate. In particular, if predicate is
- * NULL, a %NULL return value indicates that the table is empty.
+ * %NULL, a %NULL return value indicates that the table is empty.
  **/
 void *
 _cairo_hash_table_random_entry (cairo_hash_table_t	   *hash_table,
 				cairo_hash_predicate_func_t predicate)
 {
     cairo_hash_entry_t **entry;
     unsigned long hash;
     unsigned long table_size, i, idx, step;
@@ -454,17 +454,17 @@ void *
  * WARNING: It is a fatal error to insert an element while
  * an iterator is running
  *
  * Instead of using insert to replace an entry, consider just editing
  * the entry obtained with _cairo_hash_table_lookup. Or if absolutely
  * necessary, use _cairo_hash_table_remove first.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
+ * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
  **/
 cairo_status_t
 _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
 			  cairo_hash_entry_t *key_and_value)
 {
     cairo_status_t status;
     cairo_hash_entry_t **entry;
 
@@ -499,17 +499,17 @@ cairo_status_t
  * @hash_table: a hash table
  * @key: key of entry to be removed
  *
  * Remove an entry from the hash table which has a key that matches
  * @key, if any (as determined by the keys_equal() function passed to
  * _cairo_hash_table_create).
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
- * CAIRO_STATUS_NO_MEMORY if out of memory.
+ * %CAIRO_STATUS_NO_MEMORY if out of memory.
  **/
 void
 _cairo_hash_table_remove (cairo_hash_table_t *hash_table,
 			  cairo_hash_entry_t *key)
 {
     cairo_hash_entry_t **entry;
 
     entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE);
--- a/gfx/cairo/cairo/src/cairo-hull.c
+++ b/gfx/cairo/cairo/src/cairo-hull.c
@@ -31,65 +31,56 @@
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
 
-typedef struct cairo_hull
-{
+typedef struct cairo_hull {
     cairo_point_t point;
     cairo_slope_t slope;
     int discard;
     int id;
 } cairo_hull_t;
 
-static cairo_status_t
-_cairo_hull_create (cairo_pen_vertex_t	     *vertices,
-	            int			      num_vertices,
-		    cairo_hull_t	    **out)
+static void
+_cairo_hull_init (cairo_hull_t			*hull,
+	          cairo_pen_vertex_t		*vertices,
+		  int				 num_vertices)
 {
+    cairo_point_t *p, *extremum, tmp;
     int i;
-    cairo_hull_t *hull;
-    cairo_point_t *p, *extremum, tmp;
 
     extremum = &vertices[0].point;
     for (i = 1; i < num_vertices; i++) {
 	p = &vertices[i].point;
 	if (p->y < extremum->y || (p->y == extremum->y && p->x < extremum->x))
 	    extremum = p;
     }
     /* Put the extremal point at the beginning of the array */
     tmp = *extremum;
     *extremum = vertices[0].point;
     vertices[0].point = tmp;
 
-    hull = _cairo_malloc_ab (num_vertices, sizeof (cairo_hull_t));
-    if (hull == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
     for (i = 0; i < num_vertices; i++) {
 	hull[i].point = vertices[i].point;
 	_cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point);
 
         /* give each point a unique id for later comparison */
         hull[i].id = i;
 
         /* Don't discard by default */
         hull[i].discard = 0;
 
 	/* Discard all points coincident with the extremal point */
 	if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0)
 	    hull[i].discard = 1;
     }
-
-    *out = hull;
-    return CAIRO_STATUS_SUCCESS;
 }
 
 static int
 _cairo_hull_vertex_compare (const void *av, const void *bv)
 {
     cairo_hull_t *a = (cairo_hull_t *) av;
     cairo_hull_t *b = (cairo_hull_t *) bv;
     int ret;
@@ -191,27 +182,34 @@ static void
     *num_vertices = j;
 }
 
 /* Given a set of vertices, compute the convex hull using the Graham
    scan algorithm. */
 cairo_status_t
 _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
 {
-    cairo_status_t status;
-    cairo_hull_t *hull = NULL;
+    cairo_hull_t hull_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_hull_t)];
+    cairo_hull_t *hull;
     int num_hull = *num_vertices;
 
-    status = _cairo_hull_create (vertices, num_hull, &hull);
-    if (status)
-	return status;
+    if (num_hull > ARRAY_LENGTH (hull_stack)) {
+	hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t));
+	if (hull == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else {
+	hull = hull_stack;
+    }
+
+    _cairo_hull_init (hull, vertices, num_hull);
 
     qsort (hull + 1, num_hull - 1,
 	   sizeof (cairo_hull_t), _cairo_hull_vertex_compare);
 
     _cairo_hull_eliminate_concave (hull, num_hull);
 
     _cairo_hull_to_pen (hull, vertices, num_vertices);
 
-    free (hull);
+    if (hull != hull_stack)
+	free (hull);
 
     return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -119,17 +119,17 @@ cairo_surface_t *
 					      pixman_format_code_t	 pixman_format)
 {
     cairo_image_surface_t *surface;
 
     surface = malloc (sizeof (cairo_image_surface_t));
     if (surface == NULL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    _cairo_surface_init (&surface->base, &cairo_image_surface_backend,
+    _cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
 			 _cairo_content_from_pixman_format (pixman_format));
 
     surface->pixman_image = pixman_image;
 
     surface->pixman_format = pixman_format;
     surface->format = _cairo_format_from_pixman_format (pixman_format);
     surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
     surface->owns_data = FALSE;
@@ -387,17 +387,18 @@ cairo_surface_t *
  * <informalexample><programlisting>
  * int stride;
  * unsigned char *data;
  * #cairo_surface_t *surface;
  *
  * stride = cairo_format_stride_for_width (format, width);
  * data = malloc (stride * height);
  * surface = cairo_image_surface_create_for_data (data, format,
- *						  width, height);
+ *						  width, height,
+ *						  stride);
  * </programlisting></informalexample>
  *
  * Return value: the appropriate stride to use given the desired
  * format and width, or -1 if either the format is invalid or the width
  * too large.
  *
  * Since: 1.6
  **/
@@ -1187,17 +1188,17 @@ static cairo_int_status_t
 }
 
 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))
+    if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     surface->has_clip = region != NULL;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
@@ -1241,20 +1242,20 @@ static cairo_status_t
  *
  * Checks if a surface is an #cairo_image_surface_t
  *
  * Return value: %TRUE if the surface is an image surface
  **/
 cairo_bool_t
 _cairo_surface_is_image (const cairo_surface_t *surface)
 {
-    return surface->backend == &cairo_image_surface_backend;
+    return surface->backend == &_cairo_image_surface_backend;
 }
 
-const cairo_surface_backend_t cairo_image_surface_backend = {
+const cairo_surface_backend_t _cairo_image_surface_backend = {
     CAIRO_SURFACE_TYPE_IMAGE,
     _cairo_image_surface_create_similar,
     _cairo_image_surface_finish,
     _cairo_image_surface_acquire_source_image,
     _cairo_image_surface_release_source_image,
     _cairo_image_surface_acquire_dest_image,
     _cairo_image_surface_release_dest_image,
     _cairo_image_surface_clone_similar,
--- a/gfx/cairo/cairo/src/cairo-lzw.c
+++ b/gfx/cairo/cairo/src/cairo-lzw.c
@@ -77,17 +77,17 @@ static void
 	buf->data_size = 0;
 	buf->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return;
     }
 }
 
 /* Increase the buffer size by doubling.
  *
- * Returns %CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
+ * Returns %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
  */
 static cairo_status_t
 _lzw_buf_grow (lzw_buf_t *buf)
 {
     int new_size = buf->data_size * 2;
     unsigned char *new_data;
 
     if (buf->status)
--- a/gfx/cairo/cairo/src/cairo-matrix.c
+++ b/gfx/cairo/cairo/src/cairo-matrix.c
@@ -418,16 +418,28 @@ void
         *is_tight =
             (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
              quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
             (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
              quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
     }
 }
 
+cairo_private void
+_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
+					    cairo_box_t          *bbox,
+					    cairo_bool_t *is_tight)
+{
+    double x1, y1, x2, y2;
+
+    _cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
+    _cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
+    _cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
+}
+
 static void
 _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
 {
     matrix->xx *= scalar;
     matrix->yx *= scalar;
 
     matrix->xy *= scalar;
     matrix->yy *= scalar;
@@ -473,37 +485,37 @@ static void
 cairo_status_t
 cairo_matrix_invert (cairo_matrix_t *matrix)
 {
     /* inv (A) = 1/det (A) * adj (A) */
     double det;
 
     _cairo_matrix_compute_determinant (matrix, &det);
 
-    if (det == 0)
+    if (! ISFINITE (det))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
-    if (! ISFINITE (det))
+    if (det == 0)
 	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. && ISFINITE (det);
+    return ISFINITE (det) && det != 0.;
 }
 
 void
 _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
 				   double		*det)
 {
     double a, b, c, d;
 
@@ -708,16 +720,20 @@ cairo_bool_t
 
   Which is the solution to this problem.
 
   Walter Brisken
   2004/10/08
 
   (Note that the minor axis length is at the minimum of the above solution,
   which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
+
+
+  For another derivation of the same result, using Singular Value Decomposition,
+  see doc/tutorial/src/singular.c.
 */
 
 /* determine the length of the major axis of a circle of the given radius
    after applying the transformation matrix. */
 double
 _cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radius)
 {
     double  a, b, c, d, f, g, h, i, j;
--- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h
@@ -41,17 +41,17 @@
 #include "cairo-path-fixed-private.h"
 
 typedef enum {
     /* The 5 basic drawing operations. */
     CAIRO_COMMAND_PAINT,
     CAIRO_COMMAND_MASK,
     CAIRO_COMMAND_STROKE,
     CAIRO_COMMAND_FILL,
-    CAIRO_COMMAND_SHOW_GLYPHS,
+    CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
 
     /* Other junk. For most of these, we should be able to assert that
      * they never get called except as part of fallbacks for the 5
      * basic drawing operations (which we implement already so the
      * fallbacks should never get triggered). So the plan is to
      * eliminate as many of these as possible. */
 
     CAIRO_COMMAND_INTERSECT_CLIP_PATH
@@ -99,24 +99,29 @@ typedef struct _cairo_command_fill {
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
     cairo_path_fixed_t		 path;
     cairo_fill_rule_t		 fill_rule;
     double			 tolerance;
     cairo_antialias_t		 antialias;
 } cairo_command_fill_t;
 
-typedef struct _cairo_command_show_glyphs {
+typedef struct _cairo_command_show_text_glyphs {
     cairo_command_header_t       header;
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
+    char			*utf8;
+    int				 utf8_len;
     cairo_glyph_t		*glyphs;
     unsigned int		 num_glyphs;
+    cairo_text_cluster_t	*clusters;
+    int				 num_clusters;
+    cairo_bool_t		 backward;
     cairo_scaled_font_t		*scaled_font;
-} cairo_command_show_glyphs_t;
+} cairo_command_show_text_glyphs_t;
 
 typedef struct _cairo_command_intersect_clip_path {
     cairo_command_header_t      header;
     cairo_path_fixed_t	       *path_pointer;
     cairo_path_fixed_t		path;
     cairo_fill_rule_t		fill_rule;
     double			tolerance;
     cairo_antialias_t		antialias;
@@ -125,17 +130,17 @@ typedef struct _cairo_command_intersect_
 typedef union _cairo_command {
     cairo_command_header_t      header;
 
     /* The 5 basic drawing operations. */
     cairo_command_paint_t			paint;
     cairo_command_mask_t			mask;
     cairo_command_stroke_t			stroke;
     cairo_command_fill_t			fill;
-    cairo_command_show_glyphs_t			show_glyphs;
+    cairo_command_show_text_glyphs_t		show_text_glyphs;
 
     /* The other junk. */
     cairo_command_intersect_clip_path_t		intersect_clip_path;
 } cairo_command_t;
 
 typedef struct _cairo_meta_surface {
     cairo_surface_t base;
 
@@ -154,16 +159,20 @@ typedef struct _cairo_meta_surface {
     int replay_start_idx;
 } cairo_meta_surface_t;
 
 cairo_private cairo_surface_t *
 _cairo_meta_surface_create (cairo_content_t	content,
 			    int			width_pixels,
 			    int			height_pixels);
 
+cairo_private cairo_int_status_t
+_cairo_meta_surface_get_path (cairo_surface_t	 *surface,
+			      cairo_path_fixed_t *path);
+
 cairo_private cairo_status_t
 _cairo_meta_surface_replay (cairo_surface_t *surface,
 			    cairo_surface_t *target);
 
 cairo_private cairo_status_t
 _cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
 						 cairo_surface_t *target);
 
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c
+++ b/gfx/cairo/cairo/src/cairo-meta-surface.c
@@ -34,17 +34,17 @@
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 /* A meta surface is a surface that records all drawing operations at
  * the highest level of the surface backend interface, (that is, the
- * level of paint, mask, stroke, fill, and show_glyphs). The meta
+ * level of paint, mask, stroke, fill, and show_text_glyphs). The meta
  * surface can then be "replayed" against any target surface with:
  *
  *	_cairo_meta_surface_replay (meta, target);
  *
  * after which the results in target will be identical to the results
  * that would have been obtained if the original operations applied to
  * the meta surface had instead been applied to the target surface.
  *
@@ -152,20 +152,22 @@ static cairo_status_t
 	    break;
 
 	case CAIRO_COMMAND_FILL:
 	    _cairo_pattern_fini (&command->fill.source.base);
 	    _cairo_path_fixed_fini (&command->fill.path);
 	    free (command);
 	    break;
 
-	case CAIRO_COMMAND_SHOW_GLYPHS:
-	    _cairo_pattern_fini (&command->show_glyphs.source.base);
-	    free (command->show_glyphs.glyphs);
-	    cairo_scaled_font_destroy (command->show_glyphs.scaled_font);
+	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
+	    _cairo_pattern_fini (&command->show_text_glyphs.source.base);
+	    free (command->show_text_glyphs.utf8);
+	    free (command->show_text_glyphs.glyphs);
+	    free (command->show_text_glyphs.clusters);
+	    cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font);
 	    free (command);
 	    break;
 
 	/* Other junk. */
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	    if (command->intersect_clip_path.path_pointer)
 		_cairo_path_fixed_fini (&command->intersect_clip_path.path);
 	    free (command);
@@ -421,76 +423,115 @@ static cairo_int_status_t
     _cairo_path_fixed_fini (&command->path);
   CLEANUP_SOURCE:
     _cairo_pattern_fini (&command->source.base);
   CLEANUP_COMMAND:
     free (command);
     return status;
 }
 
+static cairo_bool_t
+_cairo_meta_surface_has_show_text_glyphs (void *abstract_surface)
+{
+    return TRUE;
+}
+
 static cairo_int_status_t
-_cairo_meta_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_meta_surface_show_text_glyphs (void			    *abstract_surface,
+				      cairo_operator_t		     op,
+				      cairo_pattern_t		    *source,
+				      const char		    *utf8,
+				      int			     utf8_len,
+				      cairo_glyph_t		    *glyphs,
+				      int			     num_glyphs,
+				      const cairo_text_cluster_t    *clusters,
+				      int			     num_clusters,
+				      cairo_bool_t		     backward,
+				      cairo_scaled_font_t	    *scaled_font)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
-    cairo_command_show_glyphs_t *command;
+    cairo_command_show_text_glyphs_t *command;
 
-    command = malloc (sizeof (cairo_command_show_glyphs_t));
+    command = malloc (sizeof (cairo_command_show_text_glyphs_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    command->header.type = CAIRO_COMMAND_SHOW_GLYPHS;
+    command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
     status = _init_pattern_with_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
-    command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-    if (command->glyphs == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto CLEANUP_SOURCE;
+    command->utf8 = NULL;
+    command->utf8_len = utf8_len;
+    command->glyphs = NULL;
+    command->num_glyphs = num_glyphs;
+    command->clusters = NULL;
+    command->num_clusters = num_clusters;
+
+    if (utf8_len) {
+	command->utf8 = malloc (utf8_len);
+	if (command->utf8 == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_ARRAYS;
+	}
+	memcpy (command->utf8, utf8, utf8_len);
     }
-    memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
+    if (num_glyphs) {
+	command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (glyphs[0]));
+	if (command->glyphs == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_ARRAYS;
+	}
+	memcpy (command->glyphs, glyphs, sizeof (glyphs[0]) * num_glyphs);
+    }
+    if (num_clusters) {
+	command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0]));
+	if (command->clusters == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_ARRAYS;
+	}
+	memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
+    }
 
-    command->num_glyphs = num_glyphs;
+    command->backward = backward;
 
     command->scaled_font = cairo_scaled_font_reference (scaled_font);
 
     status = _cairo_array_append (&meta->commands, &command);
     if (status)
 	goto CLEANUP_SCALED_FONT;
 
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_SCALED_FONT:
     cairo_scaled_font_destroy (command->scaled_font);
+  CLEANUP_ARRAYS:
+    free (command->utf8);
     free (command->glyphs);
-  CLEANUP_SOURCE:
+    free (command->clusters);
+
     _cairo_pattern_fini (&command->source.base);
   CLEANUP_COMMAND:
     free (command);
     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.
  *
  * The caller owns the return value and should call
- * cairo_surface_destroy when finished with it. This function will not
+ * cairo_surface_destroy() when finished with it. This function will not
  * return %NULL, but will return a nil surface instead.
  *
  * Return value: The snapshot surface.
  **/
 static cairo_surface_t *
 _cairo_meta_surface_snapshot (void *abstract_other)
 {
     cairo_meta_surface_t *other = abstract_other;
@@ -565,16 +606,19 @@ static cairo_int_status_t
  * replayed, (as passed in to _cairo_meta_surface_create).
  */
 static cairo_int_status_t
 _cairo_meta_surface_get_extents (void			 *abstract_surface,
 				 cairo_rectangle_int_t   *rectangle)
 {
     cairo_meta_surface_t *surface = abstract_surface;
 
+    if (surface->width_pixels == -1 && surface->height_pixels == -1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     rectangle->x = 0;
     rectangle->y = 0;
     rectangle->width = surface->width_pixels;
     rectangle->height = surface->height_pixels;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -613,47 +657,128 @@ static const cairo_surface_backend_t cai
     NULL, /* get_font_options */
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
 
     /* Here are the 5 basic drawing operations, (which are in some
      * sense the only things that cairo_meta_surface should need to
-     * implement). */
+     * implement).  However, we implement the more generic show_text_glyphs
+     * instead of show_glyphs.  One or the other is eough. */
 
     _cairo_meta_surface_paint,
     _cairo_meta_surface_mask,
     _cairo_meta_surface_stroke,
     _cairo_meta_surface_fill,
-    _cairo_meta_surface_show_glyphs,
+    NULL,
+
+    _cairo_meta_surface_snapshot,
 
-    _cairo_meta_surface_snapshot
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL, /* fill_stroke */
+    NULL, /* create_solid_pattern_surface */
+
+    _cairo_meta_surface_has_show_text_glyphs,
+    _cairo_meta_surface_show_text_glyphs
 };
 
 static cairo_path_fixed_t *
 _cairo_command_get_path (cairo_command_t *command)
 {
     switch (command->header.type) {
     case CAIRO_COMMAND_PAINT:
     case CAIRO_COMMAND_MASK:
-    case CAIRO_COMMAND_SHOW_GLYPHS:
+    case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
 	return NULL;
     case CAIRO_COMMAND_STROKE:
 	return &command->stroke.path;
     case CAIRO_COMMAND_FILL:
 	return &command->fill.path;
     case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	return command->intersect_clip_path.path_pointer;
     }
 
     ASSERT_NOT_REACHED;
     return NULL;
 }
 
+cairo_int_status_t
+_cairo_meta_surface_get_path (cairo_surface_t	 *surface,
+			      cairo_path_fixed_t *path)
+{
+    cairo_meta_surface_t *meta;
+    cairo_command_t *command, **elements;
+    int i, num_elements;
+    cairo_int_status_t status;
+
+    if (surface->status)
+	return surface->status;
+
+    meta = (cairo_meta_surface_t *) surface;
+    status = CAIRO_STATUS_SUCCESS;
+
+    num_elements = meta->commands.num_elements;
+    elements = _cairo_array_index (&meta->commands, 0);
+    for (i = meta->replay_start_idx; i < num_elements; i++) {
+	command = elements[i];
+
+	switch (command->header.type) {
+	case CAIRO_COMMAND_PAINT:
+	case CAIRO_COMMAND_MASK:
+	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	    break;
+
+	case CAIRO_COMMAND_STROKE:
+	{
+	    cairo_traps_t traps;
+
+	    _cairo_traps_init (&traps);
+
+	    /* XXX call cairo_stroke_to_path() when that is implemented */
+	    status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
+							&command->stroke.style,
+							&command->stroke.ctm,
+							&command->stroke.ctm_inverse,
+							command->stroke.tolerance,
+							&traps);
+
+	    if (status == CAIRO_STATUS_SUCCESS)
+		status = _cairo_traps_path (&traps, path);
+
+	    _cairo_traps_fini (&traps);
+	    break;
+	}
+	case CAIRO_COMMAND_FILL:
+	{
+	    status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD);
+	    break;
+	}
+	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
+	{
+	    status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
+						    command->show_text_glyphs.glyphs,
+						    command->show_text_glyphs.num_glyphs,
+						    path);
+	    break;
+	}
+
+	default:
+	    ASSERT_NOT_REACHED;
+	}
+
+	if (status)
+	    break;
+    }
+
+    return _cairo_surface_set_error (surface, status);
+}
+
 static cairo_status_t
 _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 				     cairo_surface_t	     *target,
 				     cairo_meta_replay_type_t type,
 				     cairo_meta_region_type_t region)
 {
     cairo_meta_surface_t *meta;
     cairo_command_t *command, **elements;
@@ -694,17 +819,17 @@ static cairo_status_t
 		break;
 	}
 
 	dev_path = _cairo_command_get_path (command);
 	if (dev_path && has_device_transform) {
 	    status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
 	    if (status)
 		break;
-	    _cairo_path_fixed_device_transform (&path_copy, device_transform);
+	    _cairo_path_fixed_transform (&path_copy, device_transform);
 	    dev_path = &path_copy;
 	}
 
 	switch (command->header.type) {
 	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_paint (target,
 					   command->paint.op,
 					   &command->paint.source.base);
@@ -793,23 +918,23 @@ static cairo_status_t
 					      command->fill.op,
 					      &command->fill.source.base,
 					      dev_path,
 					      command->fill.fill_rule,
 					      command->fill.tolerance,
 					      command->fill.antialias);
 	    break;
 	}
-	case CAIRO_COMMAND_SHOW_GLYPHS:
+	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
 	{
-	    cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
+	    cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
 	    cairo_glyph_t *dev_glyphs;
-	    int i, num_glyphs = command->show_glyphs.num_glyphs;
+	    int i, num_glyphs = command->show_text_glyphs.num_glyphs;
 
-            /* show_glyphs is special because _cairo_surface_show_glyphs is allowed
+            /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
 	     * to modify the glyph array that's passed in.  We must always
 	     * copy the array before handing it to the backend.
 	     */
 	    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
 	    if (dev_glyphs == NULL) {
 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 		break;
 	    }
@@ -820,21 +945,24 @@ static cairo_status_t
 		    cairo_matrix_transform_point (device_transform,
 						  &dev_glyphs[i].x,
 						  &dev_glyphs[i].y);
 		}
 	    } else {
 		memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	    }
 
-	    status = _cairo_surface_show_glyphs	(target,
-						 command->show_glyphs.op,
-						 &command->show_glyphs.source.base,
-						 dev_glyphs, num_glyphs,
-						 command->show_glyphs.scaled_font);
+	    status = _cairo_surface_show_text_glyphs	(target,
+							 command->show_text_glyphs.op,
+							 &command->show_text_glyphs.source.base,
+							 command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
+							 dev_glyphs, num_glyphs,
+							 command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
+							 command->show_text_glyphs.backward,
+							 command->show_text_glyphs.scaled_font);
 
 	    free (dev_glyphs);
 	    break;
 	}
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	    /* XXX Meta surface clipping is broken and requires some
 	     * cairo-gstate.c rewriting.  Work around it for now. */
 	    if (dev_path == NULL)
@@ -882,17 +1010,17 @@ cairo_status_t
     return _cairo_meta_surface_replay_internal (surface,
 						target,
 						CAIRO_META_REPLAY,
 						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
+ * %CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
  * will be stored in the meta surface. Any other status will abort the
  * replay and return the status.
  */
 cairo_status_t
 _cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface,
 					       cairo_surface_t *target)
 {
     return _cairo_meta_surface_replay_internal (surface,
--- a/gfx/cairo/cairo/src/cairo-misc.c
+++ b/gfx/cairo/cairo/src/cairo-misc.c
@@ -33,16 +33,18 @@
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
 
+COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
+COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
 
 /**
  * cairo_status_to_string:
  * @status: a cairo status
  *
  * Provides a human-readable description of a #cairo_status_t.
  *
  * Returns: a string representation of the status
@@ -96,16 +98,26 @@ cairo_status_to_string (cairo_status_t s
     case CAIRO_STATUS_INVALID_INDEX:
 	return "invalid index passed to getter";
     case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
         return "clip region not representable in desired format";
     case CAIRO_STATUS_TEMP_FILE_ERROR:
 	return "error creating or writing to a temporary file";
     case CAIRO_STATUS_INVALID_STRIDE:
 	return "invalid value for stride";
+    case CAIRO_STATUS_FONT_TYPE_MISMATCH:
+	return "the font type is not appropriate for the operation";
+    case CAIRO_STATUS_USER_FONT_IMMUTABLE:
+	return "the user-font is immutable";
+    case CAIRO_STATUS_USER_FONT_ERROR:
+	return "error occurred in a user-font callback function";
+    case CAIRO_STATUS_NEGATIVE_COUNT:
+	return "negative number used where it is not allowed";
+    case CAIRO_STATUS_INVALID_CLUSTERS:
+	return "input clusters do not represent the accompanying text and glyph arrays";
     }
 
     return "<unknown error status>";
 }
 
 /**
  * _cairo_operator_bounded_by_mask:
  * @op: a #cairo_operator_t
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h
@@ -0,0 +1,226 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005,2007 Red Hat, Inc.
+ * Copyright © 2007 Mathias Hasselmann
+ *
+ * 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):
+ *	Carl D. Worth <cworth@cworth.org>
+ *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
+ *	Behdad Esfahbod <behdad@behdad.org>
+ */
+
+#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
+#define CAIRO_MUTEX_IMPL_PRIVATE_H
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cairo-features.h"
+
+CAIRO_BEGIN_DECLS
+
+
+/* A fully qualified no-operation statement */
+#define CAIRO_MUTEX_IMPL_NOOP	do {/*no-op*/} while (0)
+/* And one that evaluates it's argument once */
+#define CAIRO_MUTEX_IMPL_NOOP1(expr)        do { if (expr) ; } while (0)
+
+
+/* Cairo mutex implementation:
+ *
+ * Any new mutex implementation needs to do the following:
+ *
+ * - Condition on the right header or feature.  Headers are
+ *   preferred as eg. you still can use win32 mutex implementation
+ *   on a win32 system even if you do not compile the win32
+ *   surface/backend.
+ *
+ * - typedef #cairo_mutex_impl_t to the proper mutex type on your target
+ *   system.  Note that you may or may not need to use a pointer,
+ *   depending on what kinds of initialization your mutex
+ *   implementation supports.  No trailing semicolon needed.
+ *   You should be able to compile the following snippet (don't try
+ *   running it):
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex;
+ *   </programlisting>
+ *
+ * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
+ *   proper statement to lock/unlock the mutex object passed in.
+ *   You can (and should) assume that the mutex is already
+ *   initialized, and is-not-already-locked/is-locked,
+ *   respectively.  Use the "do { ... } while (0)" idiom if necessary.
+ *   No trailing semicolons are needed (in any macro you define here).
+ *   You should be able to compile the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex;
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - #define %CAIRO_MUTEX_IMPL_NIL_INITIALIZER to something that can
+ *   initialize the #cairo_mutex_impl_t type you defined.  Most of the
+ *   time one of 0, %NULL, or {} works.  At this point
+ *   you should be able to compile the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - If the above code is not enough to initialize a mutex on
+ *   your platform, #define CAIRO_MUTEX_IMPL_INIT(mutex) to statement
+ *   to initialize the mutex (allocate resources, etc).  Such that
+ *   you should be able to compile AND RUN the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
+ *
+ *      CAIRO_MUTEX_IMPL_INIT (_cairo_some_mutex);
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - If you define CAIRO_MUTEX_IMPL_INIT(mutex), cairo will use it to
+ *   initialize all static mutex'es.  If for any reason that should
+ *   not happen (eg. %CAIRO_MUTEX_IMPL_INIT is just a faster way than
+ *   what cairo does using %CAIRO_MUTEX_IMPL_NIL_INITIALIZER), then
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+ *   </programlisting>
+ *
+ * - If your system supports freeing a mutex object (deallocating
+ *   resources, etc), then #define CAIRO_MUTEX_IMPL_FINI(mutex) to do
+ *   that.
+ *
+ * - If you define CAIRO_MUTEX_IMPL_FINI(mutex), cairo will use it to
+ *   define a finalizer function to finalize all static mutex'es.
+ *   However, it's up to you to call CAIRO_MUTEX_IMPL_FINALIZE() at
+ *   proper places, eg. when the system is unloading the cairo library.
+ *   So, if for any reason finalizing static mutex'es is not needed
+ *   (eg. you never call CAIRO_MUTEX_IMPL_FINALIZE()), then
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+ *   </programlisting>
+ *
+ * - That is all.  If for any reason you think the above API is
+ *   not enough to implement #cairo_mutex_impl_t on your system, please
+ *   stop and write to the cairo mailing list about it.  DO NOT
+ *   poke around cairo-mutex-private.h for possible solutions.
+ */
+
+#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
+#error "Do not include cairo-mutex-impl-private.h directly.  Include cairo-mutex-type-private.h instead."
+#endif
+
+#if CAIRO_NO_MUTEX
+
+/* No mutexes */
+
+  typedef int cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
+
+#elif HAVE_PTHREAD_H /*******************************************************/
+
+# include <pthread.h>
+
+  typedef pthread_mutex_t cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#elif HAVE_WINDOWS_H /*******************************************************/
+
+# include <windows.h>
+
+  typedef CRITICAL_SECTION cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
+
+#elif defined __OS2__ /******************************************************/
+
+# define INCL_BASE
+# define INCL_PM
+# include <os2.h>
+
+  typedef HMTX cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
+# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
+# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
+
+#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
+
+  typedef BLocker* cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
+# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
+# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL
+
+#else /**********************************************************************/
+
+# error "XXX: No mutex implementation found.  Cairo will not work with multiple threads.  Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
+
+
+#endif
+
+CAIRO_END_DECLS
+
+#endif
--- a/gfx/cairo/cairo/src/cairo-mutex-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-private.h
@@ -36,141 +36,32 @@
  *	Carl D. Worth <cworth@cworth.org>
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  *	Behdad Esfahbod <behdad@behdad.org>
  */
 
 #ifndef CAIRO_MUTEX_PRIVATE_H
 #define CAIRO_MUTEX_PRIVATE_H
 
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <cairo-features.h>
-
-#include "cairo-compiler-private.h"
 #include "cairo-mutex-type-private.h"
 
-/* Only the following three are mandatory at this point */
-#ifndef CAIRO_MUTEX_LOCK
-# error "CAIRO_MUTEX_LOCK not defined.  Check cairo-mutex-type-private.h."
-#endif
-#ifndef CAIRO_MUTEX_UNLOCK
-# error "CAIRO_MUTEX_UNLOCK not defined.  Check cairo-mutex-type-private.h."
-#endif
-#ifndef CAIRO_MUTEX_NIL_INITIALIZER
-# error "CAIRO_MUTEX_NIL_INITIALIZER not defined.  Check cairo-mutex-type-private.h."
-#endif
-
 CAIRO_BEGIN_DECLS
 
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+cairo_private void _cairo_mutex_initialize (void);
+#endif
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
+cairo_private void _cairo_mutex_finalize (void);
+#endif
+/* only if using static initializer and/or finalizer define the boolean */
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
+  cairo_private extern cairo_bool_t _cairo_mutex_initialized;
+#endif
 
-#define CAIRO_MUTEX_DECLARE(mutex) extern cairo_mutex_t mutex
+/* Finally, extern the static mutexes and undef */
+
+#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
 #include "cairo-mutex-list-private.h"
 #undef CAIRO_MUTEX_DECLARE
 
-
-/* make sure implementations don't fool us: we decide these ourself */
-#undef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#undef _CAIRO_MUTEX_USE_STATIC_FINALIZER
-
-
-#ifdef CAIRO_MUTEX_INIT
-
-/* If %CAIRO_MUTEX_INIT is defined, we may need to initialize all
- * static mutex'es. */
-# ifndef CAIRO_MUTEX_INITIALIZE
-#  define CAIRO_MUTEX_INITIALIZE() do {	\
-       if (!_cairo_mutex_initialized)	\
-           _cairo_mutex_initialize ();	\
-   } while(0)
-
-   cairo_private void _cairo_mutex_initialize (void);
-
-   /* and make sure we implement the above */
-#  define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 1
-# endif /* CAIRO_MUTEX_INITIALIZE */
-
-#else /* no CAIRO_MUTEX_INIT */
-
-/* Otherwise we probably don't need to initialize static mutex'es, */
-# ifndef CAIRO_MUTEX_INITIALIZE
-#  define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# endif /* CAIRO_MUTEX_INITIALIZE */
-
-/* and dynamic ones can be initialized using the static initializer. */
-# define CAIRO_MUTEX_INIT(mutex) do {				\
-      cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_NIL_INITIALIZER;	\
-      memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex));	\
-  } while (0)
-
-#endif /* CAIRO_MUTEX_INIT */
-
-
-#ifdef CAIRO_MUTEX_FINI
-
-/* If %CAIRO_MUTEX_FINI is defined, we may need to finalize all
- * static mutex'es. */
-# ifndef CAIRO_MUTEX_FINALIZE
-#  define CAIRO_MUTEX_FINALIZE() do {	\
-       if (_cairo_mutex_initialized)	\
-           _cairo_mutex_finalize ();	\
-   } while(0)
-
-   cairo_private void _cairo_mutex_finalize (void);
-
-   /* and make sure we implement the above */
-#  define _CAIRO_MUTEX_USE_STATIC_FINALIZER 1
-# endif /* CAIRO_MUTEX_FINALIZE */
-
-#else /* no CAIRO_MUTEX_FINI */
-
-/* Otherwise we probably don't need to finalize static mutex'es, */
-# ifndef CAIRO_MUTEX_FINALIZE
-#  define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
-# endif /* CAIRO_MUTEX_FINALIZE */
-
-/* neither do the dynamic ones. */
-# define CAIRO_MUTEX_FINI(mutex)	CAIRO_MUTEX_NOOP1(mutex)
-
-#endif /* CAIRO_MUTEX_FINI */
-
-
-#ifndef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 0
-#endif
-#ifndef _CAIRO_MUTEX_USE_STATIC_FINALIZER
-#define _CAIRO_MUTEX_USE_STATIC_FINALIZER 0
-#endif
-
-/* only if using static initializer and/or finalizer define the boolean */
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
-  cairo_private extern cairo_bool_t _cairo_mutex_initialized;
-#endif
-
-
 CAIRO_END_DECLS
 
-/* Make sure everything we want is defined */
-#ifndef CAIRO_MUTEX_INITIALIZE
-# error "CAIRO_MUTEX_INITIALIZE not defined"
 #endif
-#ifndef CAIRO_MUTEX_FINALIZE
-# error "CAIRO_MUTEX_FINALIZE not defined"
-#endif
-#ifndef CAIRO_MUTEX_LOCK
-# error "CAIRO_MUTEX_LOCK not defined"
-#endif
-#ifndef CAIRO_MUTEX_UNLOCK
-# error "CAIRO_MUTEX_UNLOCK not defined"
-#endif
-#ifndef CAIRO_MUTEX_INIT
-# error "CAIRO_MUTEX_INIT not defined"
-#endif
-#ifndef CAIRO_MUTEX_FINI
-# error "CAIRO_MUTEX_FINI not defined"
-#endif
-#ifndef CAIRO_MUTEX_NIL_INITIALIZER
-# error "CAIRO_MUTEX_NIL_INITIALIZER not defined"
-#endif
-
-#endif
--- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h
@@ -40,171 +40,149 @@
 
 #ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
 #define CAIRO_MUTEX_TYPE_PRIVATE_H
 
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <cairo-features.h>
+#include "cairo-features.h"
+
+#include "cairo-compiler-private.h"
+#include "cairo-mutex-impl-private.h"
 
-CAIRO_BEGIN_DECLS
+/* Only the following three are mandatory at this point */
+#ifndef CAIRO_MUTEX_IMPL_LOCK
+# error "CAIRO_MUTEX_IMPL_LOCK not defined.  Check cairo-mutex-impl-private.h."
+#endif
+#ifndef CAIRO_MUTEX_IMPL_UNLOCK
+# error "CAIRO_MUTEX_IMPL_UNLOCK not defined.  Check cairo-mutex-impl-private.h."
+#endif
+#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined.  Check cairo-mutex-impl-private.h."
+#endif
+
+
+/* make sure implementations don't fool us: we decide these ourself */
+#undef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#undef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 
 
-/* A fully qualified no-operation statement */
-#define CAIRO_MUTEX_NOOP	do {/*no-op*/} while (0)
-/* And one that evaluates it's argument once */
-#define CAIRO_MUTEX_NOOP1(expr)        do { if (expr) ; } while (0)
+#ifdef CAIRO_MUTEX_IMPL_INIT
+
+/* If %CAIRO_MUTEX_IMPL_INIT is defined, we may need to initialize all
+ * static mutex'es. */
+# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+#  define CAIRO_MUTEX_IMPL_INITIALIZE() do {	\
+       if (!_cairo_mutex_initialized)	\
+           _cairo_mutex_initialize ();	\
+    } while(0)
+
+/* and make sure we implement the above */
+#  define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
+
+#else /* no CAIRO_MUTEX_IMPL_INIT */
+
+/* Otherwise we probably don't need to initialize static mutex'es, */
+# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+#  define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
+
+/* and dynamic ones can be initialized using the static initializer. */
+# define CAIRO_MUTEX_IMPL_INIT(mutex) do {				\
+      cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;	\
+      memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex));	\
+  } while (0)
+
+#endif /* CAIRO_MUTEX_IMPL_INIT */
 
 
-/* Cairo mutex implementation:
- *
- * Any new mutex implementation needs to do the following:
- *
- * - Condition on the right header or feature.  Headers are
- *   preferred as eg. you still can use win32 mutex implementation
- *   on a win32 system even if you do not compile the win32
- *   surface/backend.
- *
- * - typedef #cairo_mutex_t to the proper mutex type on your target
- *   system.  Note that you may or may not need to use a pointer,
- *   depending on what kinds of initialization your mutex
- *   implementation supports.  No trailing semicolon needed.
- *   You should be able to compile the following snippet (don't try
- *   running it):
- *
- *	cairo_mutex_t _cairo_some_mutex;
- *
- * - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to
- *   proper statement to lock/unlock the mutex object passed in.
- *   You can (and should) assume that the mutex is already
- *   initialized, and is-not-already-locked/is-locked,
- *   respectively.  Use the "do { ... } while (0)" idiom if necessary.
- *   No trailing semicolons are needed (in any macro you define here).
- *   You should be able to compile the following snippet:
- *
- *	cairo_mutex_t _cairo_some_mutex;
- *
- *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *
- * - #define %CAIRO_MUTEX_NIL_INITIALIZER to something that can
- *   initialize the #cairo_mutex_t type you defined.  Most of the
- *   time one of 0, %NULL, or {} works.  At this point
- *   you should be able to compile the following snippet:
- *
- *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
- *
- *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *
- * - If the above code is not enough to initialize a mutex on
- *   your platform, #define CAIRO_MUTEX_INIT(mutex) to statement
- *   to initialize the mutex (allocate resources, etc).  Such that
- *   you should be able to compile AND RUN the following snippet:
- *
- *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
- *
- *      %CAIRO_MUTEX_INIT (_cairo_some_mutex);
- *
- *      if (1)
- *          %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *
- * - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to
- *   initialize all static mutex'es.  If for any reason that should
- *   not happen (eg. %CAIRO_MUTEX_INIT is just a faster way than
- *   what cairo does using %CAIRO_MUTEX_NIL_INITIALIZER), then
- *   #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
- *
- * - If your system supports freeing a mutex object (deallocating
- *   resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do
- *   that.
- *
- * - If you define CAIRO_MUTEX_FINI(mutex), cairo will use it to
- *   define a finalizer function to finalize all static mutex'es.
- *   However, it's up to you to call CAIRO_MUTEX_FINALIZE() at
- *   proper places, eg. when the system is unloading the cairo library.
- *   So, if for any reason finalizing static mutex'es is not needed
- *   (eg. you never call %CAIRO_MUTEX_FINALIZE), then
- *   #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
- *
- * - That is all.  If for any reason you think the above API is
- *   not enough to implement #cairo_mutex_t on your system, please
- *   stop and write to the cairo mailing list about it.  DO NOT
- *   poke around cairo-mutex-private.h for possible solutions.
- */
+#ifdef CAIRO_MUTEX_IMPL_FINI
+
+/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
+ * static mutex'es. */
+# ifndef CAIRO_MUTEX_IMPL_FINALIZE
+#  define CAIRO_MUTEX_IMPL_FINALIZE() do {	\
+       if (_cairo_mutex_initialized)	\
+           _cairo_mutex_finalize ();	\
+    } while(0)
+
+/* and make sure we implement the above */
+#  define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
+
+#else /* no CAIRO_MUTEX_IMPL_FINI */
 
-#if CAIRO_NO_MUTEX
-
-/* No mutexes */
-
-  typedef int cairo_mutex_t;
-
-# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
-# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER 0
-
-#elif HAVE_PTHREAD_H /*******************************************************/
+/* Otherwise we probably don't need to finalize static mutex'es, */
+# ifndef CAIRO_MUTEX_IMPL_FINALIZE
+#  define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
 
-# include <pthread.h>
-
-  typedef pthread_mutex_t cairo_mutex_t;
-
-# define CAIRO_MUTEX_LOCK(mutex) pthread_mutex_lock (&(mutex))
-# define CAIRO_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
-# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (&(mutex))
-# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-
-#elif HAVE_WINDOWS_H /*******************************************************/
-
-# include <windows.h>
-
-  typedef CRITICAL_SECTION cairo_mutex_t;
+/* neither do the dynamic ones. */
+# define CAIRO_MUTEX_IMPL_FINI(mutex)	CAIRO_MUTEX_IMPL_NOOP1(mutex)
 
-# define CAIRO_MUTEX_LOCK(mutex) EnterCriticalSection (&(mutex))
-# define CAIRO_MUTEX_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
-# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (&(mutex))
-# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (&(mutex))
-# define CAIRO_MUTEX_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
+#endif /* CAIRO_MUTEX_IMPL_FINI */
 
-#elif defined __OS2__ /******************************************************/
-
-# define INCL_BASE
-# define INCL_PM
-# include <os2.h>
-
-  typedef HMTX cairo_mutex_t;
 
-# define CAIRO_MUTEX_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
-# define CAIRO_MUTEX_UNLOCK(mutex) DosReleaseMutexSem(mutex)
-# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
-# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER 0
-
-#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
-
-  typedef BLocker* cairo_mutex_t;
-
-# define CAIRO_MUTEX_LOCK(mutex) (mutex)->Lock()
-# define CAIRO_MUTEX_UNLOCK(mutex) (mutex)->Unlock()
-# define CAIRO_MUTEX_INIT(mutex) (mutex) = new BLocker()
-# define CAIRO_MUTEX_FINI(mutex) delete (mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER NULL
-
-#else /**********************************************************************/
-
-# error "XXX: No mutex implementation found.  Cairo will not work with multiple threads.  Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
+#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 0
+#endif
+#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
+#define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 0
+#endif
 
 
+/* Make sure everything we want is defined */
+#ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+# error "CAIRO_MUTEX_IMPL_INITIALIZE not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_FINALIZE
+# error "CAIRO_MUTEX_IMPL_FINALIZE not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_LOCK
+# error "CAIRO_MUTEX_IMPL_LOCK not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_UNLOCK
+# error "CAIRO_MUTEX_IMPL_UNLOCK not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_INIT
+# error "CAIRO_MUTEX_IMPL_INIT not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_FINI
+# error "CAIRO_MUTEX_IMPL_FINI not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined"
 #endif
 
-CAIRO_END_DECLS
+
+/* Public interface. */
+
+/* By default it simply uses the implementation provided.
+ * But we can provide for debugging features by overriding them */
+
+#ifndef CAIRO_MUTEX_DEBUG
+typedef cairo_mutex_impl_t cairo_mutex_t;
+#else
+# define cairo_mutex_t			cairo_mutex_impl_t
+#endif
+
+#define CAIRO_MUTEX_INITIALIZE		CAIRO_MUTEX_IMPL_INITIALIZE
+#define CAIRO_MUTEX_FINALIZE		CAIRO_MUTEX_IMPL_FINALIZE
+#define CAIRO_MUTEX_LOCK		CAIRO_MUTEX_IMPL_LOCK
+#define CAIRO_MUTEX_UNLOCK		CAIRO_MUTEX_IMPL_UNLOCK
+#define CAIRO_MUTEX_INIT		CAIRO_MUTEX_IMPL_INIT
+#define CAIRO_MUTEX_FINI		CAIRO_MUTEX_IMPL_FINI
+#define CAIRO_MUTEX_NIL_INITIALIZER	CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+
+
+
+/* Debugging support */
+
+#ifdef CAIRO_MUTEX_DEBUG
+
+/* TODO add mutex debugging facilities here (eg deadlock detection) */
+
+#endif /* CAIRO_MUTEX_DEBUG */
 
 #endif
--- a/gfx/cairo/cairo/src/cairo-mutex.c
+++ b/gfx/cairo/cairo/src/cairo-mutex.c
@@ -28,49 +28,51 @@
  * The Original Code is the cairo graphics library.
  *
  * Contributor(s):
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  */
 
 #include "cairoint.h"
 
+#include "cairo-mutex-private.h"
+
 #define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 
-# if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#  define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE FALSE
+# if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#  define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE
 # else
-#  define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE TRUE
+#  define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE
 # endif
 
-cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE;
+cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE;
 
-# undef _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE
+# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE
 
 #endif
 
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
 void _cairo_mutex_initialize (void)
 {
     if (_cairo_mutex_initialized)
         return;
 
     _cairo_mutex_initialized = TRUE;
 
 #define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex)
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 }
 #endif
 
-#if _CAIRO_MUTEX_USE_STATIC_FINALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 void _cairo_mutex_finalize (void)
 {
     if (!_cairo_mutex_initialized)
         return;
 
     _cairo_mutex_initialized = FALSE;
 
 #define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex)
--- a/gfx/cairo/cairo/src/cairo-os2-private.h
+++ b/gfx/cairo/cairo/src/cairo-os2-private.h
@@ -44,17 +44,17 @@
 #define INCL_WIN
 #define INCL_GPI
 #ifdef __WATCOMC__
 # include <os2.h>
 #else
 # include <os2emx.h>
 #endif
 
-#include <cairo-os2.h>
+#include "cairo-os2.h"
 #include "cairoint.h"
 
 typedef struct _cairo_os2_surface
 {
     cairo_surface_t        base;
 
     /* Mutex semaphore to protect private fields from concurrent access */
     HMTX                   hmtx_use_private_fields;
--- a/gfx/cairo/cairo/src/cairo-os2-surface.c
+++ b/gfx/cairo/cairo/src/cairo-os2-surface.c
@@ -51,18 +51,18 @@
 # include "cairo-os2.h"
 # ifndef __WATCOMC__
 #  include <emx/startup.h>
 # endif
 #endif
 
 /*
  * Here comes the extra API for the OS/2 platform. Currently it consists
- * of two extra functions, the cairo_os2_init () and the
- * cairo_os2_fini (). Both of them are called automatically if
+ * of two extra functions, the cairo_os2_init() and the
+ * cairo_os2_fini(). Both of them are called automatically if
  * Cairo is compiled to be a DLL file, but you have to call them before
  * using the Cairo API if you link to Cairo statically!
  *
  * You'll also find the code in here which deals with DLL initialization
  * and termination, if the code is built to be a DLL.
  * (if BUILD_CAIRO_DLL is defined)
  */
 
@@ -140,18 +140,20 @@ cairo_os2_fini (void)
     _cairo_font_reset_static_data ();
 #if CAIRO_HAS_FT_FONT
     _cairo_ft_font_reset_static_data ();
 #endif
 
     CAIRO_MUTEX_FINALIZE ();
 
 #if CAIRO_HAS_FT_FONT
+# if HAVE_FCFINI
     /* Uninitialize FontConfig */
     FcFini ();
+# endif
 #endif
 
 #ifdef __WATCOMC__
     /* It can happen that the libraries we use have memory leaks,
      * 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
--- a/gfx/cairo/cairo/src/cairo-os2.h
+++ b/gfx/cairo/cairo/src/cairo-os2.h
@@ -33,17 +33,17 @@
  *
  * Contributor(s):
  *     Peter Weilbacher <mozilla@Weilbacher.org>
  */
 
 #ifndef _CAIRO_OS2_H_
 #define _CAIRO_OS2_H_
 
-#include <cairo.h>
+#include "cairo.h"
 
 CAIRO_BEGIN_DECLS
 
 /* The OS/2 Specific Cairo API */
 
 cairo_public void
 cairo_os2_init (void);
 
--- a/gfx/cairo/cairo/src/cairo-output-stream-private.h
+++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h
@@ -152,17 +152,17 @@ cairo_private cairo_output_stream_t *
 
 cairo_private void
 _cairo_memory_stream_copy (cairo_output_stream_t *base,
 			   cairo_output_stream_t *dest);
 
 cairo_private int
 _cairo_memory_stream_length (cairo_output_stream_t *stream);
 
-/* cairo_base85_stream.c */
+/* cairo-base85-stream.c */
 cairo_private cairo_output_stream_t *
 _cairo_base85_stream_create (cairo_output_stream_t *output);
 
-/* cairo_deflate_stream.c */
+/* cairo-deflate-stream.c */
 cairo_private cairo_output_stream_t *
 _cairo_deflate_stream_create (cairo_output_stream_t *output);
 
 #endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-output-stream.c
+++ b/gfx/cairo/cairo/src/cairo-output-stream.c
@@ -44,29 +44,31 @@
 #include <ctype.h>
 #include <errno.h>
 
 /* Numbers printed with %f are printed with this number of significant
  * digits after the decimal.
  */
 #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
 
-/* Numbers printed with %g are assumed to only have CAIRO_FIXED_FRAC_BITS
+/* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
  * bits of precision available after the decimal point.
  *
  * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
  * digits after the decimal point required to preserve the available
  * precision.
  *
  * The conversion is:
  *
+ * <programlisting>
  * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
+ * </programlisting>
  *
  * We can replace ceil(x) with (int)(x+1) since x will never be an
- * integer for any likely value of CAIRO_FIXED_FRAC_BITS.
+ * integer for any likely value of %CAIRO_FIXED_FRAC_BITS.
  */
 #define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
 
 void
 _cairo_output_stream_init (cairo_output_stream_t            *stream,
 			   cairo_output_stream_write_func_t  write_func,
 			   cairo_output_stream_close_func_t  close_func)
 {
--- a/gfx/cairo/cairo/src/cairo-paginated-private.h
+++ b/gfx/cairo/cairo/src/cairo-paginated-private.h
@@ -62,60 +62,68 @@ struct _cairo_paginated_surface_backend 
 
     /* Optional. Specifies the smallest box that encloses all objects
      * on the page. Will be called at the end of the ANALYZE phase but
      * before the mode is changed to RENDER.
      */
     cairo_warn cairo_int_status_t
     (*set_bounding_box)	(void	   	*surface,
 			 cairo_box_t	*bbox);
+
+    /* Optional. Indicates whether the page requires fallback images.
+     * Will be called at the end of the ANALYZE phase but before the
+     * mode is changed to RENDER.
+     */
+    cairo_warn cairo_int_status_t
+    (*set_fallback_images_required)(void   	  *surface,
+				    cairo_bool_t   fallbacks_required);
 };
 
 /* A #cairo_paginated_surface_t provides a very convenient wrapper that
  * is well-suited for doing the analysis common to most surfaces that
  * have paginated output, (that is, things directed at printers, or
  * for saving content in files such as PostScript or PDF files).
  *
  * To use the paginated surface, you'll first need to create your
  * 'real' surface using _cairo_surface_init() and the standard
  * #cairo_surface_backend_t. Then you also call
  * _cairo_paginated_surface_create which takes its own, much simpler,
  * #cairo_paginated_surface_backend_t. You are free to return the result
  * of _cairo_paginated_surface_create() from your public
- * cairo_<foo>_surface_create. The paginated backend will be careful
+ * cairo_<foo>_surface_create(). The paginated backend will be careful
  * to not let the user see that they really got a "wrapped"
  * surface. See test-paginated-surface.c for a fairly minimal example
  * of a paginated-using surface. That should be a reasonable example
  * to follow.
  *
  * What the paginated surface does is first save all drawing
  * operations for a page into a meta-surface. Then when the user calls
- * cairo_show_page, the paginated surface performs the following
+ * cairo_show_page(), the paginated surface performs the following
  * sequence of operations (using the backend functions passed to
- * cairo_paginated_surface_create):
+ * cairo_paginated_surface_create()):
  *
- * 1. Calls start_page (if non %NULL). At this point, it is appropriate
+ * 1. Calls start_page() (if not %NULL). At this point, it is appropriate
  *    for the target to emit any page-specific header information into
  *    its output.
  *
- * 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
+ * 2. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_ANALYZE
  *
  * 3. Replays the meta-surface to the target surface, (with an
  *    analysis surface inserted between which watches the return value
  *    from each operation). This analysis stage is used to decide which
  *    operations will require fallbacks.
  *
- * 4. Calls set_bounding_box to provide the target surface with the
+ * 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
+ * 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. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
+ * 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 three separate
  * stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase
  * the target should not actually perform any rendering, (for example,
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -84,17 +84,17 @@ cairo_surface_t *
 
     _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend,
 			 content);
 
     /* Override surface->base.type with target's type so we don't leak
      * evidence of the paginated wrapper out to the user. */
     surface->base.type = cairo_surface_get_type (target);
 
-    surface->target = target;
+    surface->target = cairo_surface_reference (target);
 
     surface->content = content;
     surface->width = width;
     surface->height = height;
 
     surface->backend = backend;
 
     surface->meta = _cairo_meta_surface_create (content, width, height);
@@ -311,16 +311,25 @@ static cairo_int_status_t
 	 cairo_box_t bbox;
 
 	 _cairo_analysis_surface_get_bounding_box (analysis, &bbox);
 	 status = surface->backend->set_bounding_box (surface->target, &bbox);
 	 if (status)
 	     goto FAIL;
      }
 
+    if (surface->backend->set_fallback_images_required) {
+	cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis);
+
+	status = surface->backend->set_fallback_images_required (surface->target,
+								 has_fallbacks);
+	if (status)
+	    goto FAIL;
+    }
+
     surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
 
     /* Finer grained fallbacks are currently only supported for some
      * surface types */
     switch (surface->target->type) {
         case CAIRO_SURFACE_TYPE_PDF:
         case CAIRO_SURFACE_TYPE_PS:
         case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
@@ -590,47 +599,63 @@ static cairo_int_status_t
 
     surface->page_is_blank = FALSE;
 
     return _cairo_surface_fill (surface->meta, op, source,
 				path, fill_rule,
 				tolerance, antialias);
 }
 
+static cairo_bool_t
+_cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
+{
+    cairo_paginated_surface_t *surface = abstract_surface;
+
+    return _cairo_surface_has_show_text_glyphs (surface->target);
+}
+
 static cairo_int_status_t
-_cairo_paginated_surface_show_glyphs (void			*abstract_surface,
-				      cairo_operator_t		 op,
-				      cairo_pattern_t		*source,
-				      cairo_glyph_t		*glyphs,
-				      int			 num_glyphs,
-				      cairo_scaled_font_t	*scaled_font)
+_cairo_paginated_surface_show_text_glyphs (void			    *abstract_surface,
+					  cairo_operator_t	     op,
+					  cairo_pattern_t	    *source,
+					  const char		    *utf8,
+					  int			     utf8_len,
+					  cairo_glyph_t		    *glyphs,
+					  int			     num_glyphs,
+					  const cairo_text_cluster_t *clusters,
+					  int			     num_clusters,
+					  cairo_bool_t		     backward,
+					  cairo_scaled_font_t	    *scaled_font)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
 
     /* Optimize away erasing of nothing. */
     if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
 	return CAIRO_STATUS_SUCCESS;
 
     surface->page_is_blank = FALSE;
 
     /* Since this is a "wrapping" surface, we're calling back into
-     * _cairo_surface_show_glyphs from within a call to the same.
-     * Since _cairo_surface_show_glyphs acquires a mutex, we release
+     * _cairo_surface_show_text_glyphs from within a call to the same.
+     * Since _cairo_surface_show_text_glyphs acquires a mutex, we release
      * and re-acquire the mutex around this nested call.
      *
      * Yes, this is ugly, but we consider it pragmatic as compared to
      * adding locking code to all 18 surface-backend-specific
      * show_glyphs functions, (which would get less testing and likely
      * lead to bugs).
      */
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
-    status = _cairo_surface_show_glyphs (surface->meta, op, source,
-					 glyphs, num_glyphs,
-					 scaled_font);
+    status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
+					      utf8, utf8_len,
+					      glyphs, num_glyphs,
+					      clusters, num_clusters,
+					      backward,
+					      scaled_font);
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
 
     return status;
 }
 
 static cairo_surface_t *
 _cairo_paginated_surface_snapshot (void *abstract_other)
 {
@@ -661,11 +686,17 @@ static const cairo_surface_backend_t cai
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
     _cairo_paginated_surface_paint,
     _cairo_paginated_surface_mask,
     _cairo_paginated_surface_stroke,
     _cairo_paginated_surface_fill,
-    _cairo_paginated_surface_show_glyphs,
-    _cairo_paginated_surface_snapshot
+    NULL, /* show_glyphs */
+    _cairo_paginated_surface_snapshot,
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL, /* fill_stroke */
+    NULL, /* create_solid_pattern_surface */
+    _cairo_paginated_surface_has_show_text_glyphs,
+    _cairo_paginated_surface_show_text_glyphs
 };
--- a/gfx/cairo/cairo/src/cairo-path-fixed.c
+++ b/gfx/cairo/cairo/src/cairo-path-fixed.c
@@ -471,26 +471,26 @@ static int const num_args[] =
 {
     1, /* cairo_path_move_to */
     1, /* cairo_path_op_line_to */
     3, /* cairo_path_op_curve_to */
     0, /* cairo_path_op_close_path */
 };
 
 cairo_status_t
-_cairo_path_fixed_interpret (cairo_path_fixed_t			*path,
+_cairo_path_fixed_interpret (const cairo_path_fixed_t		*path,
 			     cairo_direction_t			 dir,
 			     cairo_path_fixed_move_to_func_t	*move_to,
 			     cairo_path_fixed_line_to_func_t	*line_to,
 			     cairo_path_fixed_curve_to_func_t	*curve_to,
 			     cairo_path_fixed_close_path_func_t	*close_path,
 			     void				*closure)
 {
     cairo_status_t status;
-    cairo_path_buf_t *buf;
+    const cairo_path_buf_t *buf;
     cairo_path_op_t op;
     cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
     int step = forward ? 1 : -1;
 
     for (buf = forward ? &path->buf_head.base : path->buf_tail;
 	 buf;
 	 buf = forward ? buf->next : buf->prev)
     {
@@ -536,16 +536,62 @@ cairo_status_t
 	    }
 
 	}
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_append_move_to (void		 *closure,
+	  cairo_point_t  *point)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_move_to (path, point->x, point->y);
+}
+
+static cairo_status_t
+_append_line_to (void		 *closure,
+	  cairo_point_t *point)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_line_to (path, point->x, point->y);
+}
+
+static cairo_status_t
+_append_curve_to (void	  *closure,
+	   cairo_point_t *p0,
+	   cairo_point_t *p1,
+	   cairo_point_t *p2)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y);
+}
+
+static cairo_status_t
+_append_close_path (void *closure)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
+    return _cairo_path_fixed_close_path (path);
+}
+
+cairo_private cairo_status_t
+_cairo_path_fixed_append (cairo_path_fixed_t		  *path,
+			  const cairo_path_fixed_t	  *other,
+			  cairo_direction_t		   dir)
+{
+    return _cairo_path_fixed_interpret (other, dir,
+					_append_move_to,
+					_append_line_to,
+					_append_curve_to,
+					_append_close_path,
+					path);
+}
+
 static void
 _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
 				    cairo_fixed_t offx,
 				    cairo_fixed_t offy,
 				    cairo_fixed_t scalex,
 				    cairo_fixed_t scaley)
 {
     cairo_path_buf_t *buf = &path->buf_head.base;
@@ -561,39 +607,57 @@ static void
 		 buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley);
 	     buf->points[i].y += offy;
 	 }
 
 	 buf = buf->next;
     }
 }
 
-
 /**
- * _cairo_path_fixed_device_transform:
+ * _cairo_path_fixed_transform:
  * @path: a #cairo_path_fixed_t to be transformed
- * @device_transform: a matrix with only scaling/translation (no rotation or shear)
+ * @matrix: a #cairo_matrix_t
  *
- * Transform the fixed-point path according to the scaling and
- * translation of the given matrix. This function assert()s that the
- * given matrix has no rotation or shear elements, (that is, xy and yx
- * are 0.0).
+ * Transform the fixed-point path according to the given matrix.
+ * There is a fast path for the case where @matrix has no rotation
+ * or shear.
  **/
 void
-_cairo_path_fixed_device_transform (cairo_path_fixed_t	*path,
-				    cairo_matrix_t	*device_transform)
+_cairo_path_fixed_transform (cairo_path_fixed_t	*path,
+			     cairo_matrix_t     *matrix)
 {
-    assert (device_transform->yx == 0.0 && device_transform->xy == 0.0);
-    /* XXX: Support freeform matrices someday (right now, only translation and scale
-     * work. */
-    _cairo_path_fixed_offset_and_scale (path,
-					_cairo_fixed_from_double (device_transform->x0),
-					_cairo_fixed_from_double (device_transform->y0),
-					_cairo_fixed_from_double (device_transform->xx),
-					_cairo_fixed_from_double (device_transform->yy));
+    cairo_path_buf_t *buf;
+    int i;
+    double dx, dy;
+
+    if (matrix->yx == 0.0 && matrix->xy == 0.0) {
+	/* Fast path for the common case of scale+transform */
+	_cairo_path_fixed_offset_and_scale (path,
+					    _cairo_fixed_from_double (matrix->x0),
+					    _cairo_fixed_from_double (matrix->y0),
+					    _cairo_fixed_from_double (matrix->xx),
+					    _cairo_fixed_from_double (matrix->yy));
+	return;
+    }
+
+    buf = &path->buf_head.base;
+    while (buf) {
+	 for (i = 0; i < buf->num_points; i++) {
+	    dx = _cairo_fixed_to_double (buf->points[i].x);
+	    dy = _cairo_fixed_to_double (buf->points[i].y);
+
+	    cairo_matrix_transform_point (matrix, &dx, &dy);
+
+	    buf->points[i].x = _cairo_fixed_from_double (dx);
+	    buf->points[i].y = _cairo_fixed_from_double (dy);
+	 }
+
+	 buf = buf->next;
+    }
 }
 
 cairo_bool_t
 _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
 			    cairo_path_fixed_t *other)
 {
     cairo_path_buf_t *path_buf, *other_buf;
 
@@ -696,17 +760,17 @@ static cairo_status_t
 {
     cpf_t *cpf = closure;
 
     return cpf->close_path (cpf->closure);
 }
 
 
 cairo_status_t
-_cairo_path_fixed_interpret_flat (cairo_path_fixed_t			*path,
+_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t		*path,
 				  cairo_direction_t			dir,
 				  cairo_path_fixed_move_to_func_t	*move_to,
 				  cairo_path_fixed_line_to_func_t	*line_to,
 				  cairo_path_fixed_close_path_func_t	*close_path,
 				  void					*closure,
 				  double				tolerance)
 {
     cpf_t flattener;
@@ -800,24 +864,26 @@ cairo_bool_t
 	    box->p2 = buf->points[2];
 	}
 	return TRUE;
     }
 
     return FALSE;
 }
 
-/**
+/*
  * Check whether the given path contains a single rectangle
  * that is logically equivalent to:
+ * <informalexample><programlisting>
  *   cairo_move_to (cr, x, y);
  *   cairo_rel_line_to (cr, width, 0);
  *   cairo_rel_line_to (cr, 0, height);
  *   cairo_rel_line_to (cr, -width, 0);
  *   cairo_close_path (cr);
+ * </programlisting></informalexample>
  */
 cairo_bool_t
 _cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
 				cairo_box_t        *box)
 {
     cairo_path_buf_t *buf = &path->buf_head.base;
 
     if (!_cairo_path_fixed_is_box (path, box))
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -1186,59 +1186,67 @@ BAIL:
 typedef struct _cairo_rectilinear_stroker
 {
     cairo_stroke_style_t *stroke_style;
     cairo_fixed_t half_line_width;
     cairo_traps_t *traps;
     cairo_point_t current_point;
     cairo_point_t first_point;
     cairo_bool_t open_sub_path;
-    cairo_line_t *segments;
+    int num_segments;
     int segments_size;
-    int num_segments;
+    cairo_line_t *segments;
+    cairo_line_t segments_embedded[8]; /* common case is a single rectangle */
 } cairo_rectilinear_stroker_t;
 
 static void
 _cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t	*stroker,
 				 cairo_stroke_style_t		*stroke_style,
 				 cairo_traps_t			*traps)
 {
     stroker->stroke_style = stroke_style;
     stroker->half_line_width =
 	_cairo_fixed_from_double (stroke_style->line_width / 2.0);
     stroker->traps = traps;
     stroker->open_sub_path = FALSE;
-    stroker->segments = NULL;
-    stroker->segments_size = 0;
+    stroker->segments = stroker->segments_embedded;
+    stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded);
     stroker->num_segments = 0;
 }
 
 static void
 _cairo_rectilinear_stroker_fini (cairo_rectilinear_stroker_t	*stroker)
 {
-    free (stroker->segments);
+    if (stroker->segments != stroker->segments_embedded)
+	free (stroker->segments);
 }
 
 static cairo_status_t
 _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t	*stroker,
 					cairo_point_t			*p1,
 					cairo_point_t			*p2)
 {
-    int new_size;
-    cairo_line_t *new_segments;
 
     if (stroker->num_segments == stroker->segments_size) {
-	new_size = stroker->segments_size * 2;
-	/* Common case is one rectangle of exactly 4 segments. */
-	if (new_size == 0)
-	    new_size = 4;
-	new_segments = _cairo_realloc_ab (stroker->segments,
-	       	                          new_size, sizeof (cairo_line_t));
-	if (new_segments == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	int new_size = stroker->segments_size * 2;
+	cairo_line_t *new_segments;
+
+	if (stroker->segments == stroker->segments_embedded) {
+	    new_segments = _cairo_malloc_ab (new_size, sizeof (cairo_line_t));
+	    if (new_segments == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	    memcpy (new_segments, stroker->segments,
+		    stroker->num_segments * sizeof (cairo_line_t));
+	} else {
+	    new_segments = _cairo_realloc_ab (stroker->segments,
+					      new_size, sizeof (cairo_line_t));
+	    if (new_segments == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
 
 	stroker->segments_size = new_size;
 	stroker->segments = new_segments;
     }
 
     stroker->segments[stroker->num_segments].p1 = *p1;
     stroker->segments[stroker->num_segments].p2 = *p2;
     stroker->num_segments++;
@@ -1385,18 +1393,17 @@ static cairo_status_t
     /* We only support horizontal or vertical elements. */
     if (! (a->x == b->x || a->y == b->y))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* We don't draw anything for degenerate paths. */
     if (a->x == b->x && a->y == b->y)
 	return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_rectilinear_stroker_add_segment (stroker,
-						     a, b);
+    status = _cairo_rectilinear_stroker_add_segment (stroker, a, b);
 
     stroker->current_point = *point;
     stroker->open_sub_path = TRUE;
 
     return status;
 }
 
 static cairo_status_t
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -45,47 +45,50 @@ static const cairo_solid_pattern_t _cair
       CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
       CAIRO_STATUS_NULL_POINTER,	/* status */
       { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
-const cairo_solid_pattern_t cairo_pattern_none = {
+const cairo_solid_pattern_t _cairo_pattern_none = {
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
       CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
       CAIRO_STATUS_SUCCESS,		/* status */
       { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
 /**
  * _cairo_pattern_set_error:
  * @pattern: a pattern
- * @status: a status value indicating an error, (eg. not
- * CAIRO_STATUS_SUCCESS)
+ * @status: a status value indicating an error
  *
  * Atomically sets pattern->status to @status and calls _cairo_error;
+ * Does nothing if status is %CAIRO_STATUS_SUCCESS.
  *
  * All assignments of an error status to pattern->status should happen
  * through _cairo_pattern_set_error(). Note that due to the nature of
  * the atomic operation, it is not safe to call this function on the nil
  * objects.
  *
  * The purpose of this function is to allow the user to set a
  * breakpoint in _cairo_error() to generate a stack trace for when the
  * user causes cairo to detect an error.
  **/
 static cairo_status_t
 _cairo_pattern_set_error (cairo_pattern_t *pattern,
 			  cairo_status_t status)
 {
+    if (status == CAIRO_STATUS_SUCCESS)
+	return status;
+
     /* Don't overwrite an existing error. This preserves the first
      * error, which is the most significant. */
     _cairo_status_set_error (&pattern->status, status);
 
     return _cairo_error (status);
 }
 
 static void
@@ -247,16 +250,19 @@ cairo_status_t
 }
 
 
 void
 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
 			   const cairo_color_t	 *color,
 			   cairo_content_t	  content)
 {
+    if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
+	content = CAIRO_CONTENT_COLOR;
+
     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
     pattern->color = *color;
     pattern->content = content;
 }
 
 void
 _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
 				 cairo_surface_t	 *surface)
@@ -353,17 +359,18 @@ cairo_pattern_t *
 static void
 _cairo_pattern_reset_solid_pattern_cache (void)
 {
     int i;
 
     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
 
     for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
-	free (solid_pattern_cache.patterns[i]);
+	if (solid_pattern_cache.patterns[i])
+	    free (solid_pattern_cache.patterns[i]);
 	solid_pattern_cache.patterns[i] = NULL;
     }
     solid_pattern_cache.size = 0;
 
     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
 }
 
 static const cairo_pattern_t *
@@ -371,18 +378,17 @@ static const cairo_pattern_t *
 {
     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);
+    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
     if (pattern->status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_pattern_set_error (pattern, status);
 
     return pattern;
 }
 
 /**
  * cairo_pattern_create_rgb:
@@ -1359,136 +1365,190 @@ static cairo_int_status_t
     return status;
 }
 
 /* We maintain a small cache here, because we don't want to constantly
  * recreate surfaces for simple solid colors. */
 #define MAX_SURFACE_CACHE_SIZE 16
 static struct {
     struct _cairo_pattern_solid_surface_cache{
+	cairo_content_t  content;
 	cairo_color_t    color;
 	cairo_surface_t *surface;
     } cache[MAX_SURFACE_CACHE_SIZE];
     int size;
 } solid_surface_cache;
 
 static cairo_bool_t
 _cairo_pattern_solid_surface_matches (
 	const struct _cairo_pattern_solid_surface_cache	    *cache,
 	const cairo_solid_pattern_t			    *pattern,
 	cairo_surface_t					    *dst)
 {
-    if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
+    if (cache->content != pattern->content)
 	return FALSE;
 
-    if (! _cairo_color_equal (&cache->color, &pattern->color))
+    if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
 	return FALSE;
 
     if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
 	return FALSE;
 
     return TRUE;
 }
 
+static cairo_bool_t
+_cairo_pattern_solid_surface_matches_color (
+	const struct _cairo_pattern_solid_surface_cache	    *cache,
+	const cairo_solid_pattern_t			    *pattern,
+	cairo_surface_t					    *dst)
+{
+    if (! _cairo_color_equal (&cache->color, &pattern->color))
+	return FALSE;
+
+    return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
+}
+
 static cairo_int_status_t
 _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t	     *pattern,
 					  cairo_surface_t	     *dst,
 					  int			     x,
 					  int			     y,
 					  unsigned int		     width,
 					  unsigned int		     height,
 					  cairo_surface_t	     **out,
 					  cairo_surface_attributes_t *attribs)
 {
     static int i;
 
-    cairo_surface_t *surface;
+    cairo_surface_t *surface, *to_destroy = NULL;
     cairo_status_t   status;
 
     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
 
     /* Check cache first */
     if (i < solid_surface_cache.size &&
-	    _cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
-		                                  pattern,
-						  dst))
+	_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
+						    pattern,
+						    dst))
     {
-	if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
-	    goto DONE;
+	status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
+	if (status)
+	    goto UNLOCK;
+
+	goto DONE;
     }
 
     for (i = 0 ; i < solid_surface_cache.size; i++) {
-	if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
-		                                  pattern,
-						  dst))
+	if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
+							pattern,
+							dst))
 	{
-	    if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
-		goto DONE;
+	    status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
+	    if (status)
+		goto UNLOCK;
+
+	    goto DONE;
 	}
     }
 
-    /* Not cached, need to create new */
-    surface = _cairo_surface_create_similar_solid (dst,
-	                                           pattern->content,
-						   1, 1,
-						   &pattern->color,
-						   &pattern->base);
-    if (surface->status) {
-	status = surface->status;
-	goto UNLOCK;
+    /* Choose a surface to repaint/evict */
+    surface = NULL;
+    if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
+	i = rand () % MAX_SURFACE_CACHE_SIZE;
+	surface = solid_surface_cache.cache[i].surface;
+
+	if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
+						  pattern,
+						  dst))
+	{
+	    /* Reuse the surface instead of evicting */
+
+	    status = _cairo_surface_reset (surface);
+	    if (status)
+		goto EVICT;
+
+	    status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
+	    if (status)
+		goto EVICT;
+
+	    cairo_surface_reference (surface);
+	}
+	else
+	{
+	  EVICT:
+	    surface = NULL;
+	}
     }
 
-    if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
-	/* in the rare event of a substitute surface being returned (e.g.
-	 * malloc failure) don't cache the fallback surface */
-	*out = surface;
-	goto NOCACHE;
+    if (surface == NULL) {
+	/* Not cached, need to create new */
+	surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
+	if (surface->status) {
+	    status = surface->status;
+	    goto UNLOCK;
+	}
+
+	if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
+	    /* in the rare event of a substitute surface being returned (e.g.
+	     * malloc failure) don't cache the fallback surface */
+	    *out = surface;
+	    goto NOCACHE;
+	}
     }
 
-    /* Cache new */
-    if (solid_surface_cache.size < MAX_SURFACE_CACHE_SIZE) {
+    if (i == solid_surface_cache.size)
 	solid_surface_cache.size++;
-    } else {
-	i = rand () % MAX_SURFACE_CACHE_SIZE;
 
-	/* Evict old */
-	cairo_surface_destroy (solid_surface_cache.cache[i].surface);
-    }
-
+    to_destroy = solid_surface_cache.cache[i].surface;
+    solid_surface_cache.cache[i].surface = surface;
     solid_surface_cache.cache[i].color   = pattern->color;
-    solid_surface_cache.cache[i].surface = surface;
+    solid_surface_cache.cache[i].content = pattern->content;
 
 DONE:
     *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
 
 NOCACHE:
     attribs->x_offset = attribs->y_offset = 0;
     cairo_matrix_init_identity (&attribs->matrix);
     attribs->extend = CAIRO_EXTEND_REPEAT;
     attribs->filter = CAIRO_FILTER_NEAREST;
     attribs->acquired = FALSE;
 
     status = CAIRO_STATUS_SUCCESS;
 
 UNLOCK:
     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 
+    if (to_destroy)
+      cairo_surface_destroy (to_destroy);
+
     return status;
 }
 
 static void
 _cairo_pattern_reset_solid_surface_cache (void)
 {
-    int i;
-
     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
 
-    for (i = 0; i < solid_surface_cache.size; i++)
-	cairo_surface_destroy (solid_surface_cache.cache[i].surface);
-    solid_surface_cache.size = 0;
+    /* remove surfaces starting from the end so that solid_surface_cache.cache
+     * is always in a consistent state when we release the mutex. */
+    while (solid_surface_cache.size) {
+	cairo_surface_t *surface;
+
+	solid_surface_cache.size--;
+	surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
+	solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
+
+	/* release the lock to avoid the possibility of a recursive
+	 * deadlock when the scaled font destroy closure gets called */
+	CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
+	cairo_surface_destroy (surface);
+	CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
+    }
 
     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 }
 
 /**
  * _cairo_pattern_is_opaque_solid
  *
  * Convenience function to determine whether a pattern is an opaque
@@ -1788,28 +1848,21 @@ cairo_int_status_t
 		cairo_color_t color;
 
 		_cairo_color_init_rgba (&color,
 					src->stops->color.red,
 					src->stops->color.green,
 					src->stops->color.blue,
 					src->stops->color.alpha);
 
-		_cairo_pattern_init_solid (&solid, &color,
-					   CAIRO_COLOR_IS_OPAQUE (&color) ?
-					   CAIRO_CONTENT_COLOR :
-					   CAIRO_CONTENT_COLOR_ALPHA);
+		_cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA);
 	    }
 	    else
 	    {
-		const cairo_color_t *color;
-
-		color =	_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
-		_cairo_pattern_init_solid (&solid, color,
-					   CAIRO_CONTENT_ALPHA);
+		_cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
 	    }
 
 	    status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
 							       x, y,
 							       width, height,
 							       surface_out,
 							       attributes);
 	}
@@ -1902,20 +1955,17 @@ cairo_int_status_t
     {
 	cairo_color_t combined;
 	cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
 	cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
 
 	combined = src_solid->color;
 	_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
 
-	_cairo_pattern_init_solid (&src_tmp.solid, &combined,
-				   CAIRO_COLOR_IS_OPAQUE (&combined) ?
-				   CAIRO_CONTENT_COLOR :
-				   CAIRO_CONTENT_COLOR_ALPHA);
+	_cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
 	mask = NULL;
     }
     else
     {
 	status = _cairo_pattern_init_copy (&src_tmp.base, src);
 	if (status)
 	    return status;
@@ -2023,25 +2073,20 @@ cairo_status_t
 	return CAIRO_STATUS_SUCCESS;
     }
 
     /* XXX: We could optimize gradients with pattern->extend of NONE
      * here in some cases, (eg. radial gradients and 1 axis of
      * horizontal/vertical linear gradients).
      */
 
-    /* XXX: because extents are represented as x, y, w, h we can't
-     * actually have a rectangle that covers our entire valid
-     * coordinate space, since we'd need width/height to be 2*INT_MAX.
-     */
-
-    extents->x = 0;
-    extents->y = 0;
-    extents->width = CAIRO_RECT_INT_MAX;
-    extents->height = CAIRO_RECT_INT_MAX;
+    extents->x = CAIRO_RECT_INT_MIN;
+    extents->y = CAIRO_RECT_INT_MIN;
+    extents->width = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
+    extents->height = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * cairo_pattern_get_rgba
  * @pattern: a #cairo_pattern_t
  * @red: return value for red component of color, or %NULL
--- a/gfx/cairo/cairo/src/cairo-pdf-operators-private.h
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h
@@ -40,57 +40,103 @@
  */
 
 #ifndef CAIRO_PDF_OPERATORS_H
 #define CAIRO_PDF_OPERATORS_H
 
 #include "cairo-compiler-private.h"
 #include "cairo-types-private.h"
 
+/* The glyph buffer size is based on the expected maximum glyphs in a
+ * line so that an entire line can be emitted in as one string. If the
+ * glyphs in a line exceeds this size the only downside is the slight
+ * overhead of emitting two strings.
+ */
+#define PDF_GLYPH_BUFFER_SIZE 200
+
 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_glyph {
+    unsigned int glyph_index;
+    double x_position;
+    double x_advance;
+} cairo_pdf_glyph_t;
+
 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_bool_t in_text_object; /* inside BT/ET pair */
+
+    /* PDF text state */
+    cairo_bool_t is_new_text_object; /* text object started but matrix and font not yet selected */
+    unsigned int font_id;
+    unsigned int subset_id;
+    cairo_matrix_t text_matrix; /* PDF text matrix (Tlm in the PDF reference) */
+    cairo_matrix_t cairo_to_pdftext; /* translate cairo coords to PDF text space */
+    cairo_matrix_t font_matrix_inverse;
+    double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */
+    double cur_y;
+    int hex_width;
+    int num_glyphs;
+    cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE];
+
+    /* PDF line style */
+    cairo_bool_t         has_line_style;
+    double		 line_width;
+    cairo_line_cap_t	 line_cap;
+    cairo_line_join_t	 line_join;
+    double		 miter_limit;
+    cairo_bool_t         has_dashes;
 } 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_private cairo_status_t
 _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_status_t
+_cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators);
+
+cairo_private void
+_cairo_pdf_operators_reset (cairo_pdf_operators_t	 *pdf_operators);
+
 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_operators_emit_stroke_style (cairo_pdf_operators_t	*pdf_operators,
+					cairo_stroke_style_t	*style,
+					double			 scale);
+
+cairo_private cairo_int_status_t
 _cairo_pdf_operators_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,
@@ -101,14 +147,20 @@ cairo_private cairo_int_status_t
 _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t 	*pdf_operators,
 				  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_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);
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
+				       const char                 *utf8,
+				       int                         utf8_len,
+				       cairo_glyph_t              *glyphs,
+				       int                         num_glyphs,
+				       const cairo_text_cluster_t *clusters,
+				       int                         num_clusters,
+				       cairo_bool_t                backward,
+				       cairo_scaled_font_t	  *scaled_font);
+
 
 #endif /* CAIRO_PDF_OPERATORS_H */
--- a/gfx/cairo/cairo/src/cairo-pdf-operators.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c
@@ -42,55 +42,107 @@
 #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"
 
 #include <ctype.h>
 
+static cairo_status_t
+_cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators);
+
+
 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;
+    pdf_operators->in_text_object = FALSE;
+    pdf_operators->num_glyphs = 0;
+    pdf_operators->has_line_style = FALSE;
 }
 
-void
+cairo_status_t
 _cairo_pdf_operators_fini (cairo_pdf_operators_t	*pdf_operators)
 {
+    return _cairo_pdf_operators_flush (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;
 }
 
+/* Change the output stream to a different stream.
+ * _cairo_pdf_operators_flush() should always be called before calling
+ * this function.
+ */
 void
 _cairo_pdf_operators_set_stream (cairo_pdf_operators_t	 *pdf_operators,
 				 cairo_output_stream_t   *stream)
 {
     pdf_operators->stream = stream;
+    pdf_operators->has_line_style = FALSE;
 }
 
 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;
+    pdf_operators->has_line_style = FALSE;
+}
+
+/* Finish writing out any pending commands to the stream. This
+ * function must be called by the surface before emitting anything
+ * into the PDF stream.
+ *
+ * pdf_operators may leave the emitted PDF for some operations
+ * unfinished in case subsequent operations can be merged. This
+ * function will finish off any incomplete operation so the stream
+ * will be in a state where the surface may emit it's own PDF
+ * operations (eg changing patterns).
+ *
+ */
+cairo_status_t
+_cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (pdf_operators->in_text_object)
+	status = _cairo_pdf_operators_end_text (pdf_operators);
+
+    return status;
+}
+
+/* Reset the known graphics state of the PDF consumer. ie no
+ * assumptions will be made about the state. The next time a
+ * particular graphics state is required (eg line width) the state
+ * operator is always emitted and then remembered for subsequent
+ * operatations.
+ *
+ * This should be called when starting a new stream or after emitting
+ * the 'Q' operator (where pdf-operators functions were called inside
+ * the q/Q pair).
+ */
+void
+_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators)
+{
+    pdf_operators->has_line_style = FALSE;
 }
 
 /* A word wrap stream can be used as a filter to do word wrapping on
  * top of an existing output stream. The word wrapping is quite
  * simple, using isspace to determine characters that separate
  * words. Any word that will cause the column count exceed the given
  * max_column will have a '\n' character emitted before it.
  *
@@ -473,24 +525,25 @@ static int
     case CAIRO_LINE_JOIN_BEVEL:
 	return 2;
     default:
 	ASSERT_NOT_REACHED;
 	return 0;
     }
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t	*pdf_operators,
 					cairo_stroke_style_t	*style,
 					double			 scale)
 {
     double *dash = style->dash;
     int num_dashes = style->num_dashes;
     double dash_offset = style->dash_offset;
+    double line_width = style->line_width * scale;
 
     /* PostScript has "special needs" when it comes to zero-length
      * dash segments with butt caps. It apparently (at least
      * according to ghostscript) draws hairlines for this
      * case. That's not what the cairo semantics want, so we first
      * touch up the array to eliminate any 0.0 values that will
      * result in "on" segments.
      */
@@ -545,45 +598,60 @@ static cairo_int_status_t
 		 * we rotated a 0.0 value to the front of the list.
 		 * Set i to -2 so it will get incremented to 0. */
 		if (i == 2)
 		    i = -2;
 	    }
 	}
     }
 
-    _cairo_output_stream_printf (pdf_operators->stream,
-				 "%f w\n",
-				 style->line_width * scale);
+    if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
+	_cairo_output_stream_printf (pdf_operators->stream,
+				     "%f w\n",
+				     line_width);
+	pdf_operators->line_width = line_width;
+    }
 
-    _cairo_output_stream_printf (pdf_operators->stream,
-				 "%d J\n",
-				 _cairo_pdf_line_cap (style->line_cap));
+    if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) {
+	_cairo_output_stream_printf (pdf_operators->stream,
+				     "%d J\n",
+				     _cairo_pdf_line_cap (style->line_cap));
+	pdf_operators->line_cap = style->line_cap;
+    }
 
-    _cairo_output_stream_printf (pdf_operators->stream,
-				 "%d j\n",
-				 _cairo_pdf_line_join (style->line_join));
+    if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) {
+	_cairo_output_stream_printf (pdf_operators->stream,
+				     "%d j\n",
+				     _cairo_pdf_line_join (style->line_join));
+	pdf_operators->line_join = style->line_join;
+    }
 
     if (num_dashes) {
 	int d;
 
 	_cairo_output_stream_printf (pdf_operators->stream, "[");
 	for (d = 0; d < num_dashes; d++)
 	    _cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
 	_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
 				     dash_offset * scale);
-    } else {
+	pdf_operators->has_dashes = TRUE;
+    } else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) {
 	_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
+	pdf_operators->has_dashes = FALSE;
     }
     if (dash != style->dash)
         free (dash);
 
-    _cairo_output_stream_printf (pdf_operators->stream,
-				 "%f M ",
-				 style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
+    if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
+	_cairo_output_stream_printf (pdf_operators->stream,
+				     "%f M ",
+				     style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
+	pdf_operators->miter_limit = style->miter_limit;
+    }
+    pdf_operators->has_line_style = TRUE;
 
     return _cairo_output_stream_get_status (pdf_operators->stream);
 }
 
 /* Scale the matrix so the largest absolute value of the non
  * translation components is 1.0. Return the scale required to restore
  * the matrix to the original values.
  *
@@ -617,16 +685,19 @@ static cairo_int_status_t
 				  cairo_matrix_t	*ctm_inverse,
 				  const char 		*pdf_operator)
 {
     cairo_status_t status;
     cairo_matrix_t m, path_transform;
     cairo_bool_t has_ctm = TRUE;
     double scale = 1.0;
 
+    if (pdf_operators->in_text_object)
+	status = _cairo_pdf_operators_end_text (pdf_operators);
+
     /* Optimize away the stroke ctm when it does not affect the
      * stroke. There are other ctm cases that could be optimized
      * however this is the most common.
      */
     if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 &&
 	fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0)
     {
 	has_ctm = FALSE;
@@ -712,16 +783,19 @@ cairo_int_status_t
 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;
 
+    if (pdf_operators->in_text_object)
+	status = _cairo_pdf_operators_end_text (pdf_operators);
+
     status = _cairo_pdf_operators_emit_path (pdf_operators,
 					     path,
 					     &pdf_operators->cairo_to_pdf,
 					     CAIRO_LINE_CAP_ROUND);
     if (status)
 	return status;
 
     switch (fill_rule) {
@@ -768,210 +842,572 @@ cairo_int_status_t
 					     style,
 					     ctm,
 					     ctm_inverse,
 					     operator);
 }
 
 #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)
+/* Emit the string of glyphs using the 'Tj' operator. This requires
+ * that the glyphs are positioned at their natural glyph advances. */
+static cairo_status_t
+_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
+					cairo_output_stream_t  	*stream)
+{
+    int i;
+
+    _cairo_output_stream_printf (stream, "<");
+    for (i = 0; i < pdf_operators->num_glyphs; i++) {
+	_cairo_output_stream_printf (stream,
+				     "%0*x",
+				     pdf_operators->hex_width,
+				     pdf_operators->glyphs[i].glyph_index);
+	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
+    }
+    _cairo_output_stream_printf (stream, ">Tj\n");
+
+    return _cairo_output_stream_get_status (stream);
+}
+
+/* Emit the string of glyphs using the 'TJ' operator.
+ *
+ * The TJ operator takes an array of strings of glyphs. Each string of
+ * glyphs is displayed using the glyph advances of each glyph to
+ * position the glyphs. A relative adjustment to the glyph advance may
+ * be specified by including the adjustment between two strings. The
+ * adjustment is in units of text space * -1000.
+ */
+static cairo_status_t
+_cairo_pdf_operators_emit_glyph_string_with_positioning (
+    cairo_pdf_operators_t   *pdf_operators,
+    cairo_output_stream_t   *stream)
 {
-    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, status_ignored;
-    double Tlm_x = 0, Tlm_y = 0;
-    double Tm_x = 0, y;
-    int i, hex_width;
+    int i;
+
+    _cairo_output_stream_printf (stream, "[<");
+    for (i = 0; i < pdf_operators->num_glyphs; i++) {
+	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
+	{
+	    double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
+	    int rounded_delta;
+
+	    delta = -1000.0*delta;
+	    /* As the delta is in 1/1000 of a unit of text space,
+	     * rounding to an integer should still provide sufficient
+	     * precision. We round the delta before adding to Tm_x so
+	     * that we keep track of the accumulated rounding error in
+	     * the PDF interpreter and compensate for it when
+	     * calculating subsequent deltas.
+	     */
+	    rounded_delta = _cairo_lround (delta);
+	    if (rounded_delta != 0) {
+		_cairo_output_stream_printf (stream,
+					     ">%d<",
+					     rounded_delta);
+	    }
+
+	    /* Convert the rounded delta back to text
+	     * space before adding to the current text
+	     * position. */
+	    delta = rounded_delta/-1000.0;
+	    pdf_operators->cur_x += delta;
+	}
+
+	_cairo_output_stream_printf (stream,
+				     "%0*x",
+				     pdf_operators->hex_width,
+				     pdf_operators->glyphs[i].glyph_index);
+	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
+    }
+    _cairo_output_stream_printf (stream, ">]TJ\n");
+
+    return _cairo_output_stream_get_status (stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
+{
     cairo_output_stream_t *word_wrap_stream;
+    cairo_status_t status;
+    int i;
+    double x;
 
-    for (i = 0; i < num_glyphs; i++)
-	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
+    if (pdf_operators->num_glyphs == 0)
+	return 0;
 
     word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
     status = _cairo_output_stream_get_status (word_wrap_stream);
     if (status)
 	return _cairo_output_stream_destroy (word_wrap_stream);
 
-    _cairo_output_stream_printf (word_wrap_stream,
-				 "BT\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) {
-	    status_ignored = _cairo_output_stream_destroy (word_wrap_stream);
-            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 (word_wrap_stream, ">] TJ\n");
-                in_TJ = FALSE;
-            }
-	    _cairo_output_stream_printf (word_wrap_stream,
-					 "/f-%d-%d 1 Tf\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) {
-		    status_ignored = _cairo_output_stream_destroy (word_wrap_stream);
-		    return status;
-		}
-	    }
-        }
-
-        if (subset_glyph.subset_id != current_subset_id || !diagonal) {
-            _cairo_output_stream_printf (word_wrap_stream,
-                                         "%f %f %f %f %f %f Tm\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 (word_wrap_stream,
-                                                     "%f %f Td\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 (word_wrap_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;
-			int rounded_delta;
-
-			delta = -1000.0*delta/scaled_font->scale.xx;
-			/* As the delta is in 1/1000 of a unit of text
-			 * space, rounding to an integer should still
-			 * provide sufficient precision. We round the
-			 * delta before adding to Tm_x so that we keep
-			 * track of the accumulated rounding error in
-			 * the PDF interpreter and compensate for it
-			 * when calculating subsequent deltas.
-			 */
-			rounded_delta = _cairo_lround (delta);
-			if (rounded_delta != 0) {
-			    _cairo_output_stream_printf (word_wrap_stream,
-							 "> %d <",
-							 rounded_delta);
-			}
-
-			/* Convert the rounded delta back to cairo
-			 * space before adding to the current text
-			 * position. */
-			delta = rounded_delta*scaled_font->scale.xx/-1000.0;
-                        Tm_x += delta;
-                    }
-                    _cairo_output_stream_printf (word_wrap_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;
-			int rounded_delta;
-
-			delta = -1000.0*delta/scaled_font->scale.xx;
-			rounded_delta = _cairo_lround (delta);
-			if (rounded_delta != 0) {
-			    _cairo_output_stream_printf (word_wrap_stream,
-							 "> %d <",
-							 rounded_delta);
-			}
-			delta = rounded_delta*scaled_font->scale.xx/-1000.0;
-                        Tm_x += delta;
-                    }
-                    _cairo_output_stream_printf (word_wrap_stream,
-                                                 "%0*x>] TJ\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 (word_wrap_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 (word_wrap_stream,
-                                                 "<%0*x> Tj ",
-                                                 hex_width,
-                                                 subset_glyph.subset_glyph_index);
-                    Tm_x += subset_glyph.x_advance;
-                }
-            }
-        } else {
-            _cairo_output_stream_printf (word_wrap_stream,
-                                         "<%0*x> Tj\n",
-                                         hex_width,
-                                         subset_glyph.subset_glyph_index);
-        }
+    /* Check if glyph advance used to position every glyph */
+    x = pdf_operators->cur_x;
+    for (i = 0; i < pdf_operators->num_glyphs; i++) {
+	if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
+	    break;
+	x += pdf_operators->glyphs[i].x_advance;
+    }
+    if (i == pdf_operators->num_glyphs) {
+	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
+							 word_wrap_stream);
+    } else {
+	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
+	    pdf_operators, word_wrap_stream);
     }
 
-    _cairo_output_stream_printf (word_wrap_stream,
-				 "ET\n");
-
+    pdf_operators->num_glyphs = 0;
     status = _cairo_output_stream_destroy (word_wrap_stream);
     if (status)
 	return status;
 
+    return status;
+}
+
+static cairo_status_t
+_cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators,
+				cairo_scaled_font_subsets_glyph_t *glyph,
+				double 			           x_position)
+{
+    double x, y;
+
+    x = glyph->x_advance;
+    y = glyph->y_advance;
+    if (glyph->is_scaled)
+	cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
+
+    pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
+    pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
+    pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
+    pdf_operators->num_glyphs++;
+    if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
+	return _cairo_pdf_operators_flush_glyphs (pdf_operators);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* Use 'Tm' operator to set the PDF text matrix. */
+static cairo_status_t
+_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
+				      cairo_matrix_t         *matrix)
+{
+    cairo_matrix_t inverse;
+    cairo_status_t status;
+
+    /* We require the matrix to be invertable. */
+    inverse = *matrix;
+    status = cairo_matrix_invert (&inverse);
+    if (status)
+	return status;
+
+    pdf_operators->text_matrix = *matrix;
+    pdf_operators->cur_x = 0;
+    pdf_operators->cur_y = 0;
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%f %f %f %f %f %f Tm\n",
+				 pdf_operators->text_matrix.xx,
+				 pdf_operators->text_matrix.yx,
+				 pdf_operators->text_matrix.xy,
+				 pdf_operators->text_matrix.yy,
+				 pdf_operators->text_matrix.x0,
+				 pdf_operators->text_matrix.y0);
+
+    pdf_operators->cairo_to_pdftext = *matrix;
+    status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
+    assert (status == CAIRO_STATUS_SUCCESS);
+    cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
+			   &pdf_operators->cairo_to_pdf,
+			   &pdf_operators->cairo_to_pdftext);
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+#define TEXT_MATRIX_TOLERANCE 1e-6
+
+/* Set the translation components of the PDF text matrix to x, y. The
+ * 'Td' operator is used to transform the text matrix.
+ */
+static cairo_status_t
+_cairo_pdf_operators_set_text_position (cairo_pdf_operators_t  *pdf_operators,
+					double 			x,
+					double 			y)
+{
+    cairo_matrix_t translate, inverse;
+    cairo_status_t status;
+
+    /* The Td operator transforms the text_matrix with:
+     *
+     *   text_matrix' = T x text_matrix
+     *
+     * where T is a translation matrix with the translation components
+     * set to the Td operands tx and ty.
+     */
+    inverse = pdf_operators->text_matrix;
+    status = cairo_matrix_invert (&inverse);
+    assert (status == CAIRO_STATUS_SUCCESS);
+    pdf_operators->text_matrix.x0 = x;
+    pdf_operators->text_matrix.y0 = y;
+    cairo_matrix_multiply (&translate, &pdf_operators->text_matrix, &inverse);
+    if (fabs(translate.x0) < TEXT_MATRIX_TOLERANCE)
+	translate.x0 = 0.0;
+    if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE)
+	translate.y0 = 0.0;
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "%f %f Td\n",
+				 translate.x0,
+				 translate.y0);
+    pdf_operators->cur_x = 0;
+    pdf_operators->cur_y = 0;
+
+    pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
+    status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
+    assert (status == CAIRO_STATUS_SUCCESS);
+    cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
+			   &pdf_operators->cairo_to_pdf,
+			   &pdf_operators->cairo_to_pdftext);
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+/* Select the font using the 'Tf' operator. The font size is set to 1
+ * as we use the 'Tm' operator to set the font scale.
+ */
+static cairo_status_t
+_cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t             *pdf_operators,
+				      cairo_scaled_font_subsets_glyph_t *subset_glyph)
+{
+    cairo_status_t status;
+
+    _cairo_output_stream_printf (pdf_operators->stream,
+				 "/f-%d-%d 1 Tf\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;
+    }
+    pdf_operators->font_id = subset_glyph->font_id;
+    pdf_operators->subset_id = subset_glyph->subset_id;
+
+    if (subset_glyph->is_composite)
+	pdf_operators->hex_width = 4;
+    else
+	pdf_operators->hex_width = 2;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
+{
+    _cairo_output_stream_printf (pdf_operators->stream, "BT\n");
+
+    pdf_operators->in_text_object = TRUE;
+    pdf_operators->num_glyphs = 0;
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators)
+{
+    cairo_status_t status;
+
+    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    if (status)
+	return status;
+
+    _cairo_output_stream_printf (pdf_operators->stream, "ET\n");
+
+    pdf_operators->in_text_object = FALSE;
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+/* Compare the scale components of two matrices. The translation
+ * components are ignored. */
+static cairo_bool_t
+_cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
+{
+    return (a->xx == b->xx &&
+	    a->xy == b->xy &&
+	    a->yx == b->yx &&
+	    a->yy == b->yy);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
+				       const char 	     *utf8,
+				       int		      utf8_len)
+{
+    uint16_t *utf16;
+    int utf16_len;
+    cairo_status_t status;
+    int i;
+
+    _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
+    if (utf8_len) {
+	status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
+	if (status)
+	    return status;
+
+	for (i = 0; i < utf16_len; i++) {
+	    _cairo_output_stream_printf (pdf_operators->stream,
+					 "%04x", (int) (utf16[i]));
+	}
+	free (utf16);
+    }
+    _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t    *pdf_operators)
+{
+    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
+
     return _cairo_output_stream_get_status (pdf_operators->stream);
 }
+
+static cairo_status_t
+_cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t             *pdf_operators,
+				 cairo_glyph_t              	   *glyph,
+				 cairo_scaled_font_subsets_glyph_t *subset_glyph)
+{
+    double x, y;
+    cairo_status_t status;
+
+    if (pdf_operators->is_new_text_object ||
+	pdf_operators->font_id != subset_glyph->font_id ||
+	pdf_operators->subset_id != subset_glyph->subset_id)
+    {
+	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
+	if (status)
+	    return status;
+
+	pdf_operators->is_new_text_object = FALSE;
+    }
+
+    x = glyph->x;
+    y = glyph->y;
+    cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
+
+    /* The TJ operator for displaying text strings can only set
+     * the horizontal position of the glyphs. If the y position
+     * (in text space) changes, use the Td operator to change the
+     * current position to the next glyph. We also use the Td
+     * operator to move the current position if the horizontal
+     * position changes by more than 10 (in text space
+     * units). This is becauses the horizontal glyph positioning
+     * in the TJ operator is intended for kerning and there may be
+     * PDF consumers that do not handle very large position
+     * adjustments in TJ.
+     */
+    if (fabs(x - pdf_operators->cur_x) > 10 ||
+	fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
+    {
+	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+	if (status)
+	    return status;
+
+	x = glyph->x;
+	y = glyph->y;
+	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
+	status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
+	if (status)
+	    return status;
+
+	x = 0.0;
+	y = 0.0;
+    }
+
+    status = _cairo_pdf_operators_add_glyph (pdf_operators,
+					     subset_glyph,
+					     x);
+    return status;
+}
+
+/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
+ * empty string.
+ */
+static cairo_int_status_t
+_cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t      *pdf_operators,
+				   const char                 *utf8,
+				   int                         utf8_len,
+				   cairo_glyph_t              *glyphs,
+				   int                         num_glyphs,
+				   cairo_bool_t                backward,
+				   cairo_scaled_font_t	      *scaled_font)
+{
+    cairo_scaled_font_subsets_glyph_t subset_glyph;
+    cairo_glyph_t *cur_glyph;
+    cairo_status_t status;
+    int i;
+
+    /* If the cluster maps 1 glyph to 1 or more unicode characters, we
+     * first try _map_glyph() with the unicode string to see if it can
+     * use toUnicode to map our glyph to the unicode. This will fail
+     * if the glyph is already mapped to a different unicode string.
+     *
+     * We also go through this path if no unicode mapping was
+     * supplied (utf8_len < 0).
+     *
+     * Mapping a glyph to a zero length unicode string requires the
+     * use of ActualText.
+     */
+    if (num_glyphs == 1 && utf8_len != 0) {
+	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+						       scaled_font,
+						       glyphs->index,
+						       utf8,
+						       utf8_len < 0 ? 0 : utf8_len,
+						       &subset_glyph);
+	if (status)
+	    return status;
+
+	if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
+	    status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+						      glyphs,
+						      &subset_glyph);
+	    return 0;
+	}
+    }
+
+    /* Fallback to using ActualText to map zero or more glyphs to a
+     * unicode string. */
+    _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
+    cur_glyph = glyphs;
+    for (i = 0; i < num_glyphs; i++) {
+	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+						       scaled_font,
+						       cur_glyph->index,
+						       NULL, 0,
+						       &subset_glyph);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+						  cur_glyph,
+						  &subset_glyph);
+	if (status)
+	    return status;
+
+	if (backward)
+	    cur_glyph--;
+	else
+	    cur_glyph++;
+    }
+    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    if (status)
+	return status;
+
+    status = _cairo_pdf_operators_end_actualtext (pdf_operators);
+
+    return status;
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
+				       const char                 *utf8,
+				       int                         utf8_len,
+				       cairo_glyph_t              *glyphs,
+				       int                         num_glyphs,
+				       const cairo_text_cluster_t *clusters,
+				       int                         num_clusters,
+				       cairo_bool_t                backward,
+				       cairo_scaled_font_t	  *scaled_font)
+{
+    cairo_status_t status;
+    int i;
+    cairo_matrix_t text_matrix, invert_y_axis;
+    double x, y;
+    const char *cur_text;
+    cairo_glyph_t *cur_glyph;
+
+    pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
+    status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
+    if (status == CAIRO_STATUS_INVALID_MATRIX)
+	return CAIRO_STATUS_SUCCESS;
+    if (status)
+	return status;
+
+    pdf_operators->is_new_text_object = FALSE;
+    if (pdf_operators->in_text_object == FALSE) {
+	_cairo_pdf_operators_begin_text (pdf_operators);
+
+	/* Force Tm and Tf to be emitted when starting a new text
+	 * object.*/
+	pdf_operators->is_new_text_object = TRUE;
+    }
+
+    cairo_matrix_init_scale (&invert_y_axis, 1, -1);
+    text_matrix = scaled_font->scale;
+
+    /* Invert y axis in font space  */
+    cairo_matrix_multiply (&text_matrix, &text_matrix, &invert_y_axis);
+
+    /* Invert y axis in device space  */
+    cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
+
+    if (pdf_operators->is_new_text_object ||
+	! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
+    {
+	_cairo_pdf_operators_flush_glyphs (pdf_operators);
+	x = glyphs[0].x;
+	y = glyphs[0].y;
+	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
+	text_matrix.x0 = x;
+	text_matrix.y0 = y;
+	status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix);
+	if (status == CAIRO_STATUS_INVALID_MATRIX)
+	    return CAIRO_STATUS_SUCCESS;
+	if (status)
+	    return status;
+    }
+
+    if (num_clusters > 0) {
+	cur_text = utf8;
+	if (backward)
+	    cur_glyph = glyphs + num_glyphs;
+	else
+	    cur_glyph = glyphs;
+	for (i = 0; i < num_clusters; i++) {
+	    if (backward)
+		cur_glyph -= clusters[i].num_glyphs;
+	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+							cur_text,
+							clusters[i].num_bytes,
+							cur_glyph,
+							clusters[i].num_glyphs,
+							backward,
+							scaled_font);
+	    if (status)
+		return status;
+
+	    cur_text += clusters[i].num_bytes;
+	    if (!backward)
+		cur_glyph += clusters[i].num_glyphs;
+	}
+    } else {
+	for (i = 0; i < num_glyphs; i++) {
+	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+							NULL,
+							-1, /* no unicode string available */
+							&glyphs[i],
+							1,
+							FALSE,
+							scaled_font);
+	    if (status)
+		return status;
+	}
+    }
+
+    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
@@ -85,18 +85,23 @@ typedef struct _cairo_pdf_smask_group
     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;
+    char           	 *utf8;
+    int                   utf8_len;
     cairo_glyph_t	 *glyphs;
     int			  num_glyphs;
+    cairo_text_cluster_t *clusters;
+    int                   num_clusters;
+    cairo_bool_t          backward;
     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;
 
@@ -148,12 +153,19 @@ struct _cairo_pdf_surface {
     } group_stream;
 
     cairo_pdf_operators_t pdf_operators;
     cairo_paginated_mode_t paginated_mode;
     cairo_bool_t select_pattern_gstate_saved;
 
     cairo_bool_t force_fallbacks;
 
+    cairo_bool_t current_pattern_is_solid_color;
+    cairo_bool_t current_color_is_stroke;
+    double current_color_red;
+    double current_color_green;
+    double current_color_blue;
+    double current_color_alpha;
+
     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
@@ -43,16 +43,17 @@
 #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-output-stream-private.h"
 #include "cairo-meta-surface-private.h"
+#include "cairo-type3-glyph-surface-private.h"
 
 #include <time.h>
 #include <zlib.h>
 
 /* Issues:
  *
  * - We embed an image in the stream each time it's composited.  We
  *   could add generation counters to surfaces and remember the stream
@@ -276,16 +277,17 @@ static cairo_surface_t *
     surface->group_stream.active = FALSE;
     surface->group_stream.stream = NULL;
     surface->group_stream.mem_stream = NULL;
 
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
 
     surface->force_fallbacks = FALSE;
     surface->select_pattern_gstate_saved = FALSE;
+    surface->current_pattern_is_solid_color = 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);
@@ -296,19 +298,23 @@ static cairo_surface_t *
     _cairo_output_stream_printf (surface->output,
 				 "%%%c%c%c%c\n", 181, 237, 174, 251);
 
     surface->paginated_surface =  _cairo_paginated_surface_create (
 	                                  &surface->base,
 					  CAIRO_CONTENT_COLOR_ALPHA,
 					  width, height,
 					  &cairo_pdf_surface_paginated_backend);
+
     status = surface->paginated_surface->status;
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_STATUS_SUCCESS) {
+	/* paginated keeps the only reference to surface now, drop ours */
+	cairo_surface_destroy (&surface->base);
 	return surface->paginated_surface;
+    }
 
 BAIL1:
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
 BAIL0:
     _cairo_array_fini (&surface->objects);
     free (surface);
 
     /* destroy stream on behalf of caller */
@@ -736,18 +742,22 @@ 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->utf8)
+	free (group->utf8);
     if (group->glyphs)
 	free (group->glyphs);
+    if (group->clusters)
+	free (group->clusters);
     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)
@@ -766,25 +776,33 @@ static cairo_status_t
 
     /* 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;
+
+	/* Gradients with zero stops do not produce any output */
 	if (gradient->n_stops == 0)
 	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+	/* Gradients with one stop are the same as solid colors */
+	if (gradient->n_stops == 1) {
+	    pattern_res->id = 0;
+	    gstate_res->id = 0;
+	    return CAIRO_STATUS_SUCCESS;
+	}
     }
 
     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);
     }
@@ -846,16 +864,18 @@ static cairo_status_t
 	if (_cairo_output_stream_get_status (output))
 	    return _cairo_output_stream_destroy (output);
     }
 
     surface->pdf_stream.active = TRUE;
     surface->pdf_stream.self = self;
     surface->pdf_stream.length = length;
     surface->pdf_stream.compressed = compressed;
+    surface->current_pattern_is_solid_color = FALSE;
+    _cairo_pdf_operators_reset (&surface->pdf_operators);
 
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\n"
 				 "<< /Length %d 0 R\n",
 				 surface->pdf_stream.self.id,
 				 surface->pdf_stream.length.id);
     if (compressed)
 	_cairo_output_stream_printf (surface->output,
@@ -887,16 +907,20 @@ static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     long length;
 
     if (! surface->pdf_stream.active)
 	return CAIRO_STATUS_SUCCESS;
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     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,
 				     "\n");
     }
@@ -977,16 +1001,18 @@ static cairo_status_t
 			       cairo_pdf_resource_t *resource)
 {
     cairo_status_t status;
 
     assert (surface->pdf_stream.active == FALSE);
     assert (surface->group_stream.active == FALSE);
 
     surface->group_stream.active = TRUE;
+    surface->current_pattern_is_solid_color = FALSE;
+    _cairo_pdf_operators_reset (&surface->pdf_operators);
 
     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;
@@ -1028,16 +1054,20 @@ 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_SUCCESS, status2;
 
     assert (surface->pdf_stream.active == FALSE);
     assert (surface->group_stream.active == TRUE);
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     if (surface->compress_content) {
 	status = _cairo_output_stream_destroy (surface->group_stream.stream);
 	surface->group_stream.stream = NULL;
 
 	_cairo_output_stream_printf (surface->group_stream.mem_stream,
 				     "\n");
     }
     surface->output = surface->group_stream.old_output;
@@ -1111,16 +1141,20 @@ static cairo_status_t
 static cairo_status_t
 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
 {
     cairo_status_t status;
 
     assert (surface->pdf_stream.active == TRUE);
     assert (surface->group_stream.active == FALSE);
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     _cairo_output_stream_printf (surface->output, "Q\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\n",
@@ -1176,17 +1210,20 @@ static cairo_status_t
 				 info.id);
 
     _cairo_output_stream_printf (surface->output,
 				 "startxref\n"
 				 "%ld\n"
 				 "%%%%EOF\n",
 				 offset);
 
-     _cairo_pdf_operators_fini (&surface->pdf_operators);
+    status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
+    /* pdf_operators has already been flushed when the last stream was
+     * closed so we should never be writing anything here. */
+    assert(status2 == CAIRO_STATUS_SUCCESS);
 
     /* 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);
@@ -1226,22 +1263,32 @@ static cairo_status_t
     }
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_start_page (void *abstract_surface)
 {
+    cairo_pdf_surface_t *surface = abstract_surface;
+
+    _cairo_pdf_group_resources_clear (&surface->resources);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_pdf_surface_has_fallback_images (void 		*abstract_surface,
+					cairo_bool_t 	 has_fallbacks)
+{
     cairo_status_t status;
     cairo_pdf_surface_t *surface = abstract_surface;
 
-    surface->has_fallback_images = FALSE;
-    _cairo_pdf_group_resources_clear (&surface->resources);
-    status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
+    surface->has_fallback_images = has_fallbacks;
+    status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Emit alpha channel from the image into the given data, providing
  * an id that can be used to reference the resulting SMask object.
@@ -1491,17 +1538,17 @@ 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)
 {
     double old_width, old_height;
     cairo_paginated_mode_t old_paginated_mode;
     cairo_clip_t *old_clip;
     cairo_rectangle_int_t meta_extents;
-    cairo_status_t status, status2;
+    cairo_status_t status;
     int alpha = 0;
 
     status = _cairo_surface_get_extents (meta_surface, &meta_extents);
     if (status)
 	return status;
 
     old_width = surface->width;
     old_height = surface->height;
@@ -1519,41 +1566,41 @@ static cairo_status_t
     status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
     if (status)
 	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;
+	    return status;
 
 	_cairo_output_stream_printf (surface->output,
 				     "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
 				     alpha,
 				     surface->width,
 				     surface->height);
     }
 
     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;
+	return status;
+
+    status = _cairo_surface_set_clip (&surface->base, old_clip);
+    if (status)
+	return status;
 
     status = _cairo_pdf_surface_close_content_stream (surface);
 
- CLEANUP_GROUP:
     _cairo_pdf_surface_set_size_internal (surface,
 					  old_width,
 					  old_height);
     surface->paginated_mode = old_paginated_mode;
-    status2 = _cairo_surface_set_clip (&surface->base, old_clip);
-    if (status == CAIRO_STATUS_SUCCESS)
-	status = status2;
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
 					 cairo_pdf_pattern_t	*pdf_pattern)
 {
@@ -2557,48 +2604,96 @@ static cairo_status_t
 static cairo_status_t
 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
 				   cairo_pattern_t     *pattern,
 				   cairo_pdf_resource_t pattern_res,
 				   cairo_bool_t         is_stroke)
 {
     cairo_status_t status;
     int alpha;
+    cairo_bool_t is_solid_color = FALSE;
+    cairo_color_t *solid_color;
 
     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 ",
-				     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\n",
-                                     alpha);
-	surface->select_pattern_gstate_saved = FALSE;
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
+
+	is_solid_color = TRUE;
+	solid_color = &solid->color;
+    }
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+	pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
+    {
+	cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
+
+	if (gradient->n_stops == 1) {
+	    is_solid_color = TRUE;
+	    solid_color = &gradient->stops[0].color;
+	}
+    }
+
+    if (is_solid_color) {
+	if (surface->current_pattern_is_solid_color == FALSE ||
+	    surface->current_color_red != solid_color->red ||
+	    surface->current_color_green != solid_color->green ||
+	    surface->current_color_blue != solid_color->blue ||
+	    surface->current_color_is_stroke != is_stroke)
+	{
+	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	    if (status)
+		return status;
+
+	    _cairo_output_stream_printf (surface->output,
+					 "%f %f %f ",
+					 solid_color->red,
+					 solid_color->green,
+					 solid_color->blue);
+
+	    if (is_stroke)
+		_cairo_output_stream_printf (surface->output, "RG ");
+	    else
+		_cairo_output_stream_printf (surface->output, "rg ");
+
+	    surface->current_color_red = solid_color->red;
+	    surface->current_color_green = solid_color->green;
+	    surface->current_color_blue = solid_color->blue;
+	    surface->current_color_is_stroke = is_stroke;
+	}
+
+	if (surface->current_pattern_is_solid_color == FALSE ||
+	    surface->current_color_alpha != solid_color->alpha)
+	{
+	    status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
+	    if (status)
+		return status;
+
+	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	    if (status)
+		return status;
+
+	    _cairo_output_stream_printf (surface->output,
+					 "/a%d gs\n",
+					 alpha);
+	    surface->current_color_alpha = solid_color->alpha;
+	}
+
+	surface->current_pattern_is_solid_color = TRUE;
     } else {
 	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;
 
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	/* fill-stroke calls select_pattern twice. Don't save if the
 	 * gstate is already saved. */
 	if (!surface->select_pattern_gstate_saved)
 	    _cairo_output_stream_printf (surface->output, "q ");
 
 	if (is_stroke) {
 	    _cairo_output_stream_printf (surface->output,
 					 "/Pattern CS /p%d SCN ",
@@ -2607,27 +2702,38 @@ static cairo_status_t
 	    _cairo_output_stream_printf (surface->output,
 					 "/Pattern cs /p%d scn ",
 					 pattern_res.id);
 	}
 	_cairo_output_stream_printf (surface->output,
 				     "/a%d gs\n",
 				     alpha);
 	surface->select_pattern_gstate_saved = TRUE;
+	surface->current_pattern_is_solid_color = FALSE;
     }
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
-static void
+static cairo_int_status_t
 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
 {
-    if (surface->select_pattern_gstate_saved)
+    cairo_int_status_t status;
+
+    if (surface->select_pattern_gstate_saved) {
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output, "Q\n");
+	_cairo_pdf_operators_reset (&surface->pdf_operators);
+    }
     surface->select_pattern_gstate_saved = FALSE;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 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;
 
@@ -2666,19 +2772,27 @@ static cairo_int_status_t
 static cairo_int_status_t
 _cairo_pdf_surface_intersect_clip_path (void			*abstract_surface,
 					cairo_path_fixed_t	*path,
 					cairo_fill_rule_t	fill_rule,
 					double			tolerance,
 					cairo_antialias_t	antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
 
     if (path == NULL) {
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output, "Q q\n");
+	surface->current_pattern_is_solid_color = FALSE;
+	_cairo_pdf_operators_reset (&surface->pdf_operators);
+
 	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,
@@ -2738,44 +2852,64 @@ static void
 
     /* TODO: Figure out which other defaults to be inherited by /Page
      * objects. */
     _cairo_output_stream_printf (surface->output,
 				 ">>\n"
 				 "endobj\n");
 }
 
+static cairo_status_t
+_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t	*surface,
+					   const char 		*utf8)
+{
+    uint16_t *utf16 = NULL;
+    int utf16_len = 0;
+    cairo_status_t status;
+    int i;
+
+    if (utf8 && *utf8) {
+	status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
+	if (status && status != CAIRO_STATUS_INVALID_STRING)
+	    return status;
+    }
+
+    _cairo_output_stream_printf (surface->output, "<");
+    if (utf16 == NULL || utf16_len == 0) {
+	/* According to the "ToUnicode Mapping File Tutorial"
+	 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
+	 *
+	 * Glyphs that do not map to a Unicode code point must be
+	 * mapped to 0xfffd "REPLACEMENT CHARACTER".
+	 */
+	_cairo_output_stream_printf (surface->output,
+				     "fffd");
+    } else {
+	for (i = 0; i < utf16_len; i++)
+	    _cairo_output_stream_printf (surface->output,
+					 "%04x", (int) (utf16[i]));
+    }
+    _cairo_output_stream_printf (surface->output, ">");
+
+    if (utf16)
+	free (utf16);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 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;
-
-    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;
-
-        status = backend->map_glyphs_to_unicode (font_subset->scaled_font,
-		                                 font_subset);
-	if (status)
-	    return status;
-    }
 
     status = _cairo_pdf_surface_open_stream (surface,
 					      NULL,
 					      surface->compress_content,
 					      NULL);
     if (status)
 	return status;
 
@@ -2799,36 +2933,41 @@ static cairo_int_status_t
         _cairo_output_stream_printf (surface->output,
                                      "<00> <ff>\n");
     }
 
     _cairo_output_stream_printf (surface->output,
                                   "endcodespacerange\n");
 
     num_bfchar = font_subset->num_glyphs - 1;
+
     /* The CMap specification has a limit of 100 characters per beginbfchar operator */
     _cairo_output_stream_printf (surface->output,
                                  "%d beginbfchar\n",
                                  num_bfchar > 100 ? 100 : num_bfchar);
+
     for (i = 0; i < num_bfchar; i++) {
         if (i != 0 && i % 100 == 0) {
             _cairo_output_stream_printf (surface->output,
                                          "endbfchar\n"
                                          "%d beginbfchar\n",
                                          num_bfchar - i > 100 ? 100 : num_bfchar - i);
         }
         if (is_composite) {
             _cairo_output_stream_printf (surface->output,
-                                         "<%04x> <%04lx>\n",
-                                         i + 1, font_subset->to_unicode[i + 1]);
+                                         "<%04x> ",
+                                         i + 1);
         } else {
             _cairo_output_stream_printf (surface->output,
-                                         "<%02x> <%04lx>\n",
-                                         i + 1, font_subset->to_unicode[i + 1]);
+                                         "<%02x> ",
+                                         i + 1);
         }
+	_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
+	_cairo_output_stream_printf (surface->output,
+				     "\n");
     }
     _cairo_output_stream_printf (surface->output,
                                  "endbfchar\n");
 
     _cairo_output_stream_printf (surface->output,
                                  "endcmap\n"
                                  "CMapName currentdict /CMap defineresource pop\n"
                                  "end\n"
@@ -3296,121 +3435,69 @@ static cairo_status_t
     font.subset_resource = subset_resource;
     status = _cairo_array_append (&surface->fonts, &font);
 
     _cairo_truetype_subset_fini (&subset);
 
     return status;
 }
 
-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)
+static cairo_status_t
+_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
+			     cairo_output_stream_t *stream)
 {
-    cairo_scaled_glyph_t *scaled_glyph;
-    cairo_status_t status;
-    cairo_image_surface_t *image;
-    unsigned char *row, *byte;
-    int rows, cols;
-    double x_advance, y_advance;
-
-    status = _cairo_scaled_glyph_lookup (scaled_font,
-					 glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_METRICS|
-					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					 &scaled_glyph);
-    if (status)
-	return status;
-
-    x_advance = scaled_glyph->metrics.x_advance;
-    y_advance = scaled_glyph->metrics.y_advance;
-    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
-    *bbox = scaled_glyph->bbox;
-    *width = x_advance;
-
-    image = scaled_glyph->surface;
-    if (image->format != CAIRO_FORMAT_A1) {
-	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	status = cairo_surface_status (&image->base);
-	if (status)
-	    return status;
-    }
-
-    status = _cairo_pdf_surface_open_stream (surface,
-				             NULL,
-					     surface->compress_content,
-					     NULL);
-    if (status) {
-	if (image != scaled_glyph->surface)
-	    cairo_surface_destroy (&image->base);
-	return status;
-    }
-
-    *glyph_ret = surface->pdf_stream.self;
-
-    _cairo_output_stream_printf (surface->output,
-				 "%f 0 %f %f %f %f d1\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.x),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
-
-    _cairo_output_stream_printf (surface->output,
-				 "%f 0 0 %f %f %f cm\n",
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
-
-    _cairo_output_stream_printf (surface->output,
+    unsigned char *byte, output_byte;
+    int row, col, num_cols;
+
+    /* The only image type supported by Type 3 fonts are 1-bit image
+     * masks */
+    assert (image->format == CAIRO_FORMAT_A1);
+
+    _cairo_output_stream_printf (stream,
 				 "BI\n"
 				 "/IM true\n"
 				 "/W %d\n"
 				 "/H %d\n"
 				 "/BPC 1\n"
 				 "/D [1 0]\n",
 				 image->width,
 				 image->height);
 
-    _cairo_output_stream_printf (surface->output,
+    _cairo_output_stream_printf (stream,
 				 "ID ");
-    for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
-	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
-	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    _cairo_output_stream_write (surface->output, &output_byte, 1);
+
+    num_cols = (image->width + 7) / 8;
+    for (row = 0; row < image->height; row++) {
+	byte = image->data + row * image->stride;
+	for (col = 0; col < num_cols; col++) {
+	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    _cairo_output_stream_write (stream, &output_byte, 1);
+	    byte++;
 	}
     }
-    _cairo_output_stream_printf (surface->output,
+
+    _cairo_output_stream_printf (stream,
 				 "\nEI\n");
 
-    status = _cairo_pdf_surface_close_stream (surface);
-
-    if (image != scaled_glyph->surface)
-	cairo_surface_destroy (&image->base);
-
-    return status;
+    return _cairo_output_stream_get_status (stream);
 }
 
 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_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}};
+    cairo_surface_t *type3_surface;
 
     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)
@@ -3421,23 +3508,39 @@ static cairo_status_t
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
     if (widths == NULL) {
         free (glyphs);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
+						       NULL,
+						       _cairo_pdf_emit_imagemask);
+
     for (i = 0; i < font_subset->num_glyphs; i++) {
-        status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
-                                                       font_subset->scaled_font,
-                                                       font_subset->glyphs[i],
-                                                       &glyphs[i],
-                                                       &bbox,
-                                                       &widths[i]);
+	status = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
+						 surface->compress_content,
+						 NULL);
+	glyphs[i] = surface->pdf_stream.self;
+	if (i == 0) {
+	    status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
+								   surface->output,
+								   &bbox,
+								   &widths[i]);
+	} else {
+	    status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
+							    surface->output,
+							    font_subset->glyphs[i],
+							    &bbox,
+							    &widths[i]);
+	}
+	status = _cairo_pdf_surface_close_stream (surface);
 	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;
@@ -3447,16 +3550,17 @@ static cairo_status_t
             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_surface_destroy (type3_surface);
     if (status) {
 	free (glyphs);
 	free (widths);
 	return status;
     }
 
     encoding = _cairo_pdf_surface_new_object (surface);
     if (encoding.id == 0) {
@@ -3507,30 +3611,26 @@ static cairo_status_t
 
     _cairo_pdf_surface_update_object (surface, subset_resource);
     matrix = font_subset->scaled_font->scale_inverse;
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\n"
 				 "<< /Type /Font\n"
 				 "   /Subtype /Type3\n"
 				 "   /FontBBox [%f %f %f %f]\n"
-				 "   /FontMatrix [ %f %f %f %f 0 0 ]\n"
+				 "   /FontMatrix [ 1 0 0 1 0 0 ]\n"
 				 "   /Encoding %d 0 R\n"
 				 "   /CharProcs %d 0 R\n"
 				 "   /FirstChar 0\n"
 				 "   /LastChar %d\n",
 				 subset_resource.id,
 				 _cairo_fixed_to_double (font_bbox.p1.x),
-				 _cairo_fixed_to_double (font_bbox.p1.y),
+				 - _cairo_fixed_to_double (font_bbox.p2.y),
 				 _cairo_fixed_to_double (font_bbox.p2.x),
-				 _cairo_fixed_to_double (font_bbox.p2.y),
-				 matrix.xx,
-				 matrix.yx,
-				 -matrix.xy,
-				 -matrix.yy,
+				 - _cairo_fixed_to_double (font_bbox.p1.y),
 				 encoding.id,
 				 char_procs.id,
 				 font_subset->num_glyphs - 1);
 
     _cairo_output_stream_printf (surface->output,
 				 "   /Widths [");
     for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output, " %f", widths[i]);
@@ -3577,16 +3677,17 @@ static cairo_status_t
         status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             return status;
 #endif
 
         status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             return status;
+
     }
 
     ASSERT_NOT_REACHED;
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
@@ -3725,17 +3826,19 @@ static cairo_status_t
 	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\n",
 				     surface->width, surface->height);
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     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);
@@ -3778,17 +3881,19 @@ static cairo_status_t
 	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\n",
 				     surface->width, surface->height);
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     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);
@@ -3867,26 +3972,31 @@ static cairo_status_t
     case PDF_STROKE:
 	status = _cairo_pdf_operators_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);
+	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+							group->utf8, group->utf8_len,
+							group->glyphs, group->num_glyphs,
+							group->clusters, group->num_clusters,
+							group->backward,
+							group->scaled_font);
 	break;
     }
     if (status)
 	return status;
 
-    _cairo_pdf_surface_unselect_pattern (surface);
+    status = _cairo_pdf_surface_unselect_pattern (surface);
+    if (status)
+	return status;
+
     status = _cairo_pdf_surface_close_group (surface, NULL);
 
     _cairo_pdf_surface_set_size_internal (surface,
 					  old_width,
 					  old_height);
 
     return status;
 }
@@ -4156,18 +4266,29 @@ static cairo_int_status_t
 
     /* The SOURCE operator is supported if the pattern is opaque or if
      * there is nothing painted underneath. */
     if (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)) {
-		if (_cairo_pattern_is_opaque (pattern))
+		if (_cairo_pattern_is_opaque (pattern)) {
 		    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+		} else {
+		    /* FIXME: The analysis surface does not yet have
+		     * the capability to analyze a non opaque meta
+		     * surface and mark it supported if there is
+		     * nothing underneath. For now meta surfaces of
+		     * type CONTENT_COLOR_ALPHA painted with
+		     * OPERATOR_SOURCE will result in a fallback
+		     * image. */
+
+		    return CAIRO_INT_STATUS_UNSUPPORTED;
+		}
 	    } else {
 		return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
 										surface_pattern);
 	    }
 	}
 
 	if (_cairo_pattern_is_opaque (pattern))
 	    return CAIRO_STATUS_SUCCESS;
@@ -4197,17 +4318,16 @@ static cairo_int_status_t
     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, TRUE);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
 			  cairo_pattern_t	*source)
@@ -4252,30 +4372,36 @@ static cairo_int_status_t
 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 	if (status)
 	    return status;
 
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output,
 				     "q /s%d gs /x%d Do Q\n",
 				     gstate_res.id,
 				     group->group_res.id);
     } else {
 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
 
 	_cairo_output_stream_printf (surface->output,
 				     "0 0 %f %f re f\n",
 				     surface->width, surface->height);
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_mask	(void			*abstract_surface,
 			 cairo_operator_t	 op,
@@ -4328,16 +4454,20 @@ static cairo_int_status_t
     status = _cairo_pdf_surface_add_smask (surface, group->group_res);
     if (status)
 	return status;
 
     status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
     if (status)
 	return status;
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     _cairo_output_stream_printf (surface->output,
 				 "q /s%d gs /x%d Do Q\n",
 				 group->group_res.id,
 				 group->source_res.id);
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
@@ -4396,16 +4526,20 @@ static cairo_int_status_t
 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 	if (status)
 	    return status;
 
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output,
 				     "q /s%d gs /x%d Do Q\n",
 				     gstate_res.id,
 				     group->group_res.id);
     } else {
 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
 	if (status)
 	    return status;
@@ -4413,17 +4547,19 @@ static cairo_int_status_t
 	status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
 					      path,
 					      style,
 					      ctm,
 					      ctm_inverse);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_fill (void			*abstract_surface,
 			 cairo_operator_t	 op,
@@ -4480,32 +4616,38 @@ static cairo_int_status_t
 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 	if (status)
 	    return status;
 
 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 	if (status)
 	    return status;
 
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output,
 				     "q /s%d gs /x%d Do Q\n",
 				     gstate_res.id,
 				     group->group_res.id);
     } else {
 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
 
 	status = _cairo_pdf_operators_fill (&surface->pdf_operators,
 					    path,
 					    fill_rule);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_int_status_t
 _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
 				cairo_operator_t      fill_op,
@@ -4582,28 +4724,41 @@ static cairo_int_status_t
 					       path,
 					       fill_rule,
 					       stroke_style,
 					       stroke_ctm,
 					       stroke_ctm_inverse);
     if (status)
 	return status;
 
-    _cairo_pdf_surface_unselect_pattern (surface);
+    status = _cairo_pdf_surface_unselect_pattern (surface);
+    if (status)
+	return status;
 
     return _cairo_output_stream_get_status (surface->output);
 }
 
+static cairo_bool_t
+_cairo_pdf_surface_has_show_text_glyphs	(void			*abstract_surface)
+{
+    return TRUE;
+}
+
 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_show_text_glyphs (void			*abstract_surface,
+				     cairo_operator_t	 	 op,
+				     cairo_pattern_t	       	*source,
+				     const char                 *utf8,
+				     int                         utf8_len,
+				     cairo_glyph_t		*glyphs,
+				     int			 num_glyphs,
+				     const cairo_text_cluster_t *clusters,
+				     int                         num_clusters,
+				     cairo_bool_t                backward,
+				     cairo_scaled_font_t	*scaled_font)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
     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);
@@ -4621,60 +4776,103 @@ static cairo_int_status_t
     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 = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-	if (group->glyphs == NULL) {
-	    _cairo_pdf_smask_group_destroy (group);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	if (utf8_len) {
+	    group->utf8 = malloc(utf8_len);
+	    if (group->utf8) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->utf8, utf8, utf8_len);
 	}
-	memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
+	group->utf8_len = utf8_len;
+
+	if (num_glyphs) {
+	    group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	    if (group->glyphs == NULL) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
+	}
 	group->num_glyphs = num_glyphs;
+
+	if (num_clusters) {
+	    group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
+	    if (group->clusters) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
+	}
+	group->num_clusters = num_clusters;
+
 	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;
 
 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 	if (status)
 	    return status;
 
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->output,
 				     "q /s%d gs /x%d Do Q\n",
 				     gstate_res.id,
 				     group->group_res.id);
     } else {
 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 	if (status)
 	    return status;
 
-	status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
-						   glyphs,
-						   num_glyphs,
-						   scaled_font);
+	/* Each call to show_glyphs() with a transclucent pattern must
+	 * be in a separate text object otherwise overlapping text
+	 * from separate calls to show_glyphs will not composite with
+	 * each other. */
+	if (! _cairo_pattern_is_opaque (source)) {
+	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	    if (status)
+		return status;
+	}
+
+	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+							utf8, utf8_len,
+							glyphs, num_glyphs,
+							clusters, num_clusters,
+							backward,
+							scaled_font);
 	if (status)
 	    return status;
 
-	_cairo_pdf_surface_unselect_pattern (surface);
+	status = _cairo_pdf_surface_unselect_pattern (surface);
+	if (status)
+	    return status;
     }
 
     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;
 
     surface->paginated_mode = paginated_mode;
 }
@@ -4704,20 +4902,25 @@ static const cairo_surface_backend_t cai
     NULL, /* scaled_glyph_fini */
 
     /* Here are the drawing functions */
 
     _cairo_pdf_surface_paint,
     _cairo_pdf_surface_mask,
     _cairo_pdf_surface_stroke,
     _cairo_pdf_surface_fill,
-    _cairo_pdf_surface_show_glyphs,
+    NULL, /* show_glyphs */
     NULL, /* snapshot */
 
     NULL, /* is_compatible */
     NULL, /* reset */
     _cairo_pdf_surface_fill_stroke,
+    NULL, /* create_solid_pattern_surface */
+    _cairo_pdf_surface_has_show_text_glyphs,
+    _cairo_pdf_surface_show_text_glyphs,
 };
 
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
     _cairo_pdf_surface_start_page,
-    _cairo_pdf_surface_set_paginated_mode
+    _cairo_pdf_surface_set_paginated_mode,
+    NULL, /* set_bounding_box */
+    _cairo_pdf_surface_has_fallback_images,
 };
--- a/gfx/cairo/cairo/src/cairo-pdf.h
+++ b/gfx/cairo/cairo/src/cairo-pdf.h
@@ -32,17 +32,17 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_PDF_H
 #define CAIRO_PDF_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_PDF_SURFACE
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
 cairo_pdf_surface_create (const char		*filename,
 			  double		 width_in_points,
--- a/gfx/cairo/cairo/src/cairo-pen.c
+++ b/gfx/cairo/cairo/src/cairo-pen.c
@@ -40,25 +40,16 @@ static int
 _cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix);
 
 static void
 _cairo_pen_compute_slopes (cairo_pen_t *pen);
 
 static void
 _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
 
-void
-_cairo_pen_init_empty (cairo_pen_t *pen)
-{
-    pen->radius = 0;
-    pen->tolerance = 0;
-    pen->vertices = NULL;
-    pen->num_vertices = 0;
-}
-
 cairo_status_t
 _cairo_pen_init (cairo_pen_t	*pen,
 		 double		 radius,
 		 double		 tolerance,
 		 cairo_matrix_t	*ctm)
 {
     int i;
     int reflect;
@@ -73,20 +64,24 @@ cairo_status_t
     } else {
 	reflect = 1;
     }
 
     pen->num_vertices = _cairo_pen_vertices_needed (tolerance,
 						    radius,
 						    ctm);
 
-    pen->vertices = _cairo_malloc_ab (pen->num_vertices,
-	                              sizeof (cairo_pen_vertex_t));
-    if (pen->vertices == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
+	pen->vertices = _cairo_malloc_ab (pen->num_vertices,
+					  sizeof (cairo_pen_vertex_t));
+	if (pen->vertices == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else {
+	pen->vertices = pen->vertices_embedded;
+    }
 
     /*
      * Compute pen coordinates.  To generate the right ellipse, compute points around
      * a circle in user space and transform them to device space.  To get a consistent
      * orientation in device space, flip the pen if the transformation matrix
      * is reflecting
      */
     for (i=0; i < pen->num_vertices; i++) {
@@ -102,54 +97,76 @@ cairo_status_t
     _cairo_pen_compute_slopes (pen);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_pen_fini (cairo_pen_t *pen)
 {
-    free (pen->vertices);
-    pen->vertices = NULL;
+    if (pen->vertices != pen->vertices_embedded)
+	free (pen->vertices);
 
-    _cairo_pen_init_empty (pen);
+    pen->vertices = pen->vertices_embedded;
+    pen->num_vertices = 0;
 }
 
 cairo_status_t
 _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
 {
     *pen = *other;
 
+    pen->vertices = pen->vertices_embedded;
     if (pen->num_vertices) {
-	pen->vertices = _cairo_malloc_ab (pen->num_vertices,
-	       	                          sizeof (cairo_pen_vertex_t));
-	if (pen->vertices == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
+	    pen->vertices = _cairo_malloc_ab (pen->num_vertices,
+					      sizeof (cairo_pen_vertex_t));
+	    if (pen->vertices == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
 
-	memcpy (pen->vertices, other->vertices, pen->num_vertices * sizeof (cairo_pen_vertex_t));
+	memcpy (pen->vertices, other->vertices,
+		pen->num_vertices * sizeof (cairo_pen_vertex_t));
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
 {
-    cairo_pen_vertex_t *vertices;
     cairo_status_t status;
     int num_vertices;
     int i;
 
     num_vertices = pen->num_vertices + num_points;
-    vertices = _cairo_realloc_ab (pen->vertices,
-	                          num_vertices, sizeof (cairo_pen_vertex_t));
-    if (vertices == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (num_vertices > ARRAY_LENGTH (pen->vertices_embedded) ||
+	pen->vertices != pen->vertices_embedded)
+    {
+	cairo_pen_vertex_t *vertices;
+
+	if (pen->vertices == pen->vertices_embedded) {
+	    vertices = _cairo_malloc_ab (num_vertices,
+		                         sizeof (cairo_pen_vertex_t));
+	    if (vertices == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    pen->vertices = vertices;
+	    memcpy (vertices, pen->vertices,
+		    pen->num_vertices * sizeof (cairo_pen_vertex_t));
+	} else {
+	    vertices = _cairo_realloc_ab (pen->vertices,
+					  num_vertices,
+					  sizeof (cairo_pen_vertex_t));
+	    if (vertices == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+
+	pen->vertices = vertices;
+    }
+
     pen->num_vertices = num_vertices;
 
     /* initialize new vertices */
     for (i=0; i < num_points; i++)
 	pen->vertices[pen->num_vertices-num_points+i].point = point[i];
 
     status = _cairo_hull_compute (pen->vertices, &pen->num_vertices);
     if (status)
--- a/gfx/cairo/cairo/src/cairo-png.c
+++ b/gfx/cairo/cairo/src/cairo-png.c
@@ -192,16 +192,19 @@ write_png (cairo_surface_t	*surface,
 	break;
     case CAIRO_FORMAT_A8:
 	depth = 8;
 	png_color_type = PNG_COLOR_TYPE_GRAY;
 	break;
     case CAIRO_FORMAT_A1:
 	depth = 1;
 	png_color_type = PNG_COLOR_TYPE_GRAY;
+#ifndef WORDS_BIGENDIAN
+	png_set_packswap (png);
+#endif
 	break;
     default:
 	status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
 	goto BAIL3;
     }
 
     png_set_IHDR (png, info,
 		  image->width,
@@ -269,17 +272,17 @@ stdio_write_func (png_structp png, png_b
  * @filename: the name of a file to write to
  *
  * Writes the contents of @surface to a new file @filename as a PNG
  * image.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
  * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
  * be allocated for the operation or
- * CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
+ * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
  * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
  * while attempting to write the file.
  **/
 cairo_status_t
 cairo_surface_write_to_png (cairo_surface_t	*surface,
 			    const char		*filename)
 {
     FILE *fp;
@@ -336,26 +339,32 @@ stream_write_func (png_structp png, png_
  * @write_func: a #cairo_write_func_t
  * @closure: closure data for the write function
  *
  * Writes the image surface to the write function.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
  * successfully.  Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
  * memory could not be allocated for the operation,
- * CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
+ * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
  * pixel contents.
  **/
 cairo_status_t
 cairo_surface_write_to_png_stream (cairo_surface_t	*surface,
 				   cairo_write_func_t	write_func,
 				   void			*closure)
 {
     struct png_write_closure_t png_closure;
 
+    if (surface->status)
+	return surface->status;
+
+    if (surface->finished)
+	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
+
     png_closure.write_func = write_func;
     png_closure.closure = closure;
 
     return write_png (surface, stream_write_func, &png_closure);
 }
 slim_hidden_def (cairo_surface_write_to_png_stream);
 
 static inline int
@@ -493,35 +502,47 @@ read_png (png_rw_ptr	read_func,
 	color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     {
 	png_set_gray_to_rgb (png);
     }
 
     if (interlace != PNG_INTERLACE_NONE)
         png_set_interlace_handling (png);
 
+    png_set_filler (png, 0xff, PNG_FILLER_AFTER);
+
+    /* recheck header after setting EXPAND options */
+    png_read_update_info (png, info);
+    png_get_IHDR (png, info,
+                  &png_width, &png_height, &depth,
+                  &color_type, &interlace, NULL, NULL);
+    if (depth != 8 || interlace != PNG_INTERLACE_NONE ||
+	! (color_type == PNG_COLOR_TYPE_RGB ||
+	   color_type == PNG_COLOR_TYPE_RGB_ALPHA))
+    {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
+	goto BAIL;
+    }
+
     switch (color_type) {
 	default:
-	case PNG_COLOR_TYPE_GRAY_ALPHA:
+	    ASSERT_NOT_REACHED;
+	    /* fall-through just in case ;-) */
+
 	case PNG_COLOR_TYPE_RGB_ALPHA:
 	    format = CAIRO_FORMAT_ARGB32;
 	    png_set_read_user_transform_fn (png, premultiply_data);
 	    break;
 
-	case PNG_COLOR_TYPE_GRAY:
-	case PNG_COLOR_TYPE_PALETTE:
 	case PNG_COLOR_TYPE_RGB:
 	    format = CAIRO_FORMAT_RGB24;
 	    png_set_read_user_transform_fn (png, convert_bytes_to_data);
-	    png_set_filler (png, 0xff, PNG_FILLER_AFTER);
 	    break;
     }
 
-    png_read_update_info (png, info);
-
     stride = cairo_format_stride_for_width (format, png_width);
     if (stride < 0) {
 	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
 	goto BAIL;
     }
 
     data = _cairo_malloc_ab (png_height, stride);
     if (data == NULL) {
@@ -592,19 +613,19 @@ stdio_read_func (png_structp png, png_by
  * Creates a new image surface and initializes the contents to the
  * given PNG file.
  *
  * Return value: a new #cairo_surface_t initialized with the contents
  * of the PNG file, or a "nil" surface if any error occurred. A nil
  * surface can be checked for with cairo_surface_status(surface) which
  * may return one of the following values:
  *
- *	CAIRO_STATUS_NO_MEMORY
- *	CAIRO_STATUS_FILE_NOT_FOUND
- *	CAIRO_STATUS_READ_ERROR
+ *	%CAIRO_STATUS_NO_MEMORY
+ *	%CAIRO_STATUS_FILE_NOT_FOUND
+ *	%CAIRO_STATUS_READ_ERROR
  **/
 cairo_surface_t *
 cairo_image_surface_create_from_png (const char *filename)
 {
     FILE *fp;
     cairo_surface_t *surface;
 
     fp = fopen (filename, "rb");
--- a/gfx/cairo/cairo/src/cairo-polygon.c
+++ b/gfx/cairo/cairo/src/cairo-polygon.c
@@ -43,18 +43,18 @@ static cairo_status_t
 
 void
 _cairo_polygon_init (cairo_polygon_t *polygon)
 {
     polygon->status = CAIRO_STATUS_SUCCESS;
 
     polygon->num_edges = 0;
 
-    polygon->edges_size = 0;
-    polygon->edges = NULL;
+    polygon->edges = polygon->edges_embedded;
+    polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded);
 
     polygon->has_current_point = FALSE;
 }
 
 void
 _cairo_polygon_fini (cairo_polygon_t *polygon)
 {
     if (polygon->edges && polygon->edges != polygon->edges_embedded)
@@ -74,36 +74,27 @@ cairo_status_t
 }
 
 /* make room for at least one more edge */
 static cairo_status_t
 _cairo_polygon_grow (cairo_polygon_t *polygon)
 {
     cairo_edge_t *new_edges;
     int old_size = polygon->edges_size;
-    int embedded_size = ARRAY_LENGTH (polygon->edges_embedded);
-    int new_size = 2 * MAX (old_size, 16);
-
-    /* we have a local buffer at polygon->edges_embedded.  try to fulfill the request
-     * from there. */
-    if (old_size < embedded_size) {
-	polygon->edges = polygon->edges_embedded;
-	polygon->edges_size = embedded_size;
-	return CAIRO_STATUS_SUCCESS;
-    }
+    int new_size = 2 * old_size;
 
     assert (polygon->num_edges <= polygon->edges_size);
 
     if (polygon->edges == polygon->edges_embedded) {
 	new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
-	if (new_edges)
+	if (new_edges != NULL)
 	    memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
     } else {
 	new_edges = _cairo_realloc_ab (polygon->edges,
-	       	                       new_size, sizeof (cairo_edge_t));
+		                       new_size, sizeof (cairo_edge_t));
     }
 
     if (new_edges == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     polygon->edges = new_edges;
     polygon->edges_size = new_size;
 
--- a/gfx/cairo/cairo/src/cairo-private.h
+++ b/gfx/cairo/cairo/src/cairo-private.h
@@ -44,13 +44,14 @@ struct _cairo {
     cairo_reference_count_t ref_count;
 
     cairo_status_t status;
 
     cairo_user_data_array_t user_data;
 
     cairo_gstate_t *gstate;
     cairo_gstate_t  gstate_tail[1];
+    cairo_gstate_t *gstate_freelist;
 
     cairo_path_fixed_t path[1];
 };
 
 #endif /* CAIRO_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h
@@ -64,16 +64,22 @@ typedef struct cairo_ps_surface {
     double width;
     double height;
     int bbox_x1, bbox_y1, bbox_x2, bbox_y2;
     cairo_matrix_t cairo_to_ps;
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_bool_t use_string_datasource;
 
+    cairo_bool_t current_pattern_is_solid_color;
+    double current_color_red;
+    double current_color_green;
+    double current_color_blue;
+    double current_color_alpha;
+
     int num_pages;
 
     cairo_paginated_mode_t paginated_mode;
 
     cairo_bool_t force_fallbacks;
 
     cairo_scaled_font_subsets_t *font_subsets;
 
--- a/gfx/cairo/cairo/src/cairo-ps-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ps-surface.c
@@ -44,16 +44,17 @@
 #include "cairoint.h"
 #include "cairo-ps.h"
 #include "cairo-ps-surface-private.h"
 #include "cairo-pdf-operators-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 "cairo-type3-glyph-surface-private.h"
 
 #include <stdio.h>
 #include <ctype.h>
 #include <time.h>
 #include <zlib.h>
 #include <errno.h>
 
 #define DEBUG_PS 0
@@ -167,34 +168,45 @@ static void
 				 "/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto\n"
 				 "      0 exch rlineto 0 rlineto closepath } bind def\n"
 				 "/S { stroke } bind def\n"
 				 "/f { fill } bind def\n"
 				 "/f* { eofill } bind def\n"
 				 "/n { newpath } bind def\n"
 				 "/W { clip } bind def\n"
 				 "/W* { eoclip } bind def\n"
-				 "/Tf { pop /cairo_font exch def } bind def\n"
 				 "/BT { } bind def\n"
 				 "/ET { } bind def\n"
-				 "/Tj { show } bind def\n"
+				 "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n"
+				 "    { globaldict begin /?pdfmark /pop load def /pdfmark\n"
+				 "    /cleartomark load def end } ifelse\n"
+				 "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n"
+				 "/EMC { mark /EMC pdfmark } bind def\n"
+				 "/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n"
+				 "/Tj { show currentpoint cairo_store_point } bind def\n"
 				 "/TJ {\n"
 				 "  {\n"
 				 "    dup\n"
 				 "    type /stringtype eq\n"
 				 "    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
 				 "  } forall\n"
+				 "  currentpoint cairo_store_point\n"
 				 "} bind def\n"
-				 "/Td { matrix translate cairo_font_matrix matrix concatmatrix aload\n"
-				 "      /cairo_font_matrix exch def 6 2 roll 0 0 6 array astore\n"
-				 "      cairo_font exch selectfont moveto } bind def\n"
-				 "/Tm { 6 copy 6 array astore /cairo_font_matrix exch def 6 2 roll 0 0\n"
-				 "      6 array astore cairo_font exch selectfont moveto } bind def\n"
+				 "/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
+				 "    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
+				 "/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
+				 "      { cairo_selectfont } if } bind def\n"
+				 "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
+				 "      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
+				 "      /cairo_font where { cairo_selectfont } if } bind def\n"
+				 "/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
+				 "      cairo_store_point /cairo_font where { cairo_selectfont } if } bind def\n"
 				 "/g { setgray } bind def\n"
-				 "/rg { setrgbcolor } bind def\n");
+				 "/rg { setrgbcolor } bind def\n"
+				 "/d1 { setcachedevice } bind def\n");
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%EndProlog\n");
 
     num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);
     if (num_comments) {
 	_cairo_output_stream_printf (surface->final_stream,
 				     "%%%%BeginSetup\n");
@@ -364,207 +376,158 @@ static cairo_status_t
 				 "] def\n"
 				 "FontName currentdict end definefont pop\n");
 
     _cairo_truetype_subset_fini (&subset);
 
     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,
-					  cairo_box_t           *bbox)
+static cairo_status_t
+_cairo_ps_emit_imagemask (cairo_image_surface_t *image,
+			  cairo_output_stream_t *stream)
 {
-    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,
-				 "%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.x),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
-
-    _cairo_output_stream_printf (surface->final_stream,
+
+    /* The only image type supported by Type 3 fonts are 1-bit image
+     * masks */
+    assert (image->format == CAIRO_FORMAT_A1);
+
+    _cairo_output_stream_printf (stream,
 				 "<<\n"
 				 "   /ImageType 1\n"
 				 "   /Width %d\n"
 				 "   /Height %d\n"
-				 "   /ImageMatrix [%f %f %f %f %f %f]\n"
+				 "   /ImageMatrix [%d 0 0 %d 0 %d]\n"
 				 "   /Decode [1 0]\n"
 				 "   /BitsPerComponent 1\n",
 				 image->width,
 				 image->height,
-				 image->base.device_transform.xx,
-				 image->base.device_transform.yx,
-				 image->base.device_transform.xy,
-				 image->base.device_transform.yy,
-				 image->base.device_transform.x0,
-				 image->base.device_transform.y0);
-
-    _cairo_output_stream_printf (surface->final_stream,
+				 image->width,
+				 -image->height,
+				 image->height);
+
+    _cairo_output_stream_printf (stream,
 				 "   /DataSource   {<");
     for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
 	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
 	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    _cairo_output_stream_printf (surface->final_stream, "%02x ", output_byte);
+	    _cairo_output_stream_printf (stream, "%02x ", output_byte);
 	}
-	_cairo_output_stream_printf (surface->final_stream, "\n   ");
+	_cairo_output_stream_printf (stream, "\n   ");
     }
-    _cairo_output_stream_printf (surface->final_stream,
+    _cairo_output_stream_printf (stream,
 				 "   >}\n");
-    _cairo_output_stream_printf (surface->final_stream,
+    _cairo_output_stream_printf (stream,
 				 ">>\n");
 
-    _cairo_output_stream_printf (surface->final_stream,
+    _cairo_output_stream_printf (stream,
 				 "imagemask\n");
 
-    if (image != scaled_glyph->surface)
-	cairo_surface_destroy (&image->base);
-
-    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,
-			      cairo_box_t               *bbox)
-{
-    cairo_status_t	    status = CAIRO_STATUS_SUCCESS;
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "\t\t{ %% %d\n", subset_glyph_index);
-
-    if (subset_glyph_index != 0) {
-	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;
+    return _cairo_output_stream_get_status (stream);
 }
 
 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}};
+    cairo_surface_t *type3_surface;
+    double width;
 
 #if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_type3_font_subset\n");
 #endif
 
     matrix = font_subset->scaled_font->scale_inverse;
     _cairo_output_stream_printf (surface->final_stream,
 				 "8 dict begin\n"
 				 "/FontType 3 def\n"
-				 "/FontMatrix [%f %f %f %f 0 0] def\n"
+				 "/FontMatrix [1 0 0 1 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);
+				 "0 1 255 { Encoding exch /.notdef put } for\n");
+
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
+						       NULL,
+						       _cairo_ps_emit_imagemask);
 
     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,
-					       &bbox);
+	_cairo_output_stream_printf (surface->final_stream,
+				     "    { %% %d\n", i);
+	if (i == 0) {
+	    status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
+								   surface->final_stream,
+								   &bbox,
+								   &width);
+	} else {
+	    status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
+							    surface->final_stream,
+							    font_subset->glyphs[i],
+							    &bbox,
+							    &width);
+	}
 	if (status)
 	    return status;
 
+	_cairo_output_stream_printf (surface->final_stream,
+				     "    }\n");
         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_surface_destroy (type3_surface);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "] 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"
 				 "/f-%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.y),
 				 _cairo_fixed_to_double (font_bbox.p2.x),
-				 _cairo_fixed_to_double (font_bbox.p2.y),
+				 - _cairo_fixed_to_double (font_bbox.p1.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,
@@ -723,16 +686,17 @@ static cairo_surface_t *
     surface->ps_level_used = CAIRO_PS_LEVEL_2;
     surface->width  = width;
     surface->height = height;
     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, height);
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
     surface->force_fallbacks = FALSE;
     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
     surface->use_string_datasource = FALSE;
+    surface->current_pattern_is_solid_color = FALSE;
 
     _cairo_pdf_operators_init (&surface->pdf_operators,
 			       surface->stream,
 			       &surface->cairo_to_ps,
 			       surface->font_subsets);
     surface->num_pages = 0;
 
     _cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
@@ -742,18 +706,21 @@ static cairo_surface_t *
     surface->dsc_comment_target = &surface->dsc_header_comments;
 
     surface->paginated_surface = _cairo_paginated_surface_create (
 	                                   &surface->base,
 					   CAIRO_CONTENT_COLOR_ALPHA,
 					   width, height,
 					   &cairo_ps_surface_paginated_backend);
     status = surface->paginated_surface->status;
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status == CAIRO_STATUS_SUCCESS) {
+	/* paginated keeps the only reference to surface now, drop ours */
+	cairo_surface_destroy (&surface->base);
 	return surface->paginated_surface;
+    }
 
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
  CLEANUP_OUTPUT_STREAM:
     status_ignored = _cairo_output_stream_destroy (surface->stream);
     fclose (surface->tmpfile);
  CLEANUP_SURFACE:
     free (surface);
  CLEANUP:
@@ -1319,29 +1286,40 @@ static cairo_int_status_t
     cairo_ps_surface_t *surface = abstract_surface;
 
     /* Increment before print so page numbers start at 1. */
     surface->num_pages++;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_int_status_t
 _cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
 {
+    cairo_int_status_t status;
+
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     _cairo_output_stream_printf (surface->stream,
 				 "Q\n");
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_ps_surface_show_page (void *abstract_surface)
 {
     cairo_ps_surface_t *surface = abstract_surface;
-
-    _cairo_ps_surface_end_page (surface);
+    cairo_int_status_t status;
+
+    status = _cairo_ps_surface_end_page (surface);
+    if (status)
+	return status;
 
     _cairo_output_stream_printf (surface->stream, "showpage\n");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
 color_is_gray (double red, double green, double blue)
@@ -1713,31 +1691,31 @@ static cairo_output_stream_t *
 
 static cairo_status_t
 _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t    *surface,
 					      cairo_image_surface_t *image,
 					      cairo_image_surface_t **opaque_image)
 {
     const cairo_color_t *background_color;
     cairo_surface_t *opaque;
-    cairo_pattern_union_t pattern;
+    cairo_surface_pattern_t pattern;
     cairo_status_t status;
 
     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)
 	return opaque->status;
 
-    _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
+    _cairo_pattern_init_for_surface (&pattern, &image->base);
 
     status = _cairo_surface_fill_rectangle (opaque,
 					    CAIRO_OPERATOR_SOURCE,
 					    background_color,
 					    0, 0,
 					    image->width, image->height);
     if (status)
 	goto fail;
@@ -2047,16 +2025,18 @@ static cairo_status_t
 
     old_content = surface->content;
     old_width = surface->width;
     old_height = surface->height;
     old_cairo_to_ps = surface->cairo_to_ps;
     old_clip = _cairo_surface_get_clip (&surface->base);
     surface->width = meta_extents.width;
     surface->height = meta_extents.height;
+    surface->current_pattern_is_solid_color = FALSE;
+    _cairo_pdf_operators_reset (&surface->pdf_operators);
     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
 						  &surface->cairo_to_ps);
     _cairo_output_stream_printf (surface->stream,
 				 "  q\n"
 				 "  0 0 %f %f rectclip\n",
 				 surface->width,
 				 surface->height);
@@ -2070,21 +2050,27 @@ static cairo_status_t
     }
 
     status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
 						CAIRO_META_REGION_NATIVE);
     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	return status;
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     _cairo_output_stream_printf (surface->stream,
 				 "  Q\n");
     surface->content = old_content;
     surface->width = old_width;
     surface->height = old_height;
+    surface->current_pattern_is_solid_color = FALSE;
+    _cairo_pdf_operators_reset (&surface->pdf_operators);
     surface->cairo_to_ps = old_cairo_to_ps;
     status = _cairo_surface_set_clip (&surface->base, old_clip);
     if (status)
 	return status;
 
     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
 						  &surface->cairo_to_ps);
 
@@ -2613,16 +2599,29 @@ static cairo_status_t
     cairo_status_t status;
     cairo_gradient_pattern_t *gradient = &pattern->base;
     double first_stop, last_stop;
     int repeat_begin = 0, repeat_end = 1;
 
     if (pattern->base.n_stops == 0)
         return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
+    if (pattern->base.n_stops == 1) {
+	cairo_solid_pattern_t solid;
+
+	_cairo_pattern_init_solid (&solid,
+				   &pattern->base.stops[0].color,
+				   CAIRO_CONTENT_COLOR_ALPHA);
+	_cairo_ps_surface_emit_solid_pattern (surface,
+					      &solid);
+	_cairo_pattern_fini (&solid.base);
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     pat_to_ps = pattern->base.base.matrix;
     status = cairo_matrix_invert (&pat_to_ps);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
@@ -2740,16 +2739,29 @@ static cairo_status_t
     double x1, y1, x2, y2, r1, r2;
     cairo_matrix_t pat_to_ps;
     cairo_extend_t extend;
     cairo_status_t status;
 
     if (pattern->base.n_stops == 0)
         return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
+    if (pattern->base.n_stops == 1) {
+	cairo_solid_pattern_t solid;
+
+	_cairo_pattern_init_solid (&solid,
+				   &pattern->base.stops[0].color,
+				   CAIRO_CONTENT_COLOR_ALPHA);
+	_cairo_ps_surface_emit_solid_pattern (surface,
+					      &solid);
+	_cairo_pattern_fini (&solid.base);
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     pat_to_ps = pattern->base.base.matrix;
     status = cairo_matrix_invert (&pat_to_ps);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
@@ -2796,23 +2808,51 @@ static cairo_status_t
     return status;
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
 				cairo_pattern_t *pattern,
 				cairo_operator_t op)
 {
-    /* FIXME: We should keep track of what pattern is currently set in
-     * the postscript file and only emit code if we're setting a
-     * different pattern. */
     cairo_status_t status;
 
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
+
+	if (surface->current_pattern_is_solid_color == FALSE ||
+	    surface->current_color_red != solid->color.red ||
+	    surface->current_color_green != solid->color.green ||
+	    surface->current_color_blue != solid->color.blue ||
+	    surface->current_color_alpha != solid->color.alpha)
+	{
+	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	    if (status)
+		return status;
+
+	    _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
+
+	    surface->current_pattern_is_solid_color = TRUE;
+	    surface->current_color_red = solid->color.red;
+	    surface->current_color_green = solid->color.green;
+	    surface->current_color_blue = solid->color.blue;
+	    surface->current_color_alpha = solid->color.alpha;
+	}
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    surface->current_pattern_is_solid_color = FALSE;
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	    return status;
+
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
+
 	_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
 	break;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
 	status = _cairo_ps_surface_emit_surface_pattern (surface,
 							 (cairo_surface_pattern_t *) pattern,
 							 op);
 	if (status)
@@ -2841,27 +2881,35 @@ static cairo_int_status_t
 _cairo_ps_surface_intersect_clip_path (void		   *abstract_surface,
 				cairo_path_fixed_t *path,
 				cairo_fill_rule_t   fill_rule,
 				double		    tolerance,
 				cairo_antialias_t   antialias)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
+    cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return CAIRO_STATUS_SUCCESS;
 
 #if DEBUG_PS
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_intersect_clip_path\n");
 #endif
 
     if (path == NULL) {
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (stream, "Q q\n");
+	surface->current_pattern_is_solid_color = FALSE;
+	_cairo_pdf_operators_reset (&surface->pdf_operators);
+
 	return CAIRO_STATUS_SUCCESS;
     }
 
     return _cairo_pdf_operators_clip (&surface->pdf_operators,
 				      path,
 				      fill_rule);
 }
 
@@ -2914,16 +2962,20 @@ static cairo_int_status_t
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_paint\n");
 #endif
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status)
 	return status;
 
+    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+    if (status)
+	return status;
+
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
 	(source->extend == CAIRO_EXTEND_NONE ||
 	 source->extend == CAIRO_EXTEND_PAD))
     {
 	_cairo_output_stream_printf (stream, "q 0 0 %d %d rectclip\n",
 				     extents.width,
 				     extents.height);
 
@@ -3006,31 +3058,36 @@ static cairo_int_status_t
     _cairo_output_stream_printf (surface->stream,
 				 "%% _cairo_ps_surface_fill\n");
 #endif
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
 	(source->extend == CAIRO_EXTEND_NONE ||
 	 source->extend == CAIRO_EXTEND_PAD))
     {
+	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+	if (status)
+	    return status;
+
 	_cairo_output_stream_printf (surface->stream, "q\n");
 
 	status =  _cairo_pdf_operators_clip (&surface->pdf_operators,
 					     path,
 					     fill_rule);
 	if (status)
 	    return status;
 
 	status = _cairo_ps_surface_paint_surface (surface,
 						 (cairo_surface_pattern_t *) source,
 						 op);
 	if (status)
 	    return status;
 
 	_cairo_output_stream_printf (surface->stream, "Q\n");
+	_cairo_pdf_operators_reset (&surface->pdf_operators);
     } else {
 	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;
 
@@ -3043,17 +3100,18 @@ static cairo_int_status_t
 }
 
 static cairo_int_status_t
 _cairo_ps_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_scaled_font_t   *scaled_font,
+			       int		     *remaining_glyphs)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_ps_surface_analyze_operation (surface, op, source);
 
     assert (_cairo_ps_surface_operation_supported (surface, op, source));
@@ -3068,20 +3126,22 @@ static cairo_int_status_t
 
     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;
 
-    return _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
-					     glyphs,
-					     num_glyphs,
-					     scaled_font);
+    return _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+						  NULL, 0,
+						  glyphs, num_glyphs,
+						  NULL, 0,
+						  FALSE,
+						  scaled_font);
 }
 
 static void
 _cairo_ps_surface_set_paginated_mode (void			*abstract_surface,
 				      cairo_paginated_mode_t	 paginated_mode)
 {
     cairo_ps_surface_t *surface = abstract_surface;
 
@@ -3145,16 +3205,18 @@ static cairo_int_status_t
 	    surface->bbox_x1 = x1;
 	if (y1 < surface->bbox_y1)
 	    surface->bbox_y1 = y1;
 	if (x2 > surface->bbox_x2)
 	    surface->bbox_x2 = x2;
 	if (y2 > surface->bbox_y2)
 	    surface->bbox_y2 = y2;
     }
+    surface->current_pattern_is_solid_color = FALSE;
+    _cairo_pdf_operators_reset (&surface->pdf_operators);
 
     return _cairo_output_stream_get_status (surface->stream);
 }
 
 static const cairo_surface_backend_t cairo_ps_surface_backend = {
     CAIRO_SURFACE_TYPE_PS,
     _cairo_ps_surface_create_similar,
     _cairo_ps_surface_finish,
--- a/gfx/cairo/cairo/src/cairo-ps.h
+++ b/gfx/cairo/cairo/src/cairo-ps.h
@@ -32,17 +32,17 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_PS_H
 #define CAIRO_PS_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_PS_SURFACE
 
 #include <stdio.h>
 
 CAIRO_BEGIN_DECLS
 
 /* PS-surface functions */
--- a/gfx/cairo/cairo/src/cairo-quartz-font.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-font.c
@@ -122,19 +122,19 @@ struct _cairo_quartz_scaled_font {
 };
 
 struct _cairo_quartz_font_face {
     cairo_font_face_t base;
 
     CGFontRef cgFont;
 };
 
-/**
- ** font face backend
- **/
+/*
+ * font face backend
+ */
 
 static void
 _cairo_quartz_font_face_destroy (void *abstract_face)
 {
     cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
 
     CGFontRelease (font_face->cgFont);
 }
@@ -160,17 +160,17 @@ static cairo_status_t
     font = malloc(sizeof(cairo_quartz_scaled_font_t));
     if (font == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     memset (font, 0, sizeof(cairo_quartz_scaled_font_t));
 
     status = _cairo_scaled_font_init (&font->base,
 				      &font_face->base, font_matrix, ctm, options,
-				      &cairo_quartz_scaled_font_backend);
+				      &_cairo_quartz_scaled_font_backend);
     if (status)
 	goto FINISH;
 
     ems = CGFontGetUnitsPerEmPtr (font_face->cgFont);
 
     /* initialize metrics */
     if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) {
 	fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems);
@@ -183,16 +183,17 @@ static cairo_status_t
 	fs_metrics.max_y_advance = 0.0;
     } else {
 	CGGlyph wGlyph;
 	UniChar u;
 
 	quartz_CGFontMetrics *m;
 	m = CGFontGetHMetricsPtr (font_face->cgFont);
 
+	/* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */
 	if (!m) {
 	    status = _cairo_error(CAIRO_STATUS_NULL_POINTER);
 	    goto FINISH;
 	}
 
 	fs_metrics.ascent = (m->ascent / ems);
 	fs_metrics.descent = - (m->descent / ems);
 	fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems);
@@ -255,19 +256,19 @@ cairo_quartz_font_face_create_for_cgfont
 
     font_face->cgFont = CGFontRetain (font);
 
     _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
 
     return &font_face->base;
 }
 
-/**
- ** scaled font backend
- **/
+/*
+ * scaled font backend
+ */
 
 static cairo_quartz_font_face_t *
 _cairo_quartz_scaled_to_face (void *abstract_font)
 {
     cairo_quartz_scaled_font_t *sfont = (cairo_quartz_scaled_font_t*) abstract_font;
     cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (&sfont->base);
     if (!font_face || font_face->backend->type != CAIRO_FONT_TYPE_QUARTZ)
 	return NULL;
@@ -735,17 +736,17 @@ static unsigned long
     UniChar u = (UniChar) ucs4;
     CGGlyph glyph;
 
     CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1);
 
     return glyph;
 }
 
-const cairo_scaled_font_backend_t cairo_quartz_scaled_font_backend = {
+const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
     CAIRO_FONT_TYPE_QUARTZ,
     _cairo_quartz_font_create_toy,
     _cairo_quartz_font_fini,
     _cairo_quartz_font_scaled_glyph_init,
     NULL, /* text_to_glyphs */
     _cairo_quartz_ucs4_to_index,
     NULL, /* show_glyphs */
     NULL, /* load_truetype_table */
--- a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c
@@ -38,16 +38,17 @@
 
 #ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
 #include "cairo-quartz-image.h"
 #endif
 
 #include "cairo-quartz-private.h"
 
 #define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
+#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
 #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
 
 CGImageRef
 _cairo_quartz_create_cgimage (cairo_format_t format,
 			      unsigned int width,
 			      unsigned int height,
 			      unsigned int stride,
 			      void *data,
@@ -295,17 +296,17 @@ cairo_quartz_image_surface_create (cairo
     CGImageRef image;
 
     cairo_image_surface_t *image_surface;
     int width, height, stride;
     cairo_format_t format;
     unsigned char *data;
 
     if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE)
-	return SURFACE_ERROR_NO_MEMORY;
+	return SURFACE_ERROR_TYPE_MISMATCH;
 
     image_surface = (cairo_image_surface_t*) surface;
     width = image_surface->width;
     height = image_surface->height;
     stride = image_surface->stride;
     format = image_surface->format;
     data = image_surface->data;
 
@@ -332,17 +333,17 @@ cairo_quartz_image_surface_create (cairo
 
     image = _cairo_quartz_create_cgimage (format,
 					  width, height,
 					  stride,
 					  data,
 					  TRUE,
 					  NULL,
 					  DataProviderReleaseCallback,
-					  surface);
+					  image_surface);
 
     if (!image) {
 	free (qisurf);
 	return SURFACE_ERROR_NO_MEMORY;
     }
 
     _cairo_surface_init (&qisurf->base,
 			 &cairo_quartz_image_surface_backend,
--- a/gfx/cairo/cairo/src/cairo-quartz-image.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-image.h
@@ -31,17 +31,17 @@
  *
  * Contributor(s):
  *      Vladimir Vukicevic <vladimir@mozilla.com>
  */
 
 #ifndef CAIRO_QUARTZ_IMAGE_H
 #define CAIRO_QUARTZ_IMAGE_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_QUARTZ_IMAGE_SURFACE
 
 #include <Carbon/Carbon.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
@@ -36,17 +36,17 @@
  */
 
 #ifndef CAIRO_QUARTZ_PRIVATE_H
 #define CAIRO_QUARTZ_PRIVATE_H
 
 #include "cairoint.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
-#include <cairo-quartz.h>
+#include "cairo-quartz.h"
 
 typedef struct cairo_quartz_surface {
     cairo_surface_t base;
 
     CGContextRef cgContext;
     CGAffineTransform cgContextBaseCTM;
 
     void *imageData;
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -690,16 +690,23 @@ CreateRepeatingGradientFunction (cairo_q
 			     input_value_range,
 			     4,
 			     output_value_ranges,
 			     &callbacks);
 }
 
 /* Obtain a CGImageRef from a #cairo_surface_t * */
 
+static void
+DataProviderReleaseCallback (void *info, const void *data, size_t size)
+{
+    cairo_surface_t *surface = (cairo_surface_t *) info;
+    cairo_surface_destroy (surface);
+}
+
 static cairo_status_t
 _cairo_surface_to_cgimage (cairo_surface_t *target,
 			   cairo_surface_t *source,
 			   CGImageRef *image_out)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_surface_type_t stype = cairo_surface_get_type (source);
     cairo_image_surface_t *isurf;
@@ -732,27 +739,32 @@ static cairo_status_t
 	    return status;
     } else {
 	isurf = (cairo_image_surface_t *) source;
     }
 
     if (isurf->width == 0 || isurf->height == 0) {
 	*image_out = NULL;
     } else {
-	image = _cairo_quartz_create_cgimage (isurf->format,
-					      isurf->width,
-					      isurf->height,
-					      isurf->stride,
-					      isurf->data,
+	cairo_image_surface_t *isurf_snap = NULL;
+	isurf_snap = _cairo_surface_snapshot (isurf);
+	if (isurf_snap == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+
+	image = _cairo_quartz_create_cgimage (isurf_snap->format,
+					      isurf_snap->width,
+					      isurf_snap->height,
+					      isurf_snap->stride,
+					      isurf_snap->data,
 					      TRUE,
-					      NULL, NULL, NULL);
-
-	/* Create a copy to ensure that the CGImageRef doesn't depend on the image surface's backing store */
-	*image_out = CGImageCreateCopy (image);
-	CGImageRelease (image);
+					      NULL,
+					      DataProviderReleaseCallback,
+					      isurf_snap);
+
+	*image_out = image;
     }
 
     if ((cairo_surface_t*) isurf != source)
 	_cairo_surface_release_source_image (source, isurf, image_extra);
 
     return status;
 }
 
@@ -1870,17 +1882,18 @@ static cairo_int_status_t
 
 #if CAIRO_HAS_QUARTZ_FONT
 static cairo_int_status_t
 _cairo_quartz_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_scaled_font_t *scaled_font,
+				   int *remaining_glyphs)
 {
     CGAffineTransform textTransform, ctm;
 #define STATIC_BUF_SIZE 64
     CGGlyph glyphs_static[STATIC_BUF_SIZE];
     CGSize cg_advances_static[STATIC_BUF_SIZE];
     CGGlyph *cg_glyphs = &glyphs_static[0];
     CGSize *cg_advances = &cg_advances_static[0];
 
@@ -2149,36 +2162,36 @@ static cairo_int_status_t
 					 cairo_pattern_t *mask)
 {
     int width = surface->extents.width - surface->extents.x;
     int height = surface->extents.height - surface->extents.y;
 
     cairo_surface_t *gradient_surf = NULL;
     cairo_t *gradient_surf_cr = NULL;
 
-    cairo_pattern_union_t surface_pattern;
+    cairo_surface_pattern_t surface_pattern;
     cairo_int_status_t status;
 
     /* Render the gradient to a surface */
     gradient_surf = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32,
 						 width,
 						 height);
     gradient_surf_cr = cairo_create(gradient_surf);
     cairo_set_source (gradient_surf_cr, mask);
     cairo_set_operator (gradient_surf_cr, CAIRO_OPERATOR_SOURCE);
     cairo_paint (gradient_surf_cr);
     status = cairo_status (gradient_surf_cr);
     cairo_destroy (gradient_surf_cr);
 
     if (status)
 	goto BAIL;
 
-    _cairo_pattern_init_for_surface (&surface_pattern.surface, gradient_surf);
-
-    status = _cairo_quartz_surface_mask_with_surface (surface, op, source, &surface_pattern.surface);
+    _cairo_pattern_init_for_surface (&surface_pattern, gradient_surf);
+
+    status = _cairo_quartz_surface_mask_with_surface (surface, op, source, &surface_pattern);
 
     _cairo_pattern_fini (&surface_pattern.base);
 
   BAIL:
     if (gradient_surf)
 	cairo_surface_destroy (gradient_surf);
 
     return status;
--- a/gfx/cairo/cairo/src/cairo-quartz.h
+++ b/gfx/cairo/cairo/src/cairo-quartz.h
@@ -31,17 +31,17 @@
  *
  * Contributor(s):
  *      Vladimir Vukicevic <vladimir@mozilla.com>
  */
 
 #ifndef CAIRO_QUARTZ_H
 #define CAIRO_QUARTZ_H
 
-#include <cairo.h>
+#include "cairo.h"
 
 #if CAIRO_HAS_QUARTZ_SURFACE
 
 #include <ApplicationServices/ApplicationServices.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-rectangle.c
+++ b/gfx/cairo/cairo/src/cairo-rectangle.c
@@ -34,32 +34,65 @@
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
 
+cairo_private void
+_cairo_box_from_doubles (cairo_box_t *box,
+			 double *x1, double *y1,
+			 double *x2, double *y2)
+{
+    box->p1.x = _cairo_fixed_from_double (*x1);
+    box->p1.y = _cairo_fixed_from_double (*y1);
+    box->p2.x = _cairo_fixed_from_double (*x2);
+    box->p2.y = _cairo_fixed_from_double (*y2);
+}
+
+cairo_private void
+_cairo_box_to_doubles (const cairo_box_t *box,
+		       double *x1, double *y1,
+		       double *x2, double *y2)
+{
+    *x1 = _cairo_fixed_to_double (box->p1.x);
+    *y1 = _cairo_fixed_to_double (box->p1.y);
+    *x2 = _cairo_fixed_to_double (box->p2.x);
+    *y2 = _cairo_fixed_to_double (box->p2.y);
+}
+
+void
+_cairo_box_from_rectangle (cairo_box_t                 *box,
+			   const cairo_rectangle_int_t *rect)
+{
+    box->p1.x = _cairo_fixed_from_int (rect->x);
+    box->p1.y = _cairo_fixed_from_int (rect->y);
+    box->p2.x = _cairo_fixed_from_int (rect->x + rect->width);
+    box->p2.y = _cairo_fixed_from_int (rect->y + rect->height);
+}
+
 /* XXX We currently have a confusing mix of boxes and rectangles as
  * exemplified by this function.  A #cairo_box_t is a rectangular area
  * represented by the coordinates of the upper left and lower right
  * corners, expressed in fixed point numbers.  A #cairo_rectangle_int_t is
  * also a rectangular area, but represented by the upper left corner
  * and the width and the height, as integer numbers.
  *
  * This function converts a #cairo_box_t to a #cairo_rectangle_int_t by
  * increasing the area to the nearest integer coordinates.  We should
  * standardize on #cairo_rectangle_fixed_t and #cairo_rectangle_int_t, and
  * this function could be renamed to the more reasonable
  * _cairo_rectangle_fixed_round.
  */
 
 void
-_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle)
+_cairo_box_round_to_rectangle (const cairo_box_t     *box,
+			       cairo_rectangle_int_t *rectangle)
 {
     rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
     rectangle->y = _cairo_fixed_integer_floor (box->p1.y);
     rectangle->width = _cairo_fixed_integer_ceil (box->p2.x) - rectangle->x;
     rectangle->height = _cairo_fixed_integer_ceil (box->p2.y) - rectangle->y;
 }
 
 void
--- a/gfx/cairo/cairo/src/cairo-region-private.h
+++ b/gfx/cairo/cairo/src/cairo-region-private.h
@@ -39,17 +39,17 @@
 
 #include <pixman.h>
 
 #include "cairo-compiler-private.h"
 
 /* #cairo_region_t is defined in cairoint.h */
 
 struct _cairo_region {
-    pixman_region16_t rgn;
+    pixman_region32_t rgn;
 };
 
 cairo_private void
 _cairo_region_init (cairo_region_t *region);
 
 cairo_private void
 _cairo_region_init_rect (cairo_region_t *region,
 			 cairo_rectangle_int_t *rect);
--- a/gfx/cairo/cairo/src/cairo-region.c
+++ b/gfx/cairo/cairo/src/cairo-region.c
@@ -35,90 +35,90 @@
  *      Vladimir Vukicevic <vladimir@pobox.com>
  */
 
 #include "cairoint.h"
 
 void
 _cairo_region_init (cairo_region_t *region)
 {
-    pixman_region_init (&region->rgn);
+    pixman_region32_init (&region->rgn);
 }
 
 void
 _cairo_region_init_rect (cairo_region_t *region,
 			 cairo_rectangle_int_t *rect)
 {
-    pixman_region_init_rect (&region->rgn,
+    pixman_region32_init_rect (&region->rgn,
 			     rect->x, rect->y,
 			     rect->width, rect->height);
 }
 
 cairo_int_status_t
 _cairo_region_init_boxes (cairo_region_t *region,
 			  cairo_box_int_t *boxes,
 			  int count)
 {
-    pixman_box16_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box16_t)];
-    pixman_box16_t *pboxes = stack_pboxes;
+    pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
+    pixman_box32_t *pboxes = stack_pboxes;
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     int i;
 
     if (count > ARRAY_LENGTH(stack_pboxes)) {
-	pboxes = _cairo_malloc_ab (count, sizeof(pixman_box16_t));
+	pboxes = _cairo_malloc_ab (count, sizeof(pixman_box32_t));
 	if (pboxes == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     for (i = 0; i < count; i++) {
 	pboxes[i].x1 = boxes[i].p1.x;
 	pboxes[i].y1 = boxes[i].p1.y;
 	pboxes[i].x2 = boxes[i].p2.x;
 	pboxes[i].y2 = boxes[i].p2.y;
     }
 
-    if (!pixman_region_init_rects (&region->rgn, pboxes, count))
+    if (!pixman_region32_init_rects (&region->rgn, pboxes, count))
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (pboxes != stack_pboxes)
 	free (pboxes);
 
     return status;
 }
 
 void
 _cairo_region_fini (cairo_region_t *region)
 {
-    pixman_region_fini (&region->rgn);
+    pixman_region32_fini (&region->rgn);
 }
 
 cairo_int_status_t
 _cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
 {
-    if (!pixman_region_copy (&dst->rgn, &src->rgn))
+    if (!pixman_region32_copy (&dst->rgn, &src->rgn))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 int
 _cairo_region_num_boxes (cairo_region_t *region)
 {
-    return pixman_region_n_rects (&region->rgn);
+    return pixman_region32_n_rects (&region->rgn);
 }
 
 cairo_int_status_t
 _cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes)
 {
     int nboxes;
-    pixman_box16_t *pboxes;
+    pixman_box32_t *pboxes;
     cairo_box_int_t *cboxes;
     int i;
 
-    pboxes = pixman_region_rectangles (&region->rgn, &nboxes);
+    pboxes = pixman_region32_rectangles (&region->rgn, &nboxes);
 
     if (nboxes == 0) {
 	*num_boxes = 0;
 	*boxes = NULL;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     cboxes = _cairo_malloc_ab (nboxes, sizeof(cairo_box_int_t));
@@ -149,72 +149,72 @@ void
  * @region: a #cairo_region_t
  * @rect: rectangle into which to store the extents
  *
  * Gets the bounding box of a region as a #cairo_rectangle_int_t
  **/
 void
 _cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
 {
-    pixman_box16_t *pextents = pixman_region_extents (&region->rgn);
+    pixman_box32_t *pextents = pixman_region32_extents (&region->rgn);
 
     extents->x = pextents->x1;
     extents->y = pextents->y1;
     extents->width = pextents->x2 - pextents->x1;
     extents->height = pextents->y2 - pextents->y1;
 }
 
 cairo_int_status_t
 _cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
 {
-    if (!pixman_region_subtract (&dst->rgn, &a->rgn, &b->rgn))
+    if (!pixman_region32_subtract (&dst->rgn, &a->rgn, &b->rgn))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_int_status_t
 _cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
 {
-    if (!pixman_region_intersect (&dst->rgn, &a->rgn, &b->rgn))
+    if (!pixman_region32_intersect (&dst->rgn, &a->rgn, &b->rgn))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_int_status_t
 _cairo_region_union_rect (cairo_region_t *dst,
 			  cairo_region_t *src,
 			  cairo_rectangle_int_t *rect)
 {
-    if (!pixman_region_union_rect (&dst->rgn, &src->rgn,
+    if (!pixman_region32_union_rect (&dst->rgn, &src->rgn,
 				   rect->x, rect->y,
 				   rect->width, rect->height))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_bool_t
 _cairo_region_not_empty (cairo_region_t *region)
 {
-    return (cairo_bool_t) pixman_region_not_empty (&region->rgn);
+    return (cairo_bool_t) pixman_region32_not_empty (&region->rgn);
 }
 
 void
 _cairo_region_translate (cairo_region_t *region,
 			 int x, int y)
 {
-    pixman_region_translate (&region->rgn, x, y);
+    pixman_region32_translate (&region->rgn, x, y);
 }
 
 pixman_region_overlap_t
 _cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *rect)
 {
-    pixman_box16_t pbox;
+    pixman_box32_t pbox;
 
     pbox.x1 = rect->x;
     pbox.y1 = rect->y;
     pbox.x2 = rect->x + rect->width;
     pbox.y2 = rect->y + rect->height;
 
-    return pixman_region_contains_rectangle (&region->rgn, &pbox);
+    return pix