Bug 484076 - Update pixman and cairo. This upgrades Cairo to git revision c932a809d6484503d7ee267d934bbc87c8d44092. r=vlad
authorJoe Drew <joe@drew.ca>
Fri, 20 Mar 2009 16:02:45 -0400
changeset 26419 1effb72d30cf6b7701485e450b87bddcb7e9891d
parent 26418 82b723917b6b525479685150073fdc9a2f8c1b24
child 26420 3407ca1084a6fd02419d28227eb6138ce935e2ce
push id6059
push userjdrew@mozilla.com
push dateFri, 20 Mar 2009 20:03:16 +0000
treeherdermozilla-central@1effb72d30cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvlad
bugs484076
milestone1.9.2a1pre
Bug 484076 - Update pixman and cairo. This upgrades Cairo to git revision c932a809d6484503d7ee267d934bbc87c8d44092. r=vlad
configure.in
content/canvas/test/test_2d.path.isPointInPath.edge.html
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface.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-surface.cpp
gfx/cairo/cairo/src/cairo-cache-private.h
gfx/cairo/cairo/src/cairo-cache.c
gfx/cairo/cairo/src/cairo-cff-subset.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-combsort-private.h
gfx/cairo/cairo/src/cairo-compiler-private.h
gfx/cairo/cairo/src/cairo-debug.c
gfx/cairo/cairo/src/cairo-deflate-stream.c
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-font-face-twin-data.c
gfx/cairo/cairo/src/cairo-font-face-twin.c
gfx/cairo/cairo/src/cairo-font-face.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-gstate.c
gfx/cairo/cairo/src/cairo-hash-private.h
gfx/cairo/cairo/src/cairo-hash.c
gfx/cairo/cairo/src/cairo-hull.c
gfx/cairo/cairo/src/cairo-image-info-private.h
gfx/cairo/cairo/src/cairo-image-info.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-list-private.h
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-output-stream-private.h
gfx/cairo/cairo/src/cairo-output-stream.c
gfx/cairo/cairo/src/cairo-paginated-surface.c
gfx/cairo/cairo/src/cairo-path-bounds.c
gfx/cairo/cairo/src/cairo-path-fill.c
gfx/cairo/cairo/src/cairo-path-fixed-private.h
gfx/cairo/cairo/src/cairo-path-fixed.c
gfx/cairo/cairo/src/cairo-path-in-fill.c
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-path.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-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-quartz-font.c
gfx/cairo/cairo/src/cairo-quartz-image-surface.c
gfx/cairo/cairo/src/cairo-quartz-surface.c
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-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-skiplist-private.h
gfx/cairo/cairo/src/cairo-skiplist.c
gfx/cairo/cairo/src/cairo-spans-private.h
gfx/cairo/cairo/src/cairo-spans.c
gfx/cairo/cairo/src/cairo-spline.c
gfx/cairo/cairo/src/cairo-stroke-style.c
gfx/cairo/cairo/src/cairo-surface-fallback-private.h
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface-private.h
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-tor-scan-converter.c
gfx/cairo/cairo/src/cairo-toy-font-face.c
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-user-font.c
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xlib-display.c
gfx/cairo/cairo/src/cairo-xlib-private.h
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface-private.h
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.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/test-fallback-surface.c
gfx/cairo/cairo/src/test-meta-surface.c
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/ft-done-face.patch
gfx/cairo/glyph-safety-margin.patch
gfx/cairo/on-edge.patch
gfx/cairo/tmpfile_wince.patch
gfx/cairo/wince-fontconfig.patch
gfx/cairo/wrap-source_image.patch
gfx/cairo/zero-sized.patch
--- a/configure.in
+++ b/configure.in
@@ -5867,17 +5867,16 @@ MOZ_ARG_ENABLE_BOOL(tree-freetype,
 [  --enable-tree-freetype         Enable Tree FreeType],
     MOZ_TREE_FREETYPE=1,
     MOZ_TREE_FREETYPE= )
 if test -n "$MOZ_TREE_FREETYPE"; then
    AC_DEFINE(MOZ_TREE_FREETYPE)
    AC_SUBST(MOZ_TREE_FREETYPE)
    MOZ_ENABLE_CAIRO_FT=1       
    FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
-   FC_FONT_FEATURE="#define CAIRO_DISABLE_FONTCONFIG 1"
    FT2_CFLAGS="-I${topsrcdir}/modules/freetype2/include"
    CAIRO_FT_CFLAGS="-I${topsrcdir}/modules/freetype2/include"
    FT2_LIBS="${LIBXUL_DIST}/lib/freetype2.lib"
    CAIRO_FT_LIBS = "${LIBXUL_DIST}/lib/freetype2.lib"
    AC_DEFINE(HAVE_FT_BITMAP_SIZE_Y_PPEM)
    AC_DEFINE(HAVE_FT_GLYPHSLOT_EMBOLDEN)
    AC_DEFINE(HAVE_FT_LOAD_SFNT_TABLE)
    AC_SUBST(CAIRO_FT_CFLAGS)
@@ -7538,16 +7537,17 @@ if test "$MOZ_TREE_CAIRO"; then
 
     # Define macros for cairo-features.h
     if test "$MOZ_X11"; then
         XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
         XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
         PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+        FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="$FT2_CFLAGS"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "qt"; then
         QPAINTER_SURFACE_FEATURE="#define CAIRO_HAS_QPAINTER_SURFACE 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
         QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
@@ -7561,25 +7561,27 @@ if test "$MOZ_TREE_CAIRO"; then
         else
            WIN32_FONT_FEATURE=
         fi  
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
         OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+        FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="-I${MZFTCFGFT2}/include"
         CAIRO_FT_LIBS="-L${MZFTCFGFT2}/lib -lmozft -lmzfntcfg"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "beos"; then
         PKG_CHECK_MODULES(CAIRO_FT, fontconfig freetype2)
         BEOS_SURFACE_FEATURE="#define CAIRO_HAS_BEOS_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+        FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
     fi
     AC_SUBST(MOZ_ENABLE_CAIRO_FT)
     AC_SUBST(CAIRO_FT_CFLAGS)
 
     if test "$MOZ_DEBUG"; then
       SANITY_CHECKING_FEATURE="#define CAIRO_DO_SANITY_CHECKING 1"
     else
--- a/content/canvas/test/test_2d.path.isPointInPath.edge.html
+++ b/content/canvas/test/test_2d.path.isPointInPath.edge.html
@@ -10,17 +10,17 @@
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
 
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 ctx.rect(0, 0, 20, 20);
-todo(ctx.isPointInPath(0, 0) === true, "ctx.isPointInPath(0, 0) === true");
+ok(ctx.isPointInPath(0, 0) === true, "ctx.isPointInPath(0, 0) === true");
 ok(ctx.isPointInPath(10, 0) === true, "ctx.isPointInPath(10, 0) === true");
 ok(ctx.isPointInPath(20, 0) === true, "ctx.isPointInPath(20, 0) === true");
 ok(ctx.isPointInPath(20, 10) === true, "ctx.isPointInPath(20, 10) === true");
 ok(ctx.isPointInPath(20, 20) === true, "ctx.isPointInPath(20, 20) === true");
 ok(ctx.isPointInPath(10, 20) === true, "ctx.isPointInPath(10, 20) === true");
 ok(ctx.isPointInPath(0, 20) === true, "ctx.isPointInPath(0, 20) === true");
 ok(ctx.isPointInPath(0, 10) === true, "ctx.isPointInPath(0, 10) === true");
 ok(ctx.isPointInPath(10, -0.01) === false, "ctx.isPointInPath(10, -0.01) === false");
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -21,39 +21,37 @@ Some specific things:
 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.
 
-tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
-
 cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds
 
 win32-ddb-dib.patch: fix for bug 455513; not upstream yet pending feebdack
 
 qpainter-type.patch: add SURFACE_TYPE_QPAINTER to cairo.h
 
 wince-fixes.patch: stubs out win32 functions we use but are not supported on win32.  Also implements ExtSelectClipRgn in terms of other functions available on wince.
 
-ft-done-face.patch: bug 467874; only destroy FT_Faces created by cairo
-
-wince-fontconfig.patch: bug 462908; fixes required to compile for windows ce.  Also allows for building without fontconfig
-
-glyph-safety-margin.patch: Change the glyph dropping safety margin from 2em to 10em for bug 460023.  Upstream commit: 28a72648ba7abe02ebd4df7234424e333b85dc9c.
-
 win32-vertically-offset-glyph.patch: bug 454098; vertical positioning errors when drawing glyph runs including delta-y offsets on screen via GDI
 
 ignore-rank0.patch: bug 474886; Not redrawing the background when changing page on flickr
 
 win32-canvas-glyph-position.patch: bug 475092; horizontal positioning errors when drawing glyph runs with delta-y offsets to canvas through win32-font
 
 win32-cleartype-clipping.patch: bug 445087; some glyphs are clipped, mainly on right-hand edge, when ClearType is enabled and drawing to RGBA canvas
 
+on-edge.patch: reverts the in-fill semantic change.
+
+wrap-source_image.patch: make sure we don't free the source image until we're done with it.
+
+zero-sized.patch: deal with zero sized surface in ways less likely to crash.
+
 ==== pixman patches ====
 
 endian.patch: include cairo-platform.h for endian macros
 
 ==== disable printing patch ====
 
 disable-printing.patch:  allows us to use NS_PRINTING to disable printing.
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -87,42 +87,47 @@ CSRCS   = \
 	cairo-font-face.c \
 	cairo-font-face-twin.c \
 	cairo-font-face-twin-data.c \
         cairo-font-options.c \
         cairo-freelist.c \
         cairo-gstate.c \
         cairo-hash.c \
         cairo-hull.c \
+	cairo-image-info.c \
         cairo-image-surface.c \
         cairo-lzw.c \
         cairo-matrix.c \
         cairo-meta-surface.c \
 	cairo-misc.c \
 	cairo-mutex.c \
         cairo-output-stream.c \
         cairo-paginated-surface.c \
         cairo-path.c \
         cairo-path-bounds.c \
         cairo-path-fill.c \
         cairo-path-fixed.c \
+        cairo-path-in-fill.c \
         cairo-path-stroke.c \
         cairo-pattern.c \
         cairo-pen.c \
         cairo-polygon.c \
         cairo-rectangle.c \
         cairo-region.c \
         cairo-scaled-font.c \
         cairo-scaled-font-subsets.c \
         cairo-skiplist.c \
         cairo-slope.c \
+        cairo-spans.c \
         cairo-spline.c \
         cairo-stroke-style.c \
         cairo-surface.c \
         cairo-surface-fallback.c \
+        cairo-tor-scan-converter.c \
+        cairo-toy-font-face.c \
         cairo-traps.c \
         cairo-unicode.c \
 	cairo-user-font.c \
 	cairo-version.c \
         cairo-wideint.c \
         $(NULL)
 
 EXPORTS = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -91,37 +91,37 @@ cairo_int_status_t
     assert (status_a == CAIRO_STATUS_SUCCESS &&
 	    status_b == CAIRO_STATUS_SUCCESS);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
-			       cairo_pattern_t		*pattern)
+			       const cairo_pattern_t *pattern)
 {
     cairo_surface_t *analysis = &surface->base;
-    cairo_surface_pattern_t *surface_pattern;
+    const cairo_surface_pattern_t *surface_pattern;
     cairo_status_t status;
     cairo_bool_t old_has_ctm;
     cairo_matrix_t old_ctm, p2d;
     cairo_rectangle_int_t old_clip;
     cairo_rectangle_int_t meta_extents;
     int old_width;
     int old_height;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
-    surface_pattern = (cairo_surface_pattern_t *) pattern;
+    surface_pattern = (const 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 && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	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;
@@ -278,111 +278,110 @@ static cairo_status_t
 static cairo_int_status_t
 _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 					     cairo_path_fixed_t *path,
 					     cairo_fill_rule_t   fill_rule,
 					     double		 tolerance,
 					     cairo_antialias_t   antialias)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    double                    x1, y1, x2, y2;
-    cairo_rectangle_int_t   extent;
 
     if (path == NULL) {
 	surface->current_clip.x = 0;
 	surface->current_clip.y = 0;
 	surface->current_clip.width  = surface->width;
 	surface->current_clip.height = surface->height;
     } else {
-	cairo_status_t status;
-
-	status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance);
-	if (status)
-	    return status;
+	cairo_rectangle_int_t extents;
+	cairo_bool_t is_empty;
 
-	extent.x = floor (x1);
-	extent.y = floor (y1);
-	extent.width  = ceil (x2) - extent.x;
-	extent.height = ceil (y2) - extent.y;
-
-	_cairo_rectangle_intersect (&surface->current_clip, &extent);
+	_cairo_path_fixed_approximate_clip_extents (path, &extents);
+	is_empty = _cairo_rectangle_intersect (&surface->current_clip,
+					       &extents);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_get_extents (void			*abstract_surface,
 				     cairo_rectangle_int_t	*rectangle)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
 
     return _cairo_surface_get_extents (surface->target, rectangle);
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_paint (void			*abstract_surface,
-			      cairo_operator_t		op,
-			      cairo_pattern_t		*source)
+			       cairo_operator_t		op,
+			       const cairo_pattern_t	*source,
+			       cairo_rectangle_int_t    *paint_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t  extents;
+    cairo_bool_t is_empty;
 
     if (!surface->target->backend->paint)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->paint) (surface->target, op,
-                                                             source);
+                                                             source, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (paint_extents)
+	*paint_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
-			      cairo_pattern_t	*source,
-			      cairo_pattern_t	*mask)
+			      const cairo_pattern_t	*source,
+			      const cairo_pattern_t	*mask,
+			      cairo_rectangle_int_t 	*mask_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_int_status_t	      status, backend_status;
     cairo_rectangle_int_t   extents;
+    cairo_bool_t is_empty;
 
     if (!surface->target->backend->mask)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->mask) (surface->target, op,
-                                                            source, mask);
+                                                            source, mask, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
 	cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
 	cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
 
 	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+	    const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source;
 	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
 		backend_source_status =
 		    _analyze_meta_surface_pattern (surface, source);
 		if (_cairo_status_is_error (backend_source_status))
 		    return backend_source_status;
 	    }
 	}
 
@@ -397,236 +396,230 @@ static cairo_int_status_t
 	}
 
 	backend_status =
 	    _cairo_analysis_surface_merge_status (backend_source_status,
 						  backend_mask_status);
     }
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+    }
 
-	status = _cairo_pattern_get_extents (mask, &source_extents);
-	if (status)
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t mask_extents;
+
+	status = _cairo_pattern_get_extents (mask, &mask_extents);
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (mask_extents)
+	*mask_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_stroke (void			*abstract_surface,
 				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
+				const cairo_pattern_t	*source,
 				cairo_path_fixed_t	*path,
 				cairo_stroke_style_t	*style,
 				cairo_matrix_t		*ctm,
 				cairo_matrix_t		*ctm_inverse,
 				double			 tolerance,
-				cairo_antialias_t	 antialias)
+				cairo_antialias_t	 antialias,
+				cairo_rectangle_int_t   *stroke_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
-    cairo_traps_t            traps;
-    cairo_rectangle_int_t  extents;
+    cairo_rectangle_int_t    extents;
+    cairo_bool_t             is_empty;
 
     if (!surface->target->backend->stroke)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->stroke) (surface->target, op,
 							      source, path, style,
 							      ctm, ctm_inverse,
-							      tolerance, antialias);
+							      tolerance, antialias, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t box;
-
-	_cairo_box_from_rectangle (&box, &extents);
+	cairo_rectangle_int_t mask_extents;
 
-	_cairo_traps_init (&traps);
-	_cairo_traps_limit (&traps, &box);
-	status = _cairo_path_fixed_stroke_to_traps (path,
-						    style,
-						    ctm, ctm_inverse,
-						    tolerance,
-						    &traps);
-	if (status) {
-	    _cairo_traps_fini (&traps);
-	    return status;
-	}
+	_cairo_path_fixed_approximate_stroke_extents (path,
+						      style, ctm,
+						      &mask_extents);
 
-	_cairo_traps_extents (&traps, &box);
-	_cairo_traps_fini (&traps);
-
-        _cairo_box_round_to_rectangle (&box, &extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
+    if (stroke_extents)
+	*stroke_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_fill (void			*abstract_surface,
 			      cairo_operator_t		 op,
-			      cairo_pattern_t		*source,
+			      const cairo_pattern_t	*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
-			      cairo_antialias_t		 antialias)
+			      cairo_antialias_t		 antialias,
+			      cairo_rectangle_int_t     *fill_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
-    cairo_traps_t            traps;
-    cairo_rectangle_int_t  extents;
+    cairo_rectangle_int_t    extents;
+    cairo_bool_t             is_empty;
 
     if (!surface->target->backend->fill)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->fill) (surface->target, op,
 						    source, path, fill_rule,
-						    tolerance, antialias);
+							    tolerance, antialias, NULL);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t box;
+	cairo_rectangle_int_t mask_extents;
 
-	_cairo_box_from_rectangle (&box, &extents);
+	_cairo_path_fixed_approximate_fill_extents (path,
+						    &mask_extents);
 
-	_cairo_traps_init (&traps);
-	_cairo_traps_limit (&traps, &box);
-	status = _cairo_path_fixed_fill_to_traps (path,
-						  fill_rule,
-						  tolerance,
-						  &traps);
-	if (status) {
-	    _cairo_traps_fini (&traps);
-	    return status;
-	}
-
-	_cairo_traps_extents (&traps, &box);
-	_cairo_traps_fini (&traps);
-
-        _cairo_box_round_to_rectangle (&box, &extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
+    if (fill_extents)
+	*fill_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_operator_t	   op,
-				     cairo_pattern_t	  *source,
+				     const cairo_pattern_t *source,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
 				     cairo_scaled_font_t  *scaled_font,
-				     int                  *remaining_glyphs)
+				     int                  *remaining_glyphs,
+				     cairo_rectangle_int_t *show_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
+    cairo_bool_t             is_empty;
 
     /* 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,
-								   remaining_glyphs);
+								   remaining_glyphs, NULL);
     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);
+								     scaled_font, NULL);
     else
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _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)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &glyph_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_glyphs_extents)
+	*show_glyphs_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_bool_t
 _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
@@ -634,80 +627,85 @@ static cairo_bool_t
     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 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_text_cluster_flags_t cluster_flags,
-					  cairo_scaled_font_t	    *scaled_font)
+					  cairo_scaled_font_t	    *scaled_font,
+					  cairo_rectangle_int_t     *show_text_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
+    cairo_bool_t             is_empty;
 
     /* 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, cluster_flags,
-								     scaled_font);
+								     scaled_font, NULL);
     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);
+								&remaining_glyphs, NULL);
 	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 = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+    if (_cairo_status_is_error (status))
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
+
 	status = _cairo_pattern_get_extents (source, &source_extents);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &source_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    is_empty = _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)
+	if (unlikely (status))
 	    return status;
 
-	_cairo_rectangle_intersect (&extents, &glyph_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_text_glyphs_extents)
+	*show_text_glyphs_extents = extents;
 
     status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static const cairo_surface_backend_t cairo_analysis_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
@@ -716,16 +714,18 @@ static const cairo_surface_backend_t cai
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* acquire_dest_image */
     NULL, /* release_dest_image */
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
+    NULL, /* create_span_renderer */
+    NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
     NULL, /* set_clip_region */
     _cairo_analysis_surface_intersect_clip_path,
     _cairo_analysis_surface_get_extents,
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
     NULL, /* flush */
@@ -737,34 +737,35 @@ static const cairo_surface_backend_t cai
     _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 */
+    NULL, /* can_repaint_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;
     cairo_status_t status;
 
     status = target->status;
-    if (status)
+    if (unlikely (status))
 	return _cairo_surface_create_in_error (status);
 
     surface = malloc (sizeof (cairo_analysis_surface_t));
-    if (surface == NULL)
+    if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     /* I believe the content type here is truly arbitrary. I'm quite
      * sure nothing will ever use this value. */
     _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     surface->width = width;
@@ -876,66 +877,73 @@ static cairo_int_status_t
 
 /* 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);
+				 const cairo_pattern_t	*source,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_mask_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
-				 cairo_pattern_t	*mask);
+				 const cairo_pattern_t	*source,
+				 const cairo_pattern_t	*mask,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_stroke_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_stroke_style_t	*style,
 				 cairo_matrix_t		*ctm,
 				 cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_fill_func)			(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
-				 cairo_antialias_t	 antialias);
+				 cairo_antialias_t	 antialias,
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_show_glyphs_func)		(void			*surface,
 			         cairo_operator_t	 op,
-				 cairo_pattern_t	*source,
+				 const cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
-				 int			*remaining_glyphs);
+				 int			*remaining_glyphs,
+				 cairo_rectangle_int_t  *extents);
 
 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, /* create_span_renderer */
+    NULL, /* check_span_renderer */
     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 */
@@ -947,26 +955,27 @@ static const cairo_surface_backend_t cai
     (_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, /* can_repaint_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) {
+    if (unlikely (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-array.c
+++ b/gfx/cairo/cairo/src/cairo-array.c
@@ -133,27 +133,27 @@ cairo_status_t
     else
 	new_size = old_size * 2;
 
     while (new_size < required_size)
 	new_size = new_size * 2;
 
     if (array->elements == NULL) {
 	array->elements = malloc (sizeof (char *));
-	if (array->elements == NULL)
+	if (unlikely (array->elements == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	*array->elements = NULL;
     }
 
     array->size = new_size;
     new_elements = _cairo_realloc_ab (*array->elements,
 			              array->size, array->element_size);
 
-    if (new_elements == NULL) {
+    if (unlikely (new_elements == NULL)) {
 	array->size = old_size;
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     *array->elements = new_elements;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -274,17 +274,17 @@ cairo_status_t
 			      int		 num_elements)
 {
     cairo_status_t status;
     void *dest;
 
     assert (! array->is_snapshot);
 
     status = _cairo_array_allocate (array, num_elements, &dest);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     memcpy (dest, elements, num_elements * array->element_size);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
@@ -305,17 +305,17 @@ cairo_status_t
 		       unsigned int	  num_elements,
 		       void		**elements)
 {
     cairo_status_t status;
 
     assert (! array->is_snapshot);
 
     status = _cairo_array_grow_by (array, num_elements);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     assert (array->num_elements + num_elements <= array->size);
 
     *elements = &(*array->elements)[array->num_elements * array->element_size];
 
     array->num_elements += num_elements;
 
@@ -377,24 +377,28 @@ void
  * @array: a #cairo_user_data_array_t
  *
  * Destroys all current keys in the user data array and deallocates
  * any memory allocated for the array itself.
  **/
 void
 _cairo_user_data_array_fini (cairo_user_data_array_t *array)
 {
-    int i, num_slots;
-    cairo_user_data_slot_t *slots;
+    unsigned int num_slots;
 
     num_slots = array->num_elements;
-    slots = _cairo_array_index (array, 0);
-    for (i = 0; i < num_slots; i++) {
-	if (slots[i].user_data != NULL && slots[i].destroy != NULL)
-	    slots[i].destroy (slots[i].user_data);
+    if (num_slots) {
+	cairo_user_data_slot_t *slots;
+
+	slots = _cairo_array_index (array, 0);
+	do {
+	    if (slots->user_data != NULL && slots->destroy != NULL)
+		slots->destroy (slots->user_data);
+	    slots++;
+	} while (--num_slots);
     }
 
     _cairo_array_fini (array);
 }
 
 /**
  * _cairo_user_data_array_get_data:
  * @array: a #cairo_user_data_array_t
@@ -480,13 +484,49 @@ cairo_status_t
     }
 
     if (slot) {
 	*slot = new_slot;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     status = _cairo_array_append (array, &new_slot);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t	*dst,
+			     cairo_user_data_array_t	*src)
+{
+    /* discard any existing user-data */
+    if (dst->num_elements != 0) {
+	_cairo_user_data_array_fini (dst);
+	_cairo_user_data_array_init (dst);
+    }
+
+    if (src->num_elements == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_array_append_multiple (dst,
+					 _cairo_array_index (src, 0),
+					 src->num_elements);
+}
+
+void
+_cairo_user_data_array_foreach (cairo_user_data_array_t     *array,
+				void (*func) (const void *key,
+					      void *elt,
+					      void *closure),
+				void *closure)
+{
+    cairo_user_data_slot_t *slots;
+    int i, num_slots;
+
+    num_slots = array->num_elements;
+    slots = _cairo_array_index (array, 0);
+    for (i = 0; i < num_slots; i++) {
+	if (slots[i].user_data != NULL)
+	    func (slots[i].key, slots[i].user_data, closure);
+    }
+}
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -112,21 +112,22 @@ cairo_output_stream_t *
 _cairo_base85_stream_create (cairo_output_stream_t *output)
 {
     cairo_base85_stream_t *stream;
 
     if (output->status)
 	return _cairo_output_stream_create_in_error (output->status);
 
     stream = malloc (sizeof (cairo_base85_stream_t));
-    if (stream == NULL) {
+    if (unlikely (stream == NULL)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
     }
 
     _cairo_output_stream_init (&stream->base,
 			       _cairo_base85_stream_write,
+			       NULL,
 			       _cairo_base85_stream_close);
     stream->output = output;
     stream->pending = 0;
 
     return &stream->base;
 }
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -33,16 +33,17 @@
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 /* Provide definitions for standalone compilation */
 #include "cairoint.h"
 
 #include "cairo-skiplist-private.h"
 #include "cairo-freelist-private.h"
+#include "cairo-combsort-private.h"
 
 #define DEBUG_VALIDATE 0
 #define DEBUG_PRINT_STATE 0
 
 typedef cairo_point_t cairo_bo_point32_t;
 
 typedef struct _cairo_bo_point128 {
     cairo_int128_t x;
@@ -81,17 +82,17 @@ struct _cairo_bo_traps {
     cairo_fixed_t xmax;
     cairo_fixed_t ymax;
 };
 
 struct _cairo_bo_edge {
     cairo_bo_point32_t top;
     cairo_bo_point32_t middle;
     cairo_bo_point32_t bottom;
-    cairo_bool_t reversed;
+    int dir;
     cairo_bo_edge_t *prev;
     cairo_bo_edge_t *next;
     cairo_bo_trap_t *deferred_trap;
     sweep_line_elt_t *sweep_line_elt;
 };
 
 struct _sweep_line_elt {
     cairo_bo_edge_t *edge;
@@ -123,18 +124,16 @@ typedef struct _cairo_bo_event {
 
 #define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
 
 typedef struct _cairo_bo_event_queue {
     cairo_skip_list_t intersection_queue;
 
     cairo_bo_event_t *startstop_events;
     cairo_bo_event_t **sorted_startstop_event_ptrs;
-    unsigned next_startstop_event_index;
-    unsigned num_startstop_events;
 } cairo_bo_event_queue_t;
 
 /* This structure extends #cairo_skip_list_t, which must come first. */
 typedef struct _cairo_bo_sweep_line {
     cairo_skip_list_t active_edges;
     cairo_bo_edge_t *head;
     cairo_bo_edge_t *tail;
     int32_t current_y;
@@ -192,21 +191,31 @@ static int
      * bits. That's not true in general as there could be overflow. We
      * should prevent that before the tessellation algorithm
      * begins.
      */
     int32_t adx = a->bottom.x - a->top.x;
     int32_t bdx = b->bottom.x - b->top.x;
 
     /* Since the dy's are all positive by construction we can fast
-     * path the case where the two edges point in different directions
-     * with respect to x. */
-    if ((adx ^ bdx) < 0) {
-	return adx < 0 ? -1 : +1;
-    } else {
+     * path several common cases.
+     */
+
+    /* First check for vertical lines. */
+    if (adx == 0)
+	return -bdx;
+    if (bdx == 0)
+	return adx;
+
+    /* Then where the two edges point in different directions wrt x. */
+    if ((adx ^ bdx) < 0)
+	return adx;
+
+    /* Finally we actually need to do the general comparison. */
+    {
 	int32_t ady = a->bottom.y - a->top.y;
 	int32_t bdy = b->bottom.y - b->top.y;
 	cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
 	cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
 
 	return _cairo_int64_cmp (adx_bdy, bdx_ady);
     }
 }
@@ -214,84 +223,149 @@ static int
 /*
  * We need to compare the x-coordinates of a pair of lines for a particular y,
  * without loss of precision.
  *
  * The x-coordinate along an edge for a given y is:
  *   X = A_x + (Y - A_y) * A_dx / A_dy
  *
  * So the inequality we wish to test is:
- *   A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
- * where -?- is our inequality operator.
+ *   A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
+ * where ∘ is our inequality operator.
  *
  * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
  * all positive, so we can rearrange it thus without causing a sign change:
- *   A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
+ *   A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
  *                                 - (Y - A_y) * A_dx * B_dy
  *
  * Given the assumption that all the deltas fit within 32 bits, we can compute
- * this comparison directly using 128 bit arithmetic.
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
  *
  * (And put the burden of the work on developing fast 128 bit ops, which are
  * required throughout the tessellator.)
  *
  * See the similar discussion for _slope_compare().
  */
 static int
 edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
 			       const cairo_bo_edge_t *b,
 			       int32_t y)
 {
     /* XXX: We're assuming here that dx and dy will still fit in 32
      * bits. That's not true in general as there could be overflow. We
      * should prevent that before the tessellation algorithm
      * begins.
      */
+    int32_t dx;
     int32_t adx, ady;
     int32_t bdx, bdy;
-    cairo_int128_t L, R;
-
-    adx = a->bottom.x - a->top.x;
-    ady = a->bottom.y - a->top.y;
+    enum {
+       HAVE_NONE    = 0x0,
+       HAVE_DX      = 0x1,
+       HAVE_ADX     = 0x2,
+       HAVE_DX_ADX  = HAVE_DX | HAVE_ADX,
+       HAVE_BDX     = 0x4,
+       HAVE_DX_BDX  = HAVE_DX | HAVE_BDX,
+       HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+       HAVE_ALL     = HAVE_DX | HAVE_ADX | HAVE_BDX
+    } have_dx_adx_bdx = HAVE_ALL;
 
-    bdx = b->bottom.x - b->top.x;
-    bdy = b->bottom.y - b->top.y;
+    ady = a->bottom.y - a->top.y;
+    adx = a->bottom.x - a->top.x;
+    if (adx == 0)
+	have_dx_adx_bdx &= ~HAVE_ADX;
 
-    L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
-				 a->top.x - b->top.x);
+    bdy = b->bottom.y - b->top.y;
+    bdx = b->bottom.x - b->top.x;
+    if (bdx == 0)
+	have_dx_adx_bdx &= ~HAVE_BDX;
+
+    dx = a->top.x - b->top.x;
+    if (dx == 0)
+	have_dx_adx_bdx &= ~HAVE_DX;
 
-    R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
-									    ady),
-						    y - b->top.y),
-			   _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
-									    bdy),
-						    y - a->top.y));
+#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->top.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->top.y)
+    switch (have_dx_adx_bdx) {
+    default:
+    case HAVE_NONE:
+	return 0;
+    case HAVE_DX:
+	/* A_dy * B_dy * (A_x - B_x) ∘ 0 */
+	return dx; /* ady * bdy is positive definite */
+    case HAVE_ADX:
+	/* 0 ∘  - (Y - A_y) * A_dx * B_dy */
+	return adx; /* bdy * (y - a->top.y) is positive definite */
+    case HAVE_BDX:
+	/* 0 ∘ (Y - B_y) * B_dx * A_dy */
+	return -bdx; /* ady * (y - b->top.y) is positive definite */
+    case HAVE_ADX_BDX:
+	/*  0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+	if ((adx ^ bdx) < 0) {
+	    return adx;
+	} else if (a->top.y == b->top.y) { /* common origin */
+	    cairo_int64_t adx_bdy, bdx_ady;
+
+	    /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
+
+	    adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+	    bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
 
-    /* return _cairo_int128_cmp (L, R); */
-    if (_cairo_int128_lt (L, R))
-	return -1;
-    if (_cairo_int128_gt (L, R))
-	return 1;
-    return 0;
+	    return _cairo_int64_cmp (adx_bdy, bdx_ady);
+	} else
+	    return _cairo_int128_cmp (A, B);
+    case HAVE_DX_ADX:
+	/* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
+	if ((-adx ^ dx) < 0) {
+	    return dx;
+	} else {
+	    cairo_int64_t ady_dx, dy_adx;
+
+	    ady_dx = _cairo_int32x32_64_mul (ady, dx);
+	    dy_adx = _cairo_int32x32_64_mul (a->top.y - y, adx);
+
+	    return _cairo_int64_cmp (ady_dx, dy_adx);
+	}
+    case HAVE_DX_BDX:
+	/* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
+	if ((bdx ^ dx) < 0) {
+	    return dx;
+	} else {
+	    cairo_int64_t bdy_dx, dy_bdx;
+
+	    bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
+	    dy_bdx = _cairo_int32x32_64_mul (y - b->top.y, bdx);
+
+	    return _cairo_int64_cmp (bdy_dx, dy_bdx);
+	}
+    case HAVE_ALL:
+	return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+    }
+#undef B
+#undef A
+#undef L
 }
 
 /*
  * We need to compare the x-coordinate of a line for a particular y wrt to a
  * given x, without loss of precision.
  *
  * The x-coordinate along an edge for a given y is:
  *   X = A_x + (Y - A_y) * A_dx / A_dy
  *
  * So the inequality we wish to test is:
- *   A_x + (Y - A_y) * A_dx / A_dy -?- X
- * where -?- is our inequality operator.
+ *   A_x + (Y - A_y) * A_dx / A_dy ∘ X
+ * where ∘ is our inequality operator.
  *
  * By construction, we know that A_dy (and (Y - A_y)) are
  * all positive, so we can rearrange it thus without causing a sign change:
- *   (Y - A_y) * A_dx -?- (X - A_x) * A_dy
+ *   (Y - A_y) * A_dx ∘ (X - A_x) * A_dy
  *
  * Given the assumption that all the deltas fit within 32 bits, we can compute
  * this comparison directly using 64 bit arithmetic.
  *
  * See the similar discussion for _slope_compare() and
  * edges_compare_x_for_y_general().
  */
 static int
@@ -299,20 +373,25 @@ edge_compare_for_y_against_x (const cair
 			      int32_t y,
 			      int32_t x)
 {
     int32_t adx, ady;
     int32_t dx, dy;
     cairo_int64_t L, R;
 
     adx = a->bottom.x - a->top.x;
-    ady = a->bottom.y - a->top.y;
+    dx = x - a->top.x;
+
+    if (adx == 0)
+	return -dx;
+    if ((adx ^ dx) < 0)
+	return adx;
 
     dy = y - a->top.y;
-    dx = x - a->top.x;
+    ady = a->bottom.y - a->top.y;
 
     L = _cairo_int32x32_64_mul (dy, adx);
     R = _cairo_int32x32_64_mul (dx, ady);
 
     return _cairo_int64_cmp (L, R);
 }
 
 static int
@@ -347,17 +426,17 @@ edges_compare_x_for_y (const cairo_bo_ed
     else
 	have_ax_bx &= ~HAVE_BX;
 
     switch (have_ax_bx) {
     default:
     case HAVE_NEITHER:
 	return edges_compare_x_for_y_general (a, b, y);
     case HAVE_AX:
-	return - edge_compare_for_y_against_x (b, y, ax);
+	return -edge_compare_for_y_against_x (b, y, ax);
     case HAVE_BX:
 	return edge_compare_for_y_against_x (a, y, bx);
     case HAVE_BOTH:
 	return ax - bx;
     }
 }
 
 static int
@@ -545,31 +624,28 @@ cairo_bo_event_compare_abstract (void		*
 {
     cairo_bo_event_t *event_a = a;
     cairo_bo_event_t *event_b = b;
 
     return cairo_bo_event_compare (event_a, event_b);
 }
 
 static int
-cairo_bo_event_compare_pointers (void const *voida,
-				 void const *voidb)
+cairo_bo_event_compare_pointers (const cairo_bo_event_t *a,
+				 const cairo_bo_event_t *b)
 {
-    cairo_bo_event_t const * const *a = voida;
-    cairo_bo_event_t const * const *b = voidb;
-    if (*a != *b) {
-	int cmp = cairo_bo_event_compare (*a, *b);
-	if (cmp)
-	    return cmp;
-	if (*a < *b)
-	    return -1;
-	if (*a > *b)
-	    return +1;
-    }
-    return 0;
+    int cmp;
+
+    if (a == b)
+	return 0;
+    cmp = cairo_bo_event_compare (a, b);
+    if (cmp)
+	return cmp;
+
+    return a - b;
 }
 
 static inline cairo_int64_t
 det32_64 (int32_t a,
 	  int32_t b,
 	  int32_t c,
 	  int32_t d)
 {
@@ -619,22 +695,71 @@ intersect_lines (cairo_bo_edge_t		*a,
      * cairo_bo_tessellate_polygon().
      */
     int32_t dx1 = a->top.x - a->bottom.x;
     int32_t dy1 = a->top.y - a->bottom.y;
 
     int32_t dx2 = b->top.x - b->bottom.x;
     int32_t dy2 = b->top.y - b->bottom.y;
 
-    cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
+    cairo_int64_t den_det;
+    cairo_int64_t R;
     cairo_quorem64_t qr;
 
+    den_det = det32_64 (dx1, dy1, dx2, dy2);
     if (_cairo_int64_is_zero (den_det))
 	return CAIRO_BO_STATUS_PARALLEL;
 
+     /* Q: Can we determine that the lines do not intersect (within range)
+      * much more cheaply than computing the intersection point i.e. by
+      * avoiding the division?
+      *
+      *   X = ax + t * adx = bx + s * bdx;
+      *   Y = ay + t * ady = by + s * bdy;
+      *   ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
+      *   => t * L = R
+      *
+      * Therefore we can reject any intersection (under the criteria for
+      * valid intersection events) if:
+      *   L^R < 0 => t < 0, or
+      *   L<R => t > 1
+      *
+      * (where top/bottom must at least extend to the line endpoints).
+      *
+      * A similar substitution can be performed for s, yielding:
+      *   s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
+      */
+    R = det32_64 (dx2, dy2, b->top.x - a->top.x, b->top.y - a->top.y);
+    if (_cairo_int64_is_zero (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det)) {
+	if (_cairo_int64_ge (den_det, R))
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+    } else {
+	if (_cairo_int64_le (den_det, R))
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+    }
+
+    R = det32_64 (dy1, dx1, a->top.y - b->top.y, a->top.x - b->top.x);
+    if (_cairo_int64_is_zero (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det)) {
+	if (_cairo_int64_ge (den_det, R))
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+    } else {
+	if (_cairo_int64_le (den_det, R))
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+    }
+
+    /* We now know that the two lines should intersect within range. */
+
     a_det = det32_64 (a->top.x, a->top.y,
 		      a->bottom.x, a->bottom.y);
     b_det = det32_64 (b->top.x, b->top.y,
 		      b->bottom.x, b->bottom.y);
 
     /* x = det (a_det, dx1, b_det, dx2) / den_det */
     qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
 						       b_det, dx2),
@@ -810,81 +935,83 @@ static void
 
 static cairo_bo_event_t *
 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
 {
     skip_elt_t *elt = event_queue->intersection_queue.chains[0];
     cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
     cairo_bo_event_t *startstop;
 
-    if (event_queue->next_startstop_event_index == event_queue->num_startstop_events)
+    startstop = *event_queue->sorted_startstop_event_ptrs;
+    if (startstop == NULL)
 	return intersection;
-    startstop = event_queue->sorted_startstop_event_ptrs[
-	event_queue->next_startstop_event_index];
 
-    if (!intersection || cairo_bo_event_compare (startstop, intersection) <= 0)
+    if (intersection == NULL ||
+	cairo_bo_event_compare (startstop, intersection) <= 0)
     {
-	event_queue->next_startstop_event_index++;
+	event_queue->sorted_startstop_event_ptrs++;
 	return startstop;
     }
+
     return intersection;
 }
 
+CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
+			cairo_bo_event_t *,
+			cairo_bo_event_compare_pointers)
+
 static cairo_status_t
 _cairo_bo_event_queue_init (cairo_bo_event_queue_t	*event_queue,
 			    cairo_bo_edge_t	*edges,
 			    int				 num_edges)
 {
     int i;
     cairo_bo_event_t *events, **sorted_event_ptrs;
     unsigned num_events = 2*num_edges;
 
-    memset (event_queue, 0, sizeof(*event_queue));
-
-    _cairo_skip_list_init (&event_queue->intersection_queue,
-		    cairo_bo_event_compare_abstract,
-		    sizeof (cairo_bo_event_t));
-    if (0 == num_edges)
-	return CAIRO_STATUS_SUCCESS;
-
     /* The skip_elt_t field of a cairo_bo_event_t isn't used for start
      * or stop events, so this allocation is safe.  XXX: make the
      * event type a union so it doesn't always contain the skip
      * elt? */
-    events = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
-    if (events == NULL)
+    events = _cairo_malloc_ab_plus_c (num_events,
+				      sizeof (cairo_bo_event_t) +
+				      sizeof (cairo_bo_event_t *),
+				      sizeof (cairo_bo_event_t *));
+    if (unlikely (events == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
     event_queue->startstop_events = events;
     event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
-    event_queue->num_startstop_events = num_events;
-    event_queue->next_startstop_event_index = 0;
 
     for (i = 0; i < num_edges; i++) {
-	sorted_event_ptrs[2*i] = &events[2*i];
-	sorted_event_ptrs[2*i+1] = &events[2*i+1];
+	sorted_event_ptrs[i] = &events[2*i];
+	sorted_event_ptrs[i+num_edges] = &events[2*i+1];
 
 	/* Initialize "middle" to top */
 	edges[i].middle = edges[i].top;
 
 	_cairo_bo_event_init (&events[2*i],
 			      CAIRO_BO_EVENT_TYPE_START,
 			      &edges[i], NULL,
 			      edges[i].top);
 
 	_cairo_bo_event_init (&events[2*i+1],
 			      CAIRO_BO_EVENT_TYPE_STOP,
 			      &edges[i], NULL,
 			      edges[i].bottom);
     }
 
-    qsort (sorted_event_ptrs, num_events,
-	   sizeof(cairo_bo_event_t *),
-	   cairo_bo_event_compare_pointers);
+    _cairo_bo_event_queue_sort (sorted_event_ptrs, num_events);
+    event_queue->sorted_startstop_event_ptrs[num_events] = NULL;
+
+    _cairo_skip_list_init (&event_queue->intersection_queue,
+			   cairo_bo_event_compare_abstract,
+			   sizeof (cairo_bo_event_t));
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
 {
     _cairo_skip_list_fini (&event_queue->intersection_queue);
     if (event_queue->startstop_events)
@@ -925,18 +1052,19 @@ static cairo_status_t
 
     return _cairo_bo_event_queue_insert (event_queue, &event);
 }
 
 static void
 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
 {
     _cairo_skip_list_init (&sweep_line->active_edges,
-		    _sweep_line_elt_compare,
-		    sizeof (sweep_line_elt_t));
+			   _sweep_line_elt_compare,
+			   sizeof (sweep_line_elt_t));
+
     sweep_line->head = NULL;
     sweep_line->tail = NULL;
     sweep_line->current_y = 0;
 }
 
 static void
 _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
 {
@@ -947,18 +1075,18 @@ static cairo_status_t
 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t		*edge)
 {
     skip_elt_t *next_elt;
     sweep_line_elt_t *sweep_line_elt;
     cairo_bo_edge_t **prev_of_next, **next_of_prev;
 
     sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
-				       1 /* unique inserts*/);
-    if (sweep_line_elt == NULL)
+					      1 /* unique inserts*/);
+    if (unlikely (sweep_line_elt == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     next_elt = sweep_line_elt->elt.next[0];
     if (next_elt)
 	prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev);
     else
 	prev_of_next = &sweep_line->tail;
 
@@ -978,17 +1106,18 @@ static cairo_status_t
 }
 
 static void
 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t	*edge)
 {
     cairo_bo_edge_t **left_next, **right_prev;
 
-    _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
+    _cairo_skip_list_delete_given (&sweep_line->active_edges,
+				   &edge->sweep_line_elt->elt);
 
     left_next = &sweep_line->head;
     if (edge->prev)
 	left_next = &edge->prev->next;
 
     right_prev = &sweep_line->tail;
     if (edge->next)
 	right_prev = &edge->next->prev;
@@ -1307,20 +1436,17 @@ static cairo_status_t
 			cairo_bo_traps_t	*bo_traps)
 {
     cairo_status_t status;
     int in_out = 0;
     cairo_bo_edge_t *edge;
 
     for (edge = head; edge; edge = edge->next) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-	    if (edge->reversed)
-		in_out++;
-	    else
-		in_out--;
+	    in_out += edge->dir;
 	    if (in_out == 0) {
 		status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
 		if (status)
 		    return status;
 		continue;
 	    }
 	} else {
 	    in_out++;
@@ -1359,21 +1485,25 @@ static cairo_status_t
     cairo_bo_event_queue_t event_queue;
     cairo_bo_sweep_line_t sweep_line;
     cairo_bo_traps_t bo_traps;
     cairo_bo_event_t *event, event_saved;
     cairo_bo_edge_t *edge;
     cairo_bo_edge_t *left, *right;
     cairo_bo_edge_t *edge1, *edge2;
 
+    if (num_edges == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
     if (status)
 	return status;
 
     _cairo_bo_sweep_line_init (&sweep_line);
+
     _cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
 
 #if DEBUG_PRINT_STATE
     print_state ("After initializing", &event_queue, &sweep_line);
 #endif
 
     while (1)
     {
@@ -1527,21 +1657,20 @@ cairo_status_t
     int num_bo_edges;
     int i;
 
     if (0 == polygon->num_edges)
 	return CAIRO_STATUS_SUCCESS;
 
     has_limits = _cairo_traps_get_limit (traps, &limit);
 
-    if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
-	edges = stack_edges;
-    } else {
+    edges = stack_edges;
+    if (polygon->num_edges > ARRAY_LENGTH (stack_edges)) {
 	edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
-	if (edges == NULL)
+	if (unlikely (edges == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     /* Figure out the bounding box of the input coordinates and
      * validate that we're not given invalid polygon edges. */
     for (i = 0; i < polygon->num_edges; i++) {
 	update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x);
 	update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y);
@@ -1599,20 +1728,17 @@ cairo_status_t
 	assert (top.y < bot.y &&
 		"BUG: clamping the input range flipped the "
 		"orientation of an edge");
 
 	edge->top.x = top.x;
 	edge->top.y = top.y;
 	edge->bottom.x = bot.x;
 	edge->bottom.y = bot.y;
-	/* XXX: The 'clockWise' name that cairo_polygon_t uses is
-	 * totally bogus. It's really a (negated!) description of
-	 * whether the edge is reversed. */
-	edge->reversed = (! polygon->edges[i].clockWise);
+	edge->dir = polygon->edges[i].dir;
 	edge->deferred_trap = NULL;
 	edge->prev = NULL;
 	edge->next = NULL;
 	edge->sweep_line_elt = NULL;
 
 	num_bo_edges++;
     }
 
--- a/gfx/cairo/cairo/src/cairo-beos-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-beos-surface.cpp
@@ -31,30 +31,31 @@
  * The Initial Developer of the Original Code is Christian Biesinger
  * <cbiesinger@web.de>
  *
  * Contributor(s):
  */
 
 // This is a C++ file in order to use the C++ BeOS API
 
+#include "cairoint.h"
+
+#include "cairo-beos.h"
+
 #include <new>
 
 #include <Bitmap.h>
 #include <Region.h>
 #if 0
 #include <DirectWindow.h>
 #endif
 #include <Screen.h>
 #include <Window.h>
 #include <Locker.h>
 
-#include "cairoint.h"
-#include "cairo-beos.h"
-
 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)
 
 struct cairo_beos_surface_t {
     cairo_surface_t base;
 
     BView* view;
 
     /*
@@ -253,17 +254,17 @@ unpremultiply_rgba (unsigned char* data,
  * The returned data must be freed with free().
  **/
 static unsigned char*
 premultiply_rgba (unsigned char* data,
 		  int            width,
 		  int            height,
 		  int            stride)
 {
-    unsigned char* retdata = reinterpret_cast<unsigned char*>(malloc(stride * height));
+    unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
     if (!retdata)
 	return NULL;
 
     unsigned char* end = data + stride * height;
     for (unsigned char* in = data, *out = retdata;
 	 in < end;
 	 in += stride, out += stride)
     {
@@ -316,17 +317,17 @@ static cairo_image_surface_t*
     int width = bounds.IntegerWidth() + 1;
     int height = bounds.IntegerHeight() + 1;
     unsigned char* premultiplied;
     if (cformat == CAIRO_FORMAT_ARGB32) {
        premultiplied = premultiply_rgba(bits, width, height,
 					bitmap->BytesPerRow());
     } else {
 	premultiplied = reinterpret_cast<unsigned char*>(
-					malloc(bitmap->BytesPerRow() * height));
+					_cairo_malloc_ab(bitmap->BytesPerRow(), height));
 	if (premultiplied)
 	    memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
     }
     if (!premultiplied)
 	return NULL;
 
     cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*>
 	(cairo_image_surface_create_for_data(premultiplied,
@@ -889,16 +890,18 @@ static const struct _cairo_surface_backe
     _cairo_beos_surface_acquire_source_image,
     _cairo_beos_surface_release_source_image,
     _cairo_beos_surface_acquire_dest_image,
     _cairo_beos_surface_release_dest_image,
     NULL, /* clone_similar */
     _cairo_beos_surface_composite, /* composite */
     _cairo_beos_surface_fill_rectangles,
     NULL, /* composite_trapezoids */
+    NULL, /* create_span_renderer */
+    NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
     _cairo_beos_surface_set_clip_region,
     NULL, /* intersect_clip_path */
     _cairo_beos_surface_get_extents,
     NULL,  /* old_show_glyphs */
     NULL, /* get_font_options */
     NULL, /* flush */
@@ -940,17 +943,17 @@ static cairo_surface_t *
 
 /**
  * cairo_beos_surface_create:
  * @view: The view to draw on
  *
  * Creates a Cairo surface that draws onto a BeOS BView.
  * The caller must ensure that the view does not get deleted before the surface.
  * If the view is attached to a bitmap rather than an on-screen window, use
- * cairo_beos_surface_create_for_bitmap instead of this function.
+ * cairo_beos_surface_create_for_bitmap() instead of this function.
  **/
 cairo_surface_t *
 cairo_beos_surface_create (BView* view)
 {
     return cairo_beos_surface_create_for_bitmap(view, NULL);
 }
 
 /**
@@ -971,38 +974,8 @@ cairo_beos_surface_create (BView* view)
  * The view must already be attached to the bitmap.
  **/
 cairo_surface_t *
 cairo_beos_surface_create_for_bitmap (BView*   view,
 				      BBitmap* bmp)
 {
     return _cairo_beos_surface_create_internal(view, bmp);
 }
-
-// ---------------------------------------------------------------------------
-// Cairo uses locks without explicit initialization. To support that, we
-// provide a class here which manages the locks and is in global scope, so the
-// compiler will instantiate it on library load and destroy it on library
-// unload.
-
-class BeLocks {
-    public:
-	BLocker cairo_toy_font_face_hash_table_mutex;
-	BLocker cairo_scaled_font_map_mutex;
-	BLocker cairo_ft_unscaled_font_map_mutex;
-};
-
-static BeLocks locks;
-
-void* cairo_toy_font_face_hash_table_mutex = &locks.cairo_toy_font_face_hash_table_mutex;
-void* cairo_scaled_font_map_mutex = &locks.cairo_scaled_font_map_mutex;
-void* cairo_ft_unscaled_font_map_mutex = &locks.cairo_ft_unscaled_font_map_mutex;
-
-void _cairo_beos_lock (void* locker) {
-    BLocker* bLocker = reinterpret_cast<BLocker*>(locker);
-    bLocker->Lock();
-}
-
-void _cairo_beos_unlock (void* locker) {
-    BLocker* bLocker = reinterpret_cast<BLocker*>(locker);
-    bLocker->Unlock();
-}
-
--- a/gfx/cairo/cairo/src/cairo-cache-private.h
+++ b/gfx/cairo/cairo/src/cairo-cache-private.h
@@ -92,35 +92,39 @@ typedef cairo_bool_t
 (*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
 
 typedef void
 (*cairo_cache_callback_func_t) (void *entry,
 				void *closure);
 
 cairo_private cairo_cache_t *
 _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+		     cairo_cache_predicate_func_t  predicate,
 		     cairo_destroy_func_t	   entry_destroy,
 		     unsigned long		   max_size);
 
 cairo_private void
 _cairo_cache_destroy (cairo_cache_t *cache);
 
 cairo_private void
 _cairo_cache_freeze (cairo_cache_t *cache);
 
 cairo_private void
 _cairo_cache_thaw (cairo_cache_t *cache);
 
-cairo_private cairo_bool_t
+cairo_private void *
 _cairo_cache_lookup (cairo_cache_t	  *cache,
-		     cairo_cache_entry_t  *key,
-		     cairo_cache_entry_t **entry_return);
+		     cairo_cache_entry_t  *key);
 
 cairo_private cairo_status_t
 _cairo_cache_insert (cairo_cache_t	 *cache,
 		     cairo_cache_entry_t *entry);
 
 cairo_private void
-_cairo_cache_foreach (cairo_cache_t 	      	 *cache,
+_cairo_cache_remove (cairo_cache_t	 *cache,
+		     cairo_cache_entry_t *entry);
+
+cairo_private void
+_cairo_cache_foreach (cairo_cache_t		 *cache,
 		      cairo_cache_callback_func_t cache_callback,
 		      void			 *closure);
 
 #endif
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -34,62 +34,63 @@
  *      Keith Packard <keithp@keithp.com>
  *	Graydon Hoare <graydon@redhat.com>
  *	Carl Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
 
 static void
-_cairo_cache_remove (cairo_cache_t	 *cache,
-		     cairo_cache_entry_t *entry);
+_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
+				    unsigned long  additional);
 
-static void
-_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
-				   unsigned long  additional);
+static cairo_bool_t
+_cairo_cache_entry_is_non_zero (const void *entry)
+{
+    return ((const cairo_cache_entry_t *) entry)->size;
+}
 
 static cairo_status_t
 _cairo_cache_init (cairo_cache_t		*cache,
 		   cairo_cache_keys_equal_func_t keys_equal,
+		   cairo_cache_predicate_func_t  predicate,
 		   cairo_destroy_func_t		 entry_destroy,
 		   unsigned long		 max_size)
 {
     cache->hash_table = _cairo_hash_table_create (keys_equal);
-    if (cache->hash_table == NULL)
+    if (unlikely (cache->hash_table == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
+    if (predicate == NULL)
+	predicate = _cairo_cache_entry_is_non_zero;
+    cache->predicate = predicate;
     cache->entry_destroy = entry_destroy;
 
     cache->max_size = max_size;
     cache->size = 0;
 
     cache->freeze_count = 0;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
+_cairo_cache_pluck (void *entry, void *closure)
+{
+    _cairo_cache_remove (closure, entry);
+}
+
+static void
 _cairo_cache_fini (cairo_cache_t *cache)
 {
-    cairo_cache_entry_t *entry;
-
-    /* We have to manually remove all entries from the cache ourselves
-     * rather than relying on _cairo_hash_table_destroy() to do that
-     * since otherwise the cache->entry_destroy callback would not get
-     * called on each entry. */
-
-    while (1) {
-	entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
-	if (entry == NULL)
-	    break;
-	_cairo_cache_remove (cache, entry);
-    }
-
+    _cairo_hash_table_foreach (cache->hash_table,
+			       _cairo_cache_pluck,
+			       cache);
+    assert (cache->size == 0);
     _cairo_hash_table_destroy (cache->hash_table);
-    cache->size = 0;
 }
 
 /**
  * _cairo_cache_create:
  * @keys_equal: a function to return %TRUE if two keys are equal
  * @entry_destroy: destroy notifier for cache entries
  * @max_size: the maximum size for this cache
  * Returns: the newly created #cairo_cache_t
@@ -118,30 +119,35 @@ static void
  * in some cases the memory overhead of adding a reference count to
  * the entry would be objectionable. In such cases, the
  * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
  * used to establish a window during which no automatic removal of
  * entries will occur.
  **/
 cairo_cache_t *
 _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+		     cairo_cache_predicate_func_t  predicate,
 		     cairo_destroy_func_t	   entry_destroy,
 		     unsigned long		   max_size)
 {
     cairo_status_t status;
     cairo_cache_t *cache;
 
     cache = malloc (sizeof (cairo_cache_t));
-    if (cache == NULL) {
+    if (unlikely (cache == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
 
-    status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
-    if (status) {
+    status = _cairo_cache_init (cache,
+				keys_equal,
+				predicate,
+				entry_destroy,
+				max_size);
+    if (unlikely (status)) {
 	free (cache);
 	return NULL;
     }
 
     return cache;
 }
 
 /**
@@ -217,42 +223,41 @@ void
  * Performs a lookup in @cache looking for an entry which has a key
  * that matches @key, (as determined by the keys_equal() function
  * passed to _cairo_cache_create()).
  *
  * Return value: %TRUE if there is an entry in the cache that matches
  * @key, (which will now be in *entry_return). %FALSE otherwise, (in
  * which case *entry_return will be %NULL).
  **/
-cairo_bool_t
+void *
 _cairo_cache_lookup (cairo_cache_t	  *cache,
-		     cairo_cache_entry_t  *key,
-		     cairo_cache_entry_t **entry_return)
+		     cairo_cache_entry_t  *key)
 {
     return _cairo_hash_table_lookup (cache->hash_table,
-				     (cairo_hash_entry_t *) key,
-				     (cairo_hash_entry_t **) entry_return);
+				     (cairo_hash_entry_t *) key);
 }
 
 /**
  * _cairo_cache_remove_random:
  * @cache: a cache
  *
  * Remove a random entry from the cache.
  *
  * Return value: %TRUE if an entry was successfully removed.
  * %FALSE if there are no entries that can be removed.
  **/
 static cairo_bool_t
 _cairo_cache_remove_random (cairo_cache_t *cache)
 {
     cairo_cache_entry_t *entry;
 
-    entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
-    if (entry == NULL)
+    entry = _cairo_hash_table_random_entry (cache->hash_table,
+					    cache->predicate);
+    if (unlikely (entry == NULL))
 	return FALSE;
 
     _cairo_cache_remove (cache, entry);
 
     return TRUE;
 }
 
 /**
@@ -295,37 +300,32 @@ cairo_status_t
 		     cairo_cache_entry_t *entry)
 {
     cairo_status_t status;
 
     _cairo_cache_shrink_to_accommodate (cache, entry->size);
 
     status = _cairo_hash_table_insert (cache->hash_table,
 				       (cairo_hash_entry_t *) entry);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     cache->size += entry->size;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_cache_remove:
  * @cache: a cache
  * @entry: an entry that exists in the cache
  *
  * Remove an existing entry from the cache.
- *
- * (Note: If any caller wanted access to a non-static version of this
- * function, an improved version would require only a key rather than
- * an entry. Fixing that would require fixing _cairo_hash_table_remove
- * to return (a copy of?) the entry being removed.)
  **/
-static void
+void
 _cairo_cache_remove (cairo_cache_t	 *cache,
 		     cairo_cache_entry_t *entry)
 {
     cache->size -= entry->size;
 
     _cairo_hash_table_remove (cache->hash_table,
 			      (cairo_hash_entry_t *) entry);
 
@@ -338,26 +338,38 @@ static void
  * @cache: a cache
  * @cache_callback: function to be called for each entry
  * @closure: additional argument to be passed to @cache_callback
  *
  * Call @cache_callback for each entry in the cache, in a
  * non-specified order.
  **/
 void
-_cairo_cache_foreach (cairo_cache_t	 	      *cache,
+_cairo_cache_foreach (cairo_cache_t		      *cache,
 		      cairo_cache_callback_func_t      cache_callback,
 		      void			      *closure)
 {
     _cairo_hash_table_foreach (cache->hash_table,
 			       cache_callback,
 			       closure);
 }
 
 unsigned long
 _cairo_hash_string (const char *c)
 {
     /* This is the djb2 hash. */
-    unsigned long hash = 5381;
+    unsigned long hash = _CAIRO_HASH_INIT_VALUE;
     while (c && *c)
 	hash = ((hash << 5) + hash) + *c++;
     return hash;
 }
+
+unsigned long
+_cairo_hash_bytes (unsigned long hash,
+		   const void *ptr,
+		   unsigned int length)
+{
+    const uint8_t *bytes = ptr;
+    /* This is the djb2 hash. */
+    while (length--)
+	hash = ((hash << 5) + hash) + *bytes++;
+    return hash;
+}
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -103,16 +103,17 @@ typedef struct _cairo_cff_font {
 
     /* Font Data */
     unsigned char       *data;
     unsigned long        data_length;
     unsigned char       *current_ptr;
     unsigned char       *data_end;
     cff_header_t        *header;
     char                *font_name;
+    char                *ps_name;
     cairo_hash_table_t  *top_dict;
     cairo_hash_table_t  *private_dict;
     cairo_array_t        strings_index;
     cairo_array_t        charstrings_index;
     cairo_array_t        global_sub_index;
     cairo_array_t        local_sub_index;
     int                  num_glyphs;
     cairo_bool_t         is_cid;
@@ -293,17 +294,17 @@ cff_index_read (cairo_array_t *index, un
             end = decode_index_offset (p, offset_size);
             p += offset_size;
             if (p > end_ptr)
                 return CAIRO_INT_STATUS_UNSUPPORTED;
             element.length = end - start;
             element.is_copy = FALSE;
             element.data = data + start;
             status = _cairo_array_append (index, &element);
-            if (status)
+            if (unlikely (status))
                 return status;
             start = end;
         }
         p = data + end;
     }
     *ptr = p;
 
     return CAIRO_STATUS_SUCCESS;
@@ -319,17 +320,17 @@ cff_index_write (cairo_array_t *index, c
     cff_index_element_t *element;
     uint16_t count;
     unsigned char buf[5];
     cairo_status_t status;
 
     num_elem = _cairo_array_num_elements (index);
     count = cpu_to_be16 ((uint16_t) num_elem);
     status = _cairo_array_append_multiple (output, &count, 2);
-    if (status)
+    if (unlikely (status))
         return status;
 
     if (num_elem == 0)
         return CAIRO_STATUS_SUCCESS;
 
     /* Find maximum offset to determine offset size */
     offset = 1;
     for (i = 0; i < num_elem; i++) {
@@ -342,40 +343,40 @@ cff_index_write (cairo_array_t *index, c
         offset_size = 2;
     else if (offset < 0x1000000)
         offset_size = 3;
     else
         offset_size = 4;
 
     buf[0] = (unsigned char) offset_size;
     status = _cairo_array_append (output, buf);
-    if (status)
+    if (unlikely (status))
         return status;
 
     offset = 1;
     encode_index_offset (buf, offset_size, offset);
     status = _cairo_array_append_multiple (output, buf, offset_size);
-    if (status)
+    if (unlikely (status))
         return status;
 
     for (i = 0; i < num_elem; i++) {
         element = _cairo_array_index (index, i);
         offset += element->length;
         encode_index_offset (buf, offset_size, offset);
         status = _cairo_array_append_multiple (output, buf, offset_size);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     for (i = 0; i < num_elem; i++) {
         element = _cairo_array_index (index, i);
         status = _cairo_array_append_multiple (output,
                                                element->data,
                                                element->length);
-        if (status)
+        if (unlikely (status))
             return status;
     }
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cff_index_append (cairo_array_t *index, unsigned char *object , int length)
 {
@@ -394,23 +395,23 @@ cff_index_append_copy (cairo_array_t *in
                        unsigned int length)
 {
     cff_index_element_t element;
     cairo_status_t status;
 
     element.length = length;
     element.is_copy = TRUE;
     element.data = malloc (element.length);
-    if (element.data == NULL)
+    if (unlikely (element.data == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     memcpy (element.data, object, element.length);
 
     status = _cairo_array_append (index, &element);
-    if (status) {
+    if (unlikely (status)) {
 	free (element.data);
 	return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -435,50 +436,50 @@ static cairo_bool_t
 
     return op_a->operator == op_b->operator;
 }
 
 static cairo_status_t
 cff_dict_init (cairo_hash_table_t **dict)
 {
     *dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
-    if (*dict == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
+    if (unlikely (*dict == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_dict_init_key (cff_dict_operator_t *key, int operator)
 {
     key->base.hash = (unsigned long) operator;
     key->operator = operator;
 }
 
 static cairo_status_t
 cff_dict_create_operator (int            operator,
                           unsigned char *operand,
-                          int            operand_length,
+                          int            size,
 			  cff_dict_operator_t **out)
 {
     cff_dict_operator_t *op;
 
     op = malloc (sizeof (cff_dict_operator_t));
-    if (op == NULL)
+    if (unlikely (op == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_dict_init_key (op, operator);
-    op->operand = malloc (operand_length);
-    if (op->operand == NULL) {
+    op->operand = malloc (size);
+    if (unlikely (op->operand == NULL)) {
         free (op);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    memcpy (op->operand, operand, operand_length);
-    op->operand_length = operand_length;
+    memcpy (op->operand, operand, size);
+    op->operand_length = size;
     op->operand_offset = -1;
 
     *out = op;
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
@@ -491,31 +492,31 @@ cff_dict_read (cairo_hash_table_t *dict,
     int size;
 
     end = p + dict_size;
     _cairo_array_init (&operands, 1);
     while (p < end) {
         size = operand_length (p);
         if (size != 0) {
             status = _cairo_array_append_multiple (&operands, p, size);
-            if (status)
+            if (unlikely (status))
                 goto fail;
 
             p += size;
         } else {
             p = decode_operator (p, &operator);
             status = cff_dict_create_operator (operator,
                                           _cairo_array_index (&operands, 0),
                                           _cairo_array_num_elements (&operands),
 					  &op);
-            if (status)
+            if (unlikely (status))
                 goto fail;
 
             status = _cairo_hash_table_insert (dict, &op->base);
-            if (status)
+            if (unlikely (status))
                 goto fail;
 
             _cairo_array_truncate (&operands, 0);
         }
     }
 
 fail:
     _cairo_array_fini (&operands);
@@ -524,36 +525,34 @@ fail:
 }
 
 static void
 cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
 {
     cff_dict_operator_t key, *op;
 
     _cairo_dict_init_key (&key, operator);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
-    {
+    op = _cairo_hash_table_lookup (dict, &key.base);
+    if (op != NULL) {
         free (op->operand);
         _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
         free (op);
     }
 }
 
 static unsigned char *
 cff_dict_get_operands (cairo_hash_table_t *dict,
                        unsigned short      operator,
                        int                *size)
 {
     cff_dict_operator_t key, *op;
 
     _cairo_dict_init_key (&key, operator);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
-    {
+    op = _cairo_hash_table_lookup (dict, &key.base);
+    if (op != NULL) {
         *size = op->operand_length;
         return op->operand;
     }
 
     return NULL;
 }
 
 static cairo_status_t
@@ -561,52 +560,50 @@ cff_dict_set_operands (cairo_hash_table_
                        unsigned short      operator,
                        unsigned char      *operand,
                        int                 size)
 {
     cff_dict_operator_t key, *op;
     cairo_status_t status;
 
     _cairo_dict_init_key (&key, operator);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
-    {
+    op = _cairo_hash_table_lookup (dict, &key.base);
+    if (op != NULL) {
         free (op->operand);
         op->operand = malloc (size);
-	if (op->operand == NULL)
+	if (unlikely (op->operand == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
         memcpy (op->operand, operand, size);
         op->operand_length = size;
     }
     else
     {
         status = cff_dict_create_operator (operator, operand, size, &op);
-        if (status)
+        if (unlikely (status))
 	    return status;
 
 	status = _cairo_hash_table_insert (dict, &op->base);
-	if (status)
+	if (unlikely (status))
 	    return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static int
 cff_dict_get_location (cairo_hash_table_t *dict,
                        unsigned short      operator,
                        int                *size)
 {
     cff_dict_operator_t key, *op;
 
     _cairo_dict_init_key (&key, operator);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
-    {
+    op = _cairo_hash_table_lookup (dict, &key.base);
+    if (op != NULL) {
         *size = op->operand_length;
         return op->operand_offset;
     }
 
     return -1;
 }
 
 typedef struct _dict_write_info {
@@ -655,38 +652,39 @@ cff_dict_write (cairo_hash_table_t *dict
     cff_dict_operator_t key, *op;
 
     write_info.output = output;
     write_info.status = CAIRO_STATUS_SUCCESS;
 
     /* The CFF specification requires that the Top Dict of CID fonts
      * begin with the ROS operator. */
     _cairo_dict_init_key (&key, ROS_OP);
-    if (_cairo_hash_table_lookup (dict, &key.base,
-                                  (cairo_hash_entry_t **) &op))
+    op = _cairo_hash_table_lookup (dict, &key.base);
+    if (op != NULL)
         cairo_dict_write_operator (op, &write_info);
 
     _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
 
     return write_info.status;
 }
 
 static void
+_cff_dict_entry_pluck (void *_entry, void *dict)
+{
+    cff_dict_operator_t *entry = _entry;
+
+    _cairo_hash_table_remove (dict, &entry->base);
+    free (entry->operand);
+    free (entry);
+}
+
+static void
 cff_dict_fini (cairo_hash_table_t *dict)
 {
-    cff_dict_operator_t *entry;
-
-    while (1) {
-	entry = _cairo_hash_table_random_entry (dict, NULL);
-	if (entry == NULL)
-	    break;
-        free (entry->operand);
-        _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) entry);
-        free (entry);
-    }
+    _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
     _cairo_hash_table_destroy (dict);
 }
 
 static cairo_int_status_t
 cairo_cff_font_read_header (cairo_cff_font_t *font)
 {
     if (font->data_length < sizeof (cff_header_t))
         return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -723,44 +721,44 @@ cairo_cff_font_read_private_dict (cairo_
     unsigned char buf[10];
     unsigned char *end_buf;
     int offset;
     int i;
     unsigned char *operand;
     unsigned char *p;
 
     status = cff_dict_read (private_dict, ptr, size);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
     if (operand) {
         decode_integer (operand, &offset);
         p = ptr + offset;
         status = cff_index_read (local_sub_index, &p, font->data_end);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
         /* Use maximum sized encoding to reserve space for later modification. */
         end_buf = encode_integer_max (buf, 0);
         status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
-	if (status)
+	if (unlikely (status))
 	    return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
 {
     int type, num_ranges, first, last, fd, i, j;
 
     font->fdselect = calloc (font->num_glyphs, sizeof (int));
-    if (font->fdselect == NULL)
+    if (unlikely (font->fdselect == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     type = *p++;
     if (type == 0)
     {
         for (i = 0; i < font->num_glyphs; i++)
             font->fdselect[i] = *p++;
     } else if (type == 3) {
@@ -792,75 +790,75 @@ cairo_cff_font_read_cid_fontdict (cairo_
     unsigned char *operand;
     int offset;
     cairo_int_status_t status;
     unsigned char buf[100];
     unsigned char *end_buf;
 
     cff_index_init (&index);
     status = cff_index_read (&index, &ptr, font->data_end);
-    if (status)
+    if (unlikely (status))
         goto fail;
 
     font->num_fontdicts = _cairo_array_num_elements (&index);
 
     font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
-    if (font->fd_dict == NULL) {
+    if (unlikely (font->fd_dict == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail;
     }
 
     font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
-    if (font->fd_private_dict == NULL) {
+    if (unlikely (font->fd_private_dict == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail;
     }
 
     font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
-    if (font->fd_local_sub_index == NULL) {
+    if (unlikely (font->fd_local_sub_index == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail;
     }
 
     for (i = 0; i < font->num_fontdicts; i++) {
         status = cff_dict_init (&font->fd_dict[i]);
-        if (status)
+        if (unlikely (status))
             goto fail;
 
         element = _cairo_array_index (&index, i);
         status = cff_dict_read (font->fd_dict[i], element->data, element->length);
-        if (status)
+        if (unlikely (status))
             goto fail;
 
         operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
         if (operand == NULL) {
             status = CAIRO_INT_STATUS_UNSUPPORTED;
             goto fail;
         }
         operand = decode_integer (operand, &size);
         decode_integer (operand, &offset);
         status = cff_dict_init (&font->fd_private_dict[i]);
-	if (status)
+	if (unlikely (status))
             goto fail;
 
         cff_index_init (&font->fd_local_sub_index[i]);
         status = cairo_cff_font_read_private_dict (font,
                                                    font->fd_private_dict[i],
                                                    &font->fd_local_sub_index[i],
                                                    font->data + offset,
                                                    size);
-        if (status)
+        if (unlikely (status))
             goto fail;
 
         /* Set integer operand to max value to use max size encoding to reserve
          * space for any value later */
         end_buf = encode_integer_max (buf, 0);
         end_buf = encode_integer_max (end_buf, 0);
         status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
-        if (status)
+        if (unlikely (status))
             goto fail;
     }
 
     return CAIRO_STATUS_SUCCESS;
 
 fail:
     cff_index_fini (&index);
 
@@ -877,82 +875,82 @@ cairo_cff_font_read_top_dict (cairo_cff_
     unsigned char *operand;
     cairo_int_status_t status;
     unsigned char *p;
     int size;
     int offset;
 
     cff_index_init (&index);
     status = cff_index_read (&index, &font->current_ptr, font->data_end);
-    if (status)
+    if (unlikely (status))
         goto fail;
 
     element = _cairo_array_index (&index, 0);
     status = cff_dict_read (font->top_dict, element->data, element->length);
-    if (status)
+    if (unlikely (status))
         goto fail;
 
     if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
         font->is_cid = TRUE;
     else
         font->is_cid = FALSE;
 
     operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
     decode_integer (operand, &offset);
     p = font->data + offset;
     status = cff_index_read (&font->charstrings_index, &p, font->data_end);
-    if (status)
+    if (unlikely (status))
         goto fail;
     font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
 
     if (font->is_cid) {
         operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
         decode_integer (operand, &offset);
         status = cairo_cff_font_read_fdselect (font, font->data + offset);
-	if (status)
+	if (unlikely (status))
 	    goto fail;
 
         operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
         decode_integer (operand, &offset);
         status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
-	if (status)
+	if (unlikely (status))
 	    goto fail;
     } else {
         operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
         operand = decode_integer (operand, &size);
         decode_integer (operand, &offset);
         status = cairo_cff_font_read_private_dict (font,
                                                    font->private_dict,
 						   &font->local_sub_index,
 						   font->data + offset,
 						   size);
-	if (status)
+	if (unlikely (status))
 	    goto fail;
     }
 
     /* Use maximum sized encoding to reserve space for later modification. */
     end_buf = encode_integer_max (buf, 0);
     status = cff_dict_set_operands (font->top_dict,
 	                            CHARSTRINGS_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	goto fail;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            FDSELECT_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	goto fail;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            FDARRAY_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	goto fail;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            CHARSET_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	goto fail;
 
     cff_dict_remove (font->top_dict, ENCODING_OP);
     cff_dict_remove (font->top_dict, PRIVATE_OP);
 
     /* Remove the unique identifier operators as the subsetted font is
      * not the same is the original font. */
     cff_dict_remove (font->top_dict, UNIQUEID_OP);
@@ -990,17 +988,17 @@ static const font_read_t font_read_funcs
 static cairo_int_status_t
 cairo_cff_font_read_font (cairo_cff_font_t *font)
 {
     cairo_int_status_t status;
     unsigned int i;
 
     for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
         status = font_read_funcs[i] (font);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
@@ -1011,36 +1009,36 @@ cairo_cff_font_set_ros_strings (cairo_cf
     int sid1, sid2;
     const char *registry = "Adobe";
     const char *ordering = "Identity";
 
     sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
     status = cff_index_append_copy (&font->strings_subset_index,
                                     (unsigned char *)registry,
                                     strlen(registry));
-    if (status)
+    if (unlikely (status))
 	return status;
 
     sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
     status = cff_index_append_copy (&font->strings_subset_index,
                                     (unsigned char *)ordering,
 				    strlen(ordering));
-    if (status)
+    if (unlikely (status))
 	return status;
 
     p = encode_integer (buf, sid1);
     p = encode_integer (p, sid2);
     p = encode_integer (p, 0);
     status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
     status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_cff_font_subset_dict_string(cairo_cff_font_t   *font,
                                   cairo_hash_table_t *dict,
@@ -1059,22 +1057,22 @@ cairo_cff_font_subset_dict_string(cairo_
 
     decode_integer (p, &sid);
     if (sid < NUM_STD_STRINGS)
         return CAIRO_STATUS_SUCCESS;
 
     element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
     sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
     status = cff_index_append (&font->strings_subset_index, element->data, element->length);
-    if (status)
+    if (unlikely (status))
         return status;
 
     p = encode_integer (buf, sid);
     status = cff_dict_set_operands (dict, operator, buf, p - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static const int dict_strings[] = {
     VERSION_OP,
     NOTICE_OP,
@@ -1091,17 +1089,17 @@ static cairo_status_t
 cairo_cff_font_subset_dict_strings (cairo_cff_font_t   *font,
                                     cairo_hash_table_t *dict)
 {
     cairo_status_t status;
     unsigned int i;
 
     for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
         status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_cff_font_subset_charstrings (cairo_cff_font_t  *font)
@@ -1111,45 +1109,45 @@ cairo_cff_font_subset_charstrings (cairo
     cairo_status_t status;
 
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
         element = _cairo_array_index (&font->charstrings_index,
                                       font->scaled_font_subset->glyphs[i]);
         status = cff_index_append (&font->charstrings_subset_index,
                                    element->data,
                                    element->length);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_cff_font_subset_fontdict (cairo_cff_font_t  *font)
 {
     unsigned int i;
     int fd;
     int *reverse_map;
 
     font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
                                      sizeof (int));
-    if (font->fdselect_subset == NULL)
+    if (unlikely (font->fdselect_subset == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
-    if (font->fd_subset_map == NULL)
+    if (unlikely (font->fd_subset_map == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
-    if (font->private_dict_offset == NULL)
+    if (unlikely (font->private_dict_offset == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     reverse_map = calloc (font->num_fontdicts, sizeof (int));
-    if (reverse_map == NULL)
+    if (unlikely (reverse_map == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     for (i = 0; i < font->num_fontdicts; i++)
         reverse_map[i] = -1;
 
     font->num_subset_fontdicts = 0;
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
         fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
@@ -1169,97 +1167,97 @@ static cairo_status_t
 cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
 {
     unsigned char buf[100];
     unsigned char *end_buf;
     cairo_status_t status;
 
     font->num_fontdicts = 1;
     font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
-    if (font->fd_dict == NULL)
+    if (unlikely (font->fd_dict == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (cff_dict_init (&font->fd_dict[0])) {
 	free (font->fd_dict);
 	font->fd_dict = NULL;
 	font->num_fontdicts = 0;
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     font->fd_subset_map = malloc (sizeof (int));
-    if (font->fd_subset_map == NULL)
+    if (unlikely (font->fd_subset_map == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->private_dict_offset = malloc (sizeof (int));
-    if (font->private_dict_offset == NULL)
+    if (unlikely (font->private_dict_offset == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->fd_subset_map[0] = 0;
     font->num_subset_fontdicts = 1;
 
     /* Set integer operand to max value to use max size encoding to reserve
      * space for any value later */
     end_buf = encode_integer_max (buf, 0);
     end_buf = encode_integer_max (end_buf, 0);
     status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_cff_font_subset_strings (cairo_cff_font_t *font)
 {
     cairo_status_t status;
     unsigned int i;
 
     status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
-    if (status)
+    if (unlikely (status))
         return status;
 
     if (font->is_cid) {
         for (i = 0; i < font->num_subset_fontdicts; i++) {
             status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
-            if (status)
+            if (unlikely (status))
                 return status;
 
             status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
     } else {
         status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
     }
 
     return status;
 }
 
 static cairo_status_t
 cairo_cff_font_subset_font (cairo_cff_font_t  *font)
 {
     cairo_status_t status;
 
     status = cairo_cff_font_set_ros_strings (font);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cairo_cff_font_subset_charstrings (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     if (font->is_cid)
         status = cairo_cff_font_subset_fontdict (font);
     else
         status = cairo_cff_font_create_cid_fontdict (font);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cairo_cff_font_subset_strings (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     return status;
 }
 
 /* Set the operand of the specified operator in the (already written)
  * top dict to point to the current position in the output
  * array. Operands updated with this function must have previously
@@ -1297,21 +1295,21 @@ cairo_cff_font_write_name (cairo_cff_fon
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_array_t index;
 
     cff_index_init (&index);
 
     status = cff_index_append_copy (&index,
                                     (unsigned char *) font->subset_font_name,
                                     strlen(font->subset_font_name));
-    if (status)
+    if (unlikely (status))
 	goto FAIL;
 
     status = cff_index_write (&index, &font->output);
-    if (status)
+    if (unlikely (status))
         goto FAIL;
 
 FAIL:
     cff_index_fini (&index);
 
     return status;
 }
 
@@ -1325,37 +1323,37 @@ cairo_cff_font_write_top_dict (cairo_cff
     int dict_start, dict_size;
     int offset_size = 4;
     cairo_status_t status;
 
     /* Write an index containing the top dict */
 
     count = cpu_to_be16 (1);
     status = _cairo_array_append_multiple (&font->output, &count, 2);
-    if (status)
+    if (unlikely (status))
         return status;
     buf[0] = offset_size;
     status = _cairo_array_append (&font->output, buf);
-    if (status)
+    if (unlikely (status))
         return status;
     encode_index_offset (buf, offset_size, 1);
     status = _cairo_array_append_multiple (&font->output, buf, offset_size);
-    if (status)
+    if (unlikely (status))
         return status;
 
     /* Reserve space for last element of offset array and update after
      * dict is written */
     offset_index = _cairo_array_num_elements (&font->output);
     status = _cairo_array_append_multiple (&font->output, buf, offset_size);
-    if (status)
+    if (unlikely (status))
         return status;
 
     dict_start = _cairo_array_num_elements (&font->output);
     status = cff_dict_write (font->top_dict, &font->output);
-    if (status)
+    if (unlikely (status))
         return status;
     dict_size = _cairo_array_num_elements (&font->output) - dict_start;
 
     encode_index_offset (buf, offset_size, dict_size + 1);
     p = _cairo_array_index (&font->output, offset_index);
     memcpy (p, buf, offset_size);
 
     return CAIRO_STATUS_SUCCESS;
@@ -1380,31 +1378,31 @@ cairo_cff_font_write_fdselect (cairo_cff
     unsigned int i;
     cairo_int_status_t status;
 
     cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
 
     if (font->is_cid) {
         data = 0;
         status = _cairo_array_append (&font->output, &data);
-        if (status)
+        if (unlikely (status))
             return status;
 
         for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
             data = font->fdselect_subset[i];
             status = _cairo_array_append (&font->output, &data);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
     } else {
         unsigned char byte;
         uint16_t word;
 
         status = _cairo_array_grow_by (&font->output, 9);
-        if (status)
+        if (unlikely (status))
             return status;
 
         byte = 3;
         status = _cairo_array_append (&font->output, &byte);
         assert (status == CAIRO_STATUS_SUCCESS);
 
         word = cpu_to_be16 (1);
         status = _cairo_array_append_multiple (&font->output, &word, 2);
@@ -1430,17 +1428,17 @@ static cairo_status_t
 cairo_cff_font_write_charset (cairo_cff_font_t  *font)
 {
     unsigned char byte;
     uint16_t word;
     cairo_status_t status;
 
     cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
     status = _cairo_array_grow_by (&font->output, 5);
-    if (status)
+    if (unlikely (status))
         return status;
 
     byte = 2;
     status = _cairo_array_append (&font->output, &byte);
     assert (status == CAIRO_STATUS_SUCCESS);
 
     word = cpu_to_be16 (1);
     status = _cairo_array_append_multiple (&font->output, &word, 2);
@@ -1469,32 +1467,32 @@ cairo_cff_font_write_cid_fontdict (cairo
     uint32_t *offset_array;
     int offset_base;
     uint16_t count;
     uint8_t offset_size = 4;
 
     cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
     count = cpu_to_be16 (font->num_subset_fontdicts);
     status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
-    if (status)
+    if (unlikely (status))
         return status;
     status = _cairo_array_append (&font->output, &offset_size);
-    if (status)
+    if (unlikely (status))
         return status;
     status = _cairo_array_allocate (&font->output,
                                     (font->num_subset_fontdicts + 1)*offset_size,
                                     (void **) &offset_array);
-    if (status)
+    if (unlikely (status))
         return status;
     offset_base = _cairo_array_num_elements (&font->output) - 1;
     *offset_array++ = cpu_to_be32(1);
     for (i = 0; i < font->num_subset_fontdicts; i++) {
         status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
                                  &font->output);
-        if (status)
+        if (unlikely (status))
             return status;
         *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -1508,17 +1506,17 @@ cairo_cff_font_write_private_dict (cairo
     unsigned char buf[10];
     unsigned char *buf_end;
     unsigned char *p;
     cairo_status_t status;
 
     /* Write private dict and update offset and size in top dict */
     font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
     status = cff_dict_write (private_dict, &font->output);
-    if (status)
+    if (unlikely (status))
         return status;
 
     size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
     /* private entry has two operands - size and offset */
     buf_end = encode_integer_max (buf, size);
     buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
     offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
     assert (offset > 0);
@@ -1547,17 +1545,17 @@ cairo_cff_font_write_local_sub (cairo_cf
          * private dict */
         offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
         buf_end = encode_integer_max (buf, offset);
         offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
         assert (offset > 0);
         p = _cairo_array_index (&font->output, offset);
         memcpy (p, buf, buf_end - buf);
         status = cff_index_write (local_sub_index, &font->output);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 
 static cairo_status_t
@@ -1568,42 +1566,42 @@ cairo_cff_font_write_cid_private_dict_an
 
     if (font->is_cid) {
         for (i = 0; i < font->num_subset_fontdicts; i++) {
             status = cairo_cff_font_write_private_dict (
                             font,
                             i,
                             font->fd_dict[font->fd_subset_map[i]],
                             font->fd_private_dict[font->fd_subset_map[i]]);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
 
         for (i = 0; i < font->num_subset_fontdicts; i++) {
             status = cairo_cff_font_write_local_sub (
                             font,
                             i,
                             font->fd_private_dict[font->fd_subset_map[i]],
                            &font->fd_local_sub_index[font->fd_subset_map[i]]);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
     } else {
         status = cairo_cff_font_write_private_dict (font,
                                                     0,
                                                     font->fd_dict[0],
                                                     font->private_dict);
-	if (status)
+	if (unlikely (status))
 	    return status;
 
         status = cairo_cff_font_write_local_sub (font,
                                                  0,
                                                  font->private_dict,
                                                  &font->local_sub_index);
-	if (status)
+	if (unlikely (status))
 	    return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 typedef cairo_status_t
 (*font_write_t) (cairo_cff_font_t *font);
@@ -1624,40 +1622,40 @@ static const font_write_t font_write_fun
 static cairo_status_t
 cairo_cff_font_write_subset (cairo_cff_font_t *font)
 {
     cairo_int_status_t status;
     unsigned int i;
 
     for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
         status = font_write_funcs[i] (font);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 cairo_cff_font_generate (cairo_cff_font_t  *font,
                          const char       **data,
                          unsigned long     *length)
 {
     cairo_int_status_t status;
 
     status = cairo_cff_font_read_font (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     status = cairo_cff_font_subset_font (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     status = cairo_cff_font_write_subset (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     *data = _cairo_array_index (&font->output, 0);
     *length = _cairo_array_num_elements (&font->output);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1673,39 +1671,39 @@ cairo_cff_font_create_set_widths (cairo_
     unsigned char buf[10];
     int glyph_index;
     cairo_int_status_t status;
 
     size = sizeof (tt_hhea_t);
     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                  TT_TAG_hhea, 0,
                                                  (unsigned char*) &hhea, &size);
-    if (status)
+    if (unlikely (status))
         return status;
     num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
 
     for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
         glyph_index = font->scaled_font_subset->glyphs[i];
         long_entry_size = 2 * sizeof (int16_t);
         short_entry_size = sizeof (int16_t);
         if (glyph_index < num_hmetrics) {
             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                          TT_TAG_hmtx,
                                                          glyph_index * long_entry_size,
                                                          buf, &short_entry_size);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
         else
         {
             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
                                                          TT_TAG_hmtx,
                                                          (num_hmetrics - 1) * long_entry_size,
                                                          buf, &short_entry_size);
-            if (status)
+            if (unlikely (status))
                 return status;
         }
         font->widths[i] = be16_to_cpu (*((int16_t*)buf));
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1714,210 +1712,169 @@ static cairo_int_status_t
                         cairo_cff_font_t           **font_return,
                         const char                  *subset_name)
 {
     const cairo_scaled_font_backend_t *backend;
     cairo_status_t status;
     cairo_cff_font_t *font;
     tt_head_t head;
     tt_hhea_t hhea;
-    tt_name_t *name;
-    tt_name_record_t *record;
     unsigned long size, data_length;
-    int i, j;
 
     backend = scaled_font_subset->scaled_font->backend;
     if (!backend->load_truetype_table)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     data_length = 0;
     status = backend->load_truetype_table( scaled_font_subset->scaled_font,
                                            TT_TAG_CFF, 0, NULL, &data_length);
-    if (status)
+    if (unlikely (status))
         return status;
 
     size = sizeof (tt_head_t);
     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
                                            TT_TAG_head, 0,
                                            (unsigned char *) &head, &size);
-    if (status)
+    if (unlikely (status))
         return status;
 
     size = sizeof (tt_hhea_t);
     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
                                            TT_TAG_hhea, 0,
                                            (unsigned char *) &hhea, &size);
-    if (status)
+    if (unlikely (status))
         return status;
 
     size = 0;
     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
                                            TT_TAG_hmtx, 0, NULL, &size);
-    if (status)
-        return status;
-
-    size = 0;
-    status = backend->load_truetype_table (scaled_font_subset->scaled_font,
-                                           TT_TAG_name, 0, NULL, &size);
-    if (status)
+    if (unlikely (status))
         return status;
 
-    name = malloc (size);
-    if (name == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = backend->load_truetype_table (scaled_font_subset->scaled_font,
-                                           TT_TAG_name, 0,
-                                           (unsigned char *) name, &size);
-    if (status)
-        goto fail1;
-
     font = malloc (sizeof (cairo_cff_font_t));
-    if (font == NULL) {
-        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail1;
-    }
+    if (unlikely (font == NULL))
+        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->backend = backend;
     font->scaled_font_subset = scaled_font_subset;
 
     _cairo_array_init (&font->output, sizeof (char));
     status = _cairo_array_grow_by (&font->output, 4096);
-    if (status)
+    if (unlikely (status))
 	goto fail2;
 
     font->subset_font_name = strdup (subset_name);
-    if (font->subset_font_name == NULL) {
+    if (unlikely (font->subset_font_name == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
     }
     font->x_min = (int16_t) be16_to_cpu (head.x_min);
     font->y_min = (int16_t) be16_to_cpu (head.y_min);
     font->x_max = (int16_t) be16_to_cpu (head.x_max);
     font->y_max = (int16_t) be16_to_cpu (head.y_max);
     font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
     font->descent = (int16_t) be16_to_cpu (hhea.descender);
 
-    /* Extract the font name from the name table. At present this
-     * just looks for the Mac platform/Roman encoded font name. It
-     * should be extended to use any suitable font name in the
-     * name table. If the mac/roman font name is not found a
-     * CairoFont-x-y name is created.
-     */
     font->font_name = NULL;
-    for (i = 0; i < be16_to_cpu(name->num_records); i++) {
-        record = &(name->records[i]);
-        if ((be16_to_cpu (record->platform) == 1) &&
-            (be16_to_cpu (record->encoding) == 0) &&
-            (be16_to_cpu (record->name) == 4)) {
-            font->font_name = malloc (be16_to_cpu(record->length) + 1);
-            if (font->font_name) {
-                strncpy(font->font_name,
-                        ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
-                        be16_to_cpu (record->length));
-                font->font_name[be16_to_cpu (record->length)] = 0;
-            }
-            break;
-        }
-    }
+    status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
+					     &font->ps_name,
+					     &font->font_name);
+    if (_cairo_status_is_error (status))
+	goto fail3;
 
-    if (font->font_name == NULL) {
-        font->font_name = malloc (30);
-        if (font->font_name == NULL) {
-            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    /* If the PS name is not found, create a CairoFont-x-y name. */
+    if (font->ps_name == NULL) {
+        font->ps_name = malloc (30);
+        if (unlikely (font->ps_name == NULL)) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
             goto fail3;
-        }
-        snprintf(font->font_name, 30, "CairoFont-%u-%u",
+	}
+
+        snprintf(font->ps_name, 30, "CairoFont-%u-%u",
                  scaled_font_subset->font_id,
                  scaled_font_subset->subset_id);
     }
 
-    for (i = 0, j = 0; font->font_name[j]; j++) {
-	if (font->font_name[j] == ' ')
-	    continue;
-	font->font_name[i++] = font->font_name[j];
-    }
-    font->font_name[i] = '\0';
-
     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
-    if (font->widths == NULL) {
+    if (unlikely (font->widths == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail4;
     }
 
     status = cairo_cff_font_create_set_widths (font);
-    if (status)
+    if (unlikely (status))
 	goto fail5;
 
     font->data_length = data_length;
     font->data = malloc (data_length);
-    if (font->data == NULL) {
+    if (unlikely (font->data == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail5;
     }
     status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
                                                   TT_TAG_CFF, 0, font->data,
                                                   &font->data_length);
-    if (status)
+    if (unlikely (status))
         goto fail6;
 
     font->data_end = font->data + font->data_length;
 
     status = cff_dict_init (&font->top_dict);
-    if (status)
+    if (unlikely (status))
 	goto fail6;
 
     status = cff_dict_init (&font->private_dict);
-    if (status)
+    if (unlikely (status))
 	goto fail7;
 
     cff_index_init (&font->strings_index);
     cff_index_init (&font->charstrings_index);
     cff_index_init (&font->global_sub_index);
     cff_index_init (&font->local_sub_index);
     cff_index_init (&font->charstrings_subset_index);
     cff_index_init (&font->strings_subset_index);
     font->fdselect = NULL;
     font->fd_dict = NULL;
     font->fd_private_dict = NULL;
     font->fd_local_sub_index = NULL;
     font->fdselect_subset = NULL;
     font->fd_subset_map = NULL;
     font->private_dict_offset = NULL;
 
-    free (name);
     *font_return = font;
 
     return CAIRO_STATUS_SUCCESS;
 
 fail7:
     _cairo_hash_table_destroy (font->top_dict);
 fail6:
     free (font->data);
 fail5:
     free (font->widths);
 fail4:
-    free (font->font_name);
+    if (font->font_name)
+	free (font->font_name);
 fail3:
     free (font->subset_font_name);
 fail2:
     _cairo_array_fini (&font->output);
     free (font);
-fail1:
-    free (name);
+
     return status;
 }
 
 static void
 cairo_cff_font_destroy (cairo_cff_font_t *font)
 {
     unsigned int i;
 
     free (font->widths);
-    free (font->font_name);
+    if (font->font_name)
+	free (font->font_name);
+    free (font->ps_name);
     free (font->subset_font_name);
     _cairo_array_fini (&font->output);
     cff_dict_fini (font->top_dict);
     cff_dict_fini (font->private_dict);
     cff_index_fini (&font->strings_index);
     cff_index_fini (&font->charstrings_index);
     cff_index_fini (&font->global_sub_index);
     cff_index_fini (&font->local_sub_index);
@@ -1970,130 +1927,146 @@ cairo_status_t
 {
     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
     cairo_status_t status;
     const char *data = NULL; /* squelch bogus compiler warning */
     unsigned long length = 0; /* squelch bogus compiler warning */
     unsigned int i;
 
     status = _cairo_cff_font_create (font_subset, &font, subset_name);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cairo_cff_font_generate (font, &data, &length);
-    if (status)
+    if (unlikely (status))
 	goto fail1;
 
-    cff_subset->base_font = strdup (font->font_name);
-    if (cff_subset->base_font == NULL) {
+    cff_subset->ps_name = strdup (font->ps_name);
+    if (unlikely (cff_subset->ps_name == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail1;
     }
 
+    if (font->font_name) {
+	cff_subset->font_name = strdup (font->font_name);
+	if (cff_subset->font_name == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto fail2;
+	}
+    } else {
+	cff_subset->font_name = NULL;
+    }
+
     cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
-    if (cff_subset->widths == NULL) {
+    if (unlikely (cff_subset->widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail2;
+	goto fail3;
     }
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
         cff_subset->widths[i] = font->widths[i];
 
     cff_subset->x_min = font->x_min;
     cff_subset->y_min = font->y_min;
     cff_subset->x_max = font->x_max;
     cff_subset->y_max = font->y_max;
     cff_subset->ascent = font->ascent;
     cff_subset->descent = font->descent;
 
     cff_subset->data = malloc (length);
-    if (cff_subset->data == NULL) {
+    if (unlikely (cff_subset->data == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail3;
+	goto fail4;
     }
 
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
 
     cairo_cff_font_destroy (font);
 
     return CAIRO_STATUS_SUCCESS;
 
- fail3:
+ fail4:
     free (cff_subset->widths);
+ fail3:
+    if (cff_subset->font_name)
+	free (cff_subset->font_name);
  fail2:
-    free (cff_subset->base_font);
+    free (cff_subset->ps_name);
  fail1:
     cairo_cff_font_destroy (font);
 
     return status;
 }
 
 void
 _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
 {
-    free (subset->base_font);
+    free (subset->ps_name);
+    if (subset->font_name)
+	free (subset->font_name);
     free (subset->widths);
     free (subset->data);
 }
 
 static cairo_int_status_t
 _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                                  cairo_cff_font_t           **font_return,
                                  const char                  *subset_name)
 {
     cairo_status_t status;
     cairo_cff_font_t *font;
 
     font = malloc (sizeof (cairo_cff_font_t));
-    if (font == NULL)
+    if (unlikely (font == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font->backend = NULL;
     font->scaled_font_subset = scaled_font_subset;
 
     _cairo_array_init (&font->output, sizeof (char));
     status = _cairo_array_grow_by (&font->output, 4096);
-    if (status)
+    if (unlikely (status))
 	goto fail1;
 
     font->subset_font_name = strdup (subset_name);
-    if (font->subset_font_name == NULL) {
+    if (unlikely (font->subset_font_name == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail1;
     }
 
-    font->font_name = strdup (subset_name);
-    if (font->subset_font_name == NULL) {
+    font->ps_name = strdup (subset_name);
+    if (unlikely (font->ps_name == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
     }
+    font->font_name = NULL;
 
     font->x_min = 0;
     font->y_min = 0;
     font->x_max = 0;
     font->y_max = 0;
     font->ascent = 0;
     font->descent = 0;
 
     font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
-    if (font->widths == NULL) {
+    if (unlikely (font->widths == NULL)) {
         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         goto fail3;
     }
 
     font->data_length = 0;
     font->data = NULL;
     font->data_end = NULL;
 
     status = cff_dict_init (&font->top_dict);
-    if (status)
+    if (unlikely (status))
 	goto fail4;
 
     status = cff_dict_init (&font->private_dict);
-    if (status)
+    if (unlikely (status))
 	goto fail5;
 
     cff_index_init (&font->strings_index);
     cff_index_init (&font->charstrings_index);
     cff_index_init (&font->global_sub_index);
     cff_index_init (&font->local_sub_index);
     cff_index_init (&font->charstrings_subset_index);
     cff_index_init (&font->strings_subset_index);
@@ -2109,17 +2082,19 @@ static cairo_int_status_t
 
     return CAIRO_STATUS_SUCCESS;
 
 fail5:
     _cairo_hash_table_destroy (font->top_dict);
 fail4:
     free (font->widths);
 fail3:
-    free (font->font_name);
+    if (font->font_name)
+	free (font->font_name);
+    free (font->ps_name);
 fail2:
     free (font->subset_font_name);
 fail1:
     _cairo_array_fini (&font->output);
     free (font);
     return status;
 }
 
@@ -2146,63 +2121,63 @@ cairo_cff_font_fallback_generate (cairo_
     /* Create Top Dict */
     font->is_cid = FALSE;
     end_buf = encode_integer (buf, type2_subset->x_min);
     end_buf = encode_integer (end_buf, type2_subset->y_min);
     end_buf = encode_integer (end_buf, type2_subset->x_max);
     end_buf = encode_integer (end_buf, type2_subset->y_max);
     status = cff_dict_set_operands (font->top_dict,
 	                            FONTBBOX_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     end_buf = encode_integer_max (buf, 0);
     status = cff_dict_set_operands (font->top_dict,
 	                            CHARSTRINGS_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            FDSELECT_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            FDARRAY_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cff_dict_set_operands (font->top_dict,
 	                            CHARSET_OP, buf, end_buf - buf);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = cairo_cff_font_set_ros_strings (font);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     /* Create CID FD dictionary */
     status = cairo_cff_font_create_cid_fontdict (font);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     /* Create charstrings */
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
         charstring = _cairo_array_index(&type2_subset->charstrings, i);
 
         status = cff_index_append (&font->charstrings_subset_index,
                                    _cairo_array_index (charstring, 0),
                                    _cairo_array_num_elements (charstring));
 
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     status = cairo_cff_font_write_subset (font);
-    if (status)
+    if (unlikely (status))
         return status;
 
     *data = _cairo_array_index (&font->output, 0);
     *length = _cairo_array_num_elements (&font->output);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -2214,76 +2189,78 @@ cairo_status_t
     cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
     cairo_status_t status;
     const char *data = NULL; /* squelch bogus compiler warning */
     unsigned long length = 0; /* squelch bogus compiler warning */
     unsigned int i;
     cairo_type2_charstrings_t type2_subset;
 
     status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
-    if (status)
+    if (unlikely (status))
 	goto fail1;
 
     status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
-    if (status)
+    if (unlikely (status))
 	goto fail2;
 
-    cff_subset->base_font = strdup (font->font_name);
-    if (cff_subset->base_font == NULL) {
+    cff_subset->font_name = NULL;
+    cff_subset->ps_name = strdup (font->ps_name);
+    if (unlikely (cff_subset->ps_name == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
     }
 
     cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
-    if (cff_subset->widths == NULL) {
+    if (unlikely (cff_subset->widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail3;
     }
+
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
         cff_subset->widths[i] = type2_subset.widths[i];
 
     cff_subset->x_min = type2_subset.x_min;
     cff_subset->y_min = type2_subset.y_min;
     cff_subset->x_max = type2_subset.x_max;
     cff_subset->y_max = type2_subset.y_max;
     cff_subset->ascent = type2_subset.y_max;
     cff_subset->descent = type2_subset.y_min;
 
     cff_subset->data = malloc (length);
-    if (cff_subset->data == NULL) {
+    if (unlikely (cff_subset->data == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail4;
     }
 
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
     cff_subset->data_length = length;
 
     _cairo_type2_charstrings_fini (&type2_subset);
     cairo_cff_font_destroy (font);
 
     return CAIRO_STATUS_SUCCESS;
 
  fail4:
     free (cff_subset->widths);
  fail3:
-    free (cff_subset->base_font);
+    free (cff_subset->ps_name);
  fail2:
     _cairo_type2_charstrings_fini (&type2_subset);
  fail1:
     cairo_cff_font_destroy (font);
 
     return status;
 }
 
 void
 _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
 {
-    free (subset->base_font);
+    free (subset->ps_name);
     free (subset->widths);
     free (subset->data);
 }
 
 #endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -44,17 +44,17 @@ static cairo_clip_path_t *
 _cairo_clip_path_reference (cairo_clip_path_t *clip_path);
 
 static void
 _cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
 
 void
 _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
 {
-    if (target)
+    if (target && target->backend)
 	clip->mode = _cairo_surface_get_clip_mode (target);
     else
 	clip->mode = CAIRO_CLIP_MODE_MASK;
 
     clip->all_clipped = FALSE;
 
     clip->surface = NULL;
     clip->surface_rect.x = 0;
@@ -83,17 +83,17 @@ cairo_status_t
     clip->serial = other->serial;
 
     _cairo_region_init (&clip->region);
 
     if (other->has_region) {
 	cairo_status_t status;
 
 	status = _cairo_region_copy (&clip->region, &other->region);
-	if (status) {
+	if (unlikely (status)) {
 	    _cairo_region_fini (&clip->region);
 	    cairo_surface_destroy (clip->surface);
 	    return status;
 	}
         clip->has_region = TRUE;
     } else {
         clip->has_region = FALSE;
     }
@@ -138,88 +138,62 @@ static void
 }
 
 
 static cairo_status_t
 _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
 				         cairo_rectangle_int_t   *rectangle)
 {
     while (clip_path) {
-        cairo_status_t status;
-        cairo_traps_t traps;
-        cairo_box_t extents;
-        cairo_rectangle_int_t extents_rect;
-
-	_cairo_box_from_rectangle (&extents, rectangle);
-
-        _cairo_traps_init (&traps);
-	_cairo_traps_limit (&traps, &extents);
+        cairo_rectangle_int_t extents;
 
-        status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
-                                                  clip_path->fill_rule,
-                                                  clip_path->tolerance,
-                                                  &traps);
-        if (status) {
-            _cairo_traps_fini (&traps);
-            return status;
-        }
+	_cairo_path_fixed_approximate_clip_extents (&clip_path->path, &extents);
 
-        _cairo_traps_extents (&traps, &extents);
-        _cairo_traps_fini (&traps);
-
-        _cairo_box_round_to_rectangle (&extents, &extents_rect);
-        _cairo_rectangle_intersect (rectangle, &extents_rect);
+        if (! _cairo_rectangle_intersect (rectangle, &extents))
+	    return CAIRO_STATUS_SUCCESS;
 
         clip_path = clip_path->prev;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
 				    cairo_rectangle_int_t *rectangle)
 {
+    cairo_status_t status;
+    cairo_bool_t is_empty;
+
     if (!clip)
 	return CAIRO_STATUS_SUCCESS;
 
     if (clip->all_clipped) {
 	*rectangle = clip->surface_rect;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     if (clip->path) {
-        cairo_status_t status;
-
         status = _cairo_clip_path_intersect_to_rectangle (clip->path,
                                                           rectangle);
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     if (clip->has_region) {
-	cairo_status_t status = CAIRO_STATUS_SUCCESS;
-	cairo_region_t intersection;
-
-	_cairo_region_init_rect (&intersection, rectangle);
-
-	status = _cairo_region_intersect (&intersection, &clip->region,
-					  &intersection);
+	cairo_rectangle_int_t extents;
 
-	if (!status)
-	    _cairo_region_get_extents (&intersection, rectangle);
-
-        _cairo_region_fini (&intersection);
-
-        if (status)
-            return status;
+	_cairo_region_get_extents (&clip->region, &extents);
+	is_empty = _cairo_rectangle_intersect (rectangle, &extents);
+	if (is_empty)
+	    return CAIRO_STATUS_SUCCESS;
     }
 
     if (clip->surface)
-	_cairo_rectangle_intersect (rectangle, &clip->surface_rect);
+	is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_clip_intersect_to_region (cairo_clip_t      *clip,
 				 cairo_region_t *region)
 {
@@ -241,30 +215,30 @@ cairo_status_t
     }
 
     if (clip->path) {
 	/* Intersect clip path into region. */
     }
 
     if (clip->has_region) {
 	status = _cairo_region_intersect (region, &clip->region, region);
-	if (status)
+	if (unlikely (status))
 	    return status;
     }
 
     if (clip->surface) {
 	cairo_region_t clip_rect;
 
 	_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
 
 	status = _cairo_region_intersect (region, &clip_rect, region);
 
 	_cairo_region_fini (&clip_rect);
 
-        if (status)
+        if (unlikely (status))
             return status;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Combines the region of clip->surface given by extents in
  * device backend coordinates into the given temporary surface,
@@ -311,21 +285,21 @@ static cairo_status_t
 {
     cairo_clip_path_t *clip_path;
     cairo_status_t status;
 
     if (clip->mode != CAIRO_CLIP_MODE_PATH)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     clip_path = malloc (sizeof (cairo_clip_path_t));
-    if (clip_path == NULL)
+    if (unlikely (clip_path == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     status = _cairo_path_fixed_init_copy (&clip_path->path, path);
-    if (status) {
+    if (unlikely (status)) {
 	free (clip_path);
 	return status;
     }
 
     CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
     clip_path->fill_rule = fill_rule;
     clip_path->tolerance = tolerance;
     clip_path->antialias = antialias;
@@ -375,17 +349,16 @@ static cairo_int_status_t
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
     if (clip->mode != CAIRO_CLIP_MODE_REGION)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     status = _cairo_traps_extract_region (traps, &region);
-
     if (status)
 	return status;
 
     if (!clip->has_region) {
         status = _cairo_region_copy (&clip->region, &region);
 	if (status == CAIRO_STATUS_SUCCESS)
 	    clip->has_region = TRUE;
     } else {
@@ -416,45 +389,44 @@ static cairo_status_t
 _cairo_clip_intersect_mask (cairo_clip_t      *clip,
 			    cairo_traps_t     *traps,
 			    cairo_antialias_t antialias,
 			    cairo_surface_t   *target)
 {
     cairo_pattern_union_t pattern;
     cairo_box_t extents;
     cairo_rectangle_int_t surface_rect, target_rect;
-    cairo_surface_t *surface;
-    cairo_status_t status;
+    cairo_surface_t *surface = NULL;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
     /* Represent the clip as a mask surface.  We create a new surface
      * the size of the intersection of the old mask surface and the
      * extents of the new clip path. */
 
     _cairo_traps_extents (traps, &extents);
     _cairo_box_round_to_rectangle (&extents, &surface_rect);
 
-    if (clip->surface != NULL)
-	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);
+    if (clip->surface != NULL) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	    goto DONE;
+    }
 
     /* Intersect with the target surface rectangle so we don't use
      * more memory and time than we need to. */
     status = _cairo_surface_get_extents (target, &target_rect);
-    if (status == CAIRO_STATUS_SUCCESS)
-	_cairo_rectangle_intersect (&surface_rect, &target_rect);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &target_rect))
+	    goto DONE;
+    }
 
-    if (surface_rect.width == 0 || surface_rect.height == 0) {
-	surface = NULL;
-	status = CAIRO_STATUS_SUCCESS;
-	if (clip->surface != NULL)
-	    cairo_surface_destroy (clip->surface);
+    if (surface_rect.width == 0 || surface_rect.height == 0)
 	goto DONE;
-    }
 
     _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
 			       CAIRO_CONTENT_COLOR);
     /* The clipping operation should ideally be something like the following to
      * avoid having to do as many passes over the data
 
 	if (clip->surface != NULL) {
 	    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
@@ -473,19 +445,20 @@ static cairo_status_t
 						  traps->traps,
 						  traps->num_traps);
 
 	However this operation is not accelerated by pixman
 
 	I believe the best possible operation would probably an unbounded SRC
 	operator.  Using SRC we could potentially avoid having to initialize
 	the surface which would be ideal from an efficiency point of view.
-	However, _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) is
-	bounded by the mask.
-
+	However, CAIRO_OPERATOR_SOURCE is bounded by the trapezoid mask and
+	_cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) will assert
+	because it assumes CAIRO_OPERATOR_SOURCE has been converted into other
+	operations.
     */
 
     surface = _cairo_surface_create_similar_solid (target,
 						   CAIRO_CONTENT_ALPHA,
 						   surface_rect.width,
 						   surface_rect.height,
 						   CAIRO_COLOR_TRANSPARENT);
     if (surface->status) {
@@ -505,17 +478,17 @@ static cairo_status_t
 						  0, 0,
 						  surface_rect.width,
 						  surface_rect.height,
 						  traps->traps,
 						  traps->num_traps);
 
     _cairo_pattern_fini (&pattern.base);
 
-    if (status) {
+    if (unlikely (status)) {
 	cairo_surface_destroy (surface);
 	return status;
     }
 
     /* If there was a clip surface already, combine it with the new
      * mask surface using the IN operator, so we get the intersection
      * of the old and new clipping paths. */
 
@@ -530,46 +503,174 @@ static cairo_status_t
 					   surface_rect.y - clip->surface_rect.y,
 					   0, 0,
 					   0, 0,
 					   surface_rect.width,
 					   surface_rect.height);
 
 	_cairo_pattern_fini (&pattern.base);
 
-	if (status) {
+	if (unlikely (status)) {
 	    cairo_surface_destroy (surface);
 	    return status;
 	}
-
-	cairo_surface_destroy (clip->surface);
     }
 
  DONE:
+    cairo_surface_destroy (clip->surface);
     clip->surface = surface;
     clip->surface_rect = surface_rect;
     clip->serial = _cairo_surface_allocate_clip_serial (target);
 
     if (surface_rect.width == 0 || surface_rect.height == 0)
 	_cairo_clip_set_all_clipped (clip, target);
 
     return status;
 }
 
+static cairo_status_t
+_cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
+					cairo_path_fixed_t *path,
+					cairo_fill_rule_t   fill_rule,
+					double		    tolerance,
+					cairo_antialias_t   antialias,
+					cairo_surface_t    *target)
+{
+    cairo_span_renderer_t *renderer = NULL;
+    cairo_pattern_union_t pattern;
+    cairo_rectangle_int_t surface_rect;
+    cairo_surface_t *surface = NULL;
+    cairo_status_t status;
+    cairo_operator_t op;
+    cairo_composite_rectangles_t rects;
+
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
+    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+			       CAIRO_CONTENT_COLOR);
+
+    /* If we have a clip surface we're going to use IN to combine our
+     * new clip with the old clip.  The ADD is done to a transparent
+     * surface, as that's a fast way of doing it currently.  We should
+     * really be using SOURCE instead, but _cairo_surface_composite()
+     * checks that it's not called with SOURCE or DEST. */
+    op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;
+
+    /* Test if the target can composite spans.  We're going to assume
+     * this is a good indicator of whether a similar surface is going
+     * to be able to composite spans too. */
+    if ( !_cairo_surface_check_span_renderer (op,
+					      &pattern.base,
+					      target,
+					      antialias,
+					      NULL))
+    {
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	goto BAIL;
+    }
+
+    status = _cairo_surface_get_extents (target, &surface_rect);
+    if (status)
+	goto BAIL;
+
+    /* We'll create a new surface the size of the intersection of the
+     * old mask surface and the extents of the new clip path. */
+    {
+	cairo_rectangle_int_t extents;
+
+	_cairo_path_fixed_approximate_clip_extents (path, &extents);
+	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
+	    goto SUCCESS;
+
+	if (clip->surface != NULL &&
+	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	    goto SUCCESS;
+    }
+
+    /* Make the new mask surface and optionally initialise it from the
+     * previous clip if we have one. */
+    surface = _cairo_surface_create_similar_solid (target,
+						   CAIRO_CONTENT_ALPHA,
+						   surface_rect.width,
+						   surface_rect.height,
+						   CAIRO_COLOR_TRANSPARENT);
+    if (surface->status) {
+	_cairo_pattern_fini (&pattern.base);
+	return surface->status;
+    }
+
+    if (clip->surface) {
+	cairo_surface_pattern_t old_clip;
+	_cairo_pattern_init_for_surface (&old_clip, clip->surface);
+	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+					   &old_clip.base,
+					   NULL,
+					   surface,
+					   surface_rect.x - clip->surface_rect.x,
+					   surface_rect.y - clip->surface_rect.y,
+					   0, 0,
+					   0, 0,
+					   surface_rect.width,
+					   surface_rect.height);
+	_cairo_pattern_fini (&old_clip.base);
+	if (status)
+	    goto BAIL;
+    }
+
+    _cairo_composite_rectangles_init (&rects,
+				      surface_rect.x,
+				      surface_rect.y,
+				      surface_rect.width,
+				      surface_rect.height);
+    rects.dst.x = 0;
+    rects.dst.y = 0;
+
+    /* Render the new clipping path into the new mask surface. We've
+     * chosen op to either combine the new clip path with the existing
+     * clip mask (if there is one) or just render it. */
+    status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
+						path, surface,
+						fill_rule, tolerance,
+						antialias, &rects);
+    if (status)
+	goto BAIL;
+
+ SUCCESS:
+    if (clip->surface != NULL)
+	cairo_surface_destroy (clip->surface);
+    clip->surface = surface;
+    clip->surface_rect = surface_rect;
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
+    surface = NULL;
+
+    if (surface_rect.width == 0 || surface_rect.height == 0)
+	_cairo_clip_set_all_clipped (clip, target);
+
+ BAIL:
+    if (renderer)
+	renderer->destroy(renderer);
+    if (surface)
+	cairo_surface_destroy (surface);
+    _cairo_pattern_fini (&pattern.base);
+    return status;
+}
+
 cairo_status_t
 _cairo_clip_clip (cairo_clip_t       *clip,
 		  cairo_path_fixed_t *path,
 		  cairo_fill_rule_t   fill_rule,
 		  double              tolerance,
 		  cairo_antialias_t   antialias,
 		  cairo_surface_t    *target)
 {
     cairo_status_t status;
     cairo_rectangle_int_t rectangle;
     cairo_traps_t traps;
+    cairo_box_t ignored_box;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
     /* catch the empty clip path */
     if (! path->has_current_point) {
 	_cairo_clip_set_all_clipped (clip, target);
 	return CAIRO_STATUS_SUCCESS;
@@ -579,33 +680,45 @@ cairo_status_t
 					 path, fill_rule, tolerance,
 					 antialias);
     if (status == CAIRO_STATUS_SUCCESS)
         clip->serial = _cairo_surface_allocate_clip_serial (target);
 
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
+    /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter
+     * again. */
+    if (antialias != CAIRO_ANTIALIAS_NONE &&
+	!_cairo_path_fixed_is_box (path, &ignored_box) &&
+	!_cairo_path_fixed_is_region (path))
+    {
+	status = _cairo_clip_intersect_mask_using_spans (
+	    clip, path, fill_rule, tolerance, antialias, target);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
+
     _cairo_traps_init (&traps);
 
     /* Limit the traps to the target surface
      * - so we don't add more traps than needed. */
     status = _cairo_surface_get_extents (target, &rectangle);
     if (status == CAIRO_STATUS_SUCCESS) {
 	cairo_box_t box;
 
 	_cairo_box_from_rectangle (&box, &rectangle);
 	_cairo_traps_limit (&traps, &box);
     }
 
     status = _cairo_path_fixed_fill_to_traps (path,
 					      fill_rule,
 					      tolerance,
 					      &traps);
-    if (status)
+    if (unlikely (status))
 	goto bail;
 
     status = _cairo_clip_intersect_region (clip, &traps, target);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	goto bail;
 
     status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);
 
@@ -652,17 +765,17 @@ void
 static cairo_status_t
 _cairo_clip_path_reapply_clip_path (cairo_clip_t      *clip,
                                     cairo_clip_path_t *clip_path)
 {
     cairo_status_t status;
 
     if (clip_path->prev) {
         status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev);
-	if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	if (_cairo_status_is_error (status))
 	    return status;
     }
 
     return _cairo_clip_intersect_path (clip,
                                        &clip_path->path,
 				       clip_path->fill_rule,
 				       clip_path->tolerance,
 				       clip_path->antialias);
@@ -678,44 +791,44 @@ cairo_status_t
     _cairo_clip_init (clip, target);
 
     if (other->mode != clip->mode) {
         /* We should reapply the original clip path in this case, and let
          * whatever the right handling is happen */
     } else {
         if (other->has_region) {
             status = _cairo_region_copy (&clip->region, &other->region);
-	    if (status)
+	    if (unlikely (status))
 		goto BAIL;
 
 	    clip->has_region = TRUE;
         }
 
         if (other->surface) {
 	    int dx, dy;
             status = _cairo_surface_clone_similar (target, other->surface,
 					           0,
 						   0,
 						   other->surface_rect.width,
 						   other->surface_rect.height,
 						   &dx, &dy,
 						   &clip->surface);
-	    if (status)
+	    if (unlikely (status))
 		goto BAIL;
 
             clip->surface_rect = other->surface_rect;
 
 	    /* src offset was 0, so we expect an exact replica of the surface */
 	    assert (dx == 0);
 	    assert (dy == 0);
         }
 
         if (other->path) {
             status = _cairo_clip_path_reapply_clip_path (clip, other->path);
-	    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    if (_cairo_status_is_error (status))
 		goto BAIL;
         }
     }
 
     return CAIRO_STATUS_SUCCESS;
 
 BAIL:
     if (clip->has_region)
@@ -735,20 +848,22 @@ static cairo_bool_t
 _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
 			      cairo_rectangle_int_t *clip_rect,
 			      cairo_rectangle_t *user_rect)
 {
     cairo_bool_t is_tight;
 
     double x1 = clip_rect->x;
     double y1 = clip_rect->y;
-    double x2 = clip_rect->x + clip_rect->width;
-    double y2 = clip_rect->y + clip_rect->height;
+    double x2 = clip_rect->x + (int) clip_rect->width;
+    double y2 = clip_rect->y + (int) clip_rect->height;
 
-    _cairo_gstate_backend_to_user_rectangle (gstate, &x1, &y1, &x2, &y2, &is_tight);
+    _cairo_gstate_backend_to_user_rectangle (gstate,
+					     &x1, &y1, &x2, &y2,
+					     &is_tight);
 
     user_rect->x = x1;
     user_rect->y = y1;
     user_rect->width  = x2 - x1;
     user_rect->height = y2 - y1;
 
     return is_tight;
 }
@@ -764,71 +879,68 @@ cairo_rectangle_list_t *
 	goto DONE;
 
     if (clip->path || clip->surface) {
 	_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
     }
 
     if (clip->has_region) {
-	cairo_box_int_t *boxes;
         int i;
 
-	if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes))
-	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+	n_boxes = _cairo_region_num_boxes (&clip->region);
 
 	if (n_boxes) {
 	    rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
-	    if (rectangles == NULL) {
-		_cairo_region_boxes_fini (&clip->region, boxes);
+	    if (unlikely (rectangles == NULL)) {
 		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 		return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
 	    }
 
 	    for (i = 0; i < n_boxes; ++i) {
-               cairo_rectangle_int_t clip_rect;
+		cairo_box_int_t box;
+		cairo_rectangle_int_t clip_rect;
+
+		_cairo_region_get_box (&clip->region, i, &box);
 
-               clip_rect.x = boxes[i].p1.x;
-               clip_rect.y = boxes[i].p1.y;
-               clip_rect.width  = boxes[i].p2.x - boxes[i].p1.x;
-               clip_rect.height = boxes[i].p2.y - boxes[i].p1.y;
-
+		clip_rect.x = box.p1.x;
+		clip_rect.y = box.p1.y;
+		clip_rect.width  = box.p2.x - box.p1.x;
+		clip_rect.height = box.p2.y - box.p1.y;
+		
 		if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
 		    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
-		    _cairo_region_boxes_fini (&clip->region, boxes);
 		    free (rectangles);
 		    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 		}
 	    }
 	}
-
-	_cairo_region_boxes_fini (&clip->region, boxes);
     } else {
         cairo_rectangle_int_t extents;
 
 	n_boxes = 1;
 
 	rectangles = malloc(sizeof (cairo_rectangle_t));
-	if (rectangles == NULL) {
+	if (unlikely (rectangles == NULL)) {
 	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
 	}
 
 	if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) ||
 	    !_cairo_clip_int_rect_to_user(gstate, &extents, rectangles))
 	{
 	    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 	    free (rectangles);
 	    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 	}
     }
 
  DONE:
     list = malloc (sizeof (cairo_rectangle_list_t));
-    if (list == NULL) {
+    if (unlikely (list == NULL)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         free (rectangles);
         return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
     }
 
     list->status = CAIRO_STATUS_SUCCESS;
     list->rectangles = rectangles;
     list->num_rectangles = n_boxes;
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-combsort-private.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * 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 Chris Wilson
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+/* This fragment implements a comb sort (specifically combsort11) */
+#ifndef _HAVE_CAIRO_COMBSORT_NEWGAP
+#define _HAVE_CAIRO_COMBSORT_NEWGAP
+static inline unsigned int
+_cairo_combsort_newgap (unsigned int gap)
+{
+  gap = 10 * gap / 13;
+  if (gap == 9 || gap == 10)
+    gap = 11;
+  if (gap < 1)
+    gap = 1;
+  return gap;
+}
+#endif
+
+#define CAIRO_COMBSORT_DECLARE(NAME, TYPE, CMP) \
+static void \
+NAME (TYPE *base, unsigned int nmemb) \
+{ \
+  unsigned int gap = nmemb; \
+  unsigned int i, j; \
+  int swapped; \
+  do { \
+      gap = _cairo_combsort_newgap (gap); \
+      swapped = 0; \
+      for (i = 0; i < nmemb-gap ; i++) { \
+	  j = i + gap; \
+	  if (CMP (base[i], base[j]) > 0 ) { \
+	      TYPE tmp; \
+	      tmp = base[i]; \
+	      base[i] = base[j]; \
+	      base[j] = tmp; \
+	      swapped = 1; \
+	  } \
+      } \
+  } while (gap > 1 || swapped); \
+}
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -134,29 +134,71 @@
 #if __GNUC__ >= 3
 #define cairo_pure __attribute__((pure))
 #define cairo_const __attribute__((const))
 #else
 #define cairo_pure
 #define cairo_const
 #endif
 
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _CAIRO_BOOLEAN_EXPR(expr)                   \
+ __extension__ ({                               \
+   int _cairo_boolean_var_;                         \
+   if (expr)                                    \
+      _cairo_boolean_var_ = 1;                      \
+   else                                         \
+      _cairo_boolean_var_ = 0;                      \
+   _cairo_boolean_var_;                             \
+})
+#define likely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 1))
+#define unlikely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
 #ifndef __GNUC__
 #undef __attribute__
 #define __attribute__(x)
 #endif
 
 #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
 #define snprintf _snprintf
 #define popen _popen
+#define pclose _pclose
 #endif
 
 #ifdef _MSC_VER
 #undef inline
 #define inline __inline
 #endif
 
+#ifdef _MSC_VER
+/* When compiling with /Gy and /OPT:ICF identical functions will be folded in together.
+   The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and
+   will never be folded into another one. Something like this might eventually
+   be needed for GCC but it seems fine for now. */
+#define CAIRO_ENSURE_UNIQUE                       \
+    do {                                          \
+	char func[] = __FUNCTION__;               \
+	char file[] = __FILE__;                   \
+	__asm {                                   \
+	    __asm jmp __internal_skip_line_no     \
+	    __asm _emit (__LINE__ & 0xff)         \
+	    __asm _emit ((__LINE__>>8) & 0xff)    \
+	    __asm _emit ((__LINE__>>16) & 0xff)   \
+	    __asm _emit ((__LINE__>>24) & 0xff)   \
+	    __asm lea eax, func                   \
+	    __asm lea eax, file                   \
+	    __asm __internal_skip_line_no:        \
+	};                                        \
+    } while (0)
+#else
+#define CAIRO_ENSURE_UNIQUE    do { } while (0)
+#endif
+
 #ifdef __STRICT_ANSI__
 #undef inline
 #define inline __inline__
 #endif
 
 #endif
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -56,20 +56,24 @@
  * 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_face_reset_static_data ();
+    _cairo_scaled_font_map_destroy ();
+
+    _cairo_toy_font_face_reset_static_data ();
 
 #if CAIRO_HAS_FT_FONT
     _cairo_ft_font_reset_static_data ();
 #endif
 
+    _cairo_intern_string_reset_static_data ();
+
     _cairo_scaled_font_reset_static_data ();
 
     _cairo_pattern_reset_static_data ();
 
     CAIRO_MUTEX_FINALIZE ();
 }
--- a/gfx/cairo/cairo/src/cairo-deflate-stream.c
+++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c
@@ -116,23 +116,24 @@ cairo_output_stream_t *
 _cairo_deflate_stream_create (cairo_output_stream_t *output)
 {
     cairo_deflate_stream_t *stream;
 
     if (output->status)
 	return _cairo_output_stream_create_in_error (output->status);
 
     stream = malloc (sizeof (cairo_deflate_stream_t));
-    if (stream == NULL) {
+    if (unlikely (stream == NULL)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
     }
 
     _cairo_output_stream_init (&stream->base,
 			       _cairo_deflate_stream_write,
+			       NULL,
 			       _cairo_deflate_stream_close);
     stream->output = output;
 
     stream->zlib_stream.zalloc = Z_NULL;
     stream->zlib_stream.zfree  = Z_NULL;
     stream->zlib_stream.opaque  = Z_NULL;
 
     if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -450,17 +450,17 @@ static cairo_surface_t *
                 "%s( src=%p, content=0x%x, width=%d, height=%d).\n",
                 __FUNCTION__, source, content, width, height);
 
     width = (width <= 0) ? 1 : width;
     height = (height<= 0) ? 1 : height;
 
     format = _cairo_format_from_content (content);
     surface = calloc (1, sizeof (cairo_directfb_surface_t));
-    if (surface == NULL)
+    if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     surface->dfb = source->dfb;
 
     if (width < 8 || height < 8) {
         IDirectFBSurface *tmp;
 	DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
 
@@ -544,16 +544,17 @@ static cairo_status_t
 				      NULL, image_extra, DSLF_READ);
 }
 
 static void
 _cairo_directfb_surface_release_source_image (void                  *abstract_surface,
                                               cairo_image_surface_t *image,
                                               void                  *image_extra)
 {
+    cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra;
 
     D_DEBUG_AT (CairoDFB_Acquire,
 		"%s( surface=%p ).\n", __FUNCTION__, surface);
 
     buffer->Unlock (buffer);
 
     cairo_surface_destroy (&image->base);
@@ -697,18 +698,18 @@ static cairo_status_t
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
-                             cairo_pattern_t             *src_pattern,
-                             cairo_pattern_t             *mask_pattern,
+                             const cairo_pattern_t       *src_pattern,
+                             const cairo_pattern_t       *mask_pattern,
                              cairo_operator_t             op,
                              int *src_x,             int *src_y,
                              int *mask_x,            int *mask_y,
                              unsigned int                 width,
                              unsigned int                 height,
                              cairo_directfb_surface_t   **ret_src,
                              cairo_surface_attributes_t  *ret_src_attr)
 {
@@ -727,17 +728,17 @@ static cairo_int_status_t
     if (! _directfb_get_operator (op, &sblend, &dblend))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (mask_pattern) {
 	cairo_solid_pattern_t *pattern;
 
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
-	    cairo_pattern_t *tmp;
+	    const cairo_pattern_t *tmp;
 	    int              tmp_x, tmp_y;
 
 	    if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
 		sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	    D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
 
@@ -756,21 +757,16 @@ static cairo_int_status_t
 	    }
 	}
 
 	color = &((cairo_solid_pattern_t *) mask_pattern)->color;
     } else {
 	color = _cairo_stock_color (CAIRO_STOCK_WHITE);
     }
 
-    /* XXX DirectFB currently does not support filtering, so force NEAREST
-     * in order to hit optimisations inside core.
-    */
-    src_pattern->filter = CAIRO_FILTER_NEAREST;
-
     status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
 					     *src_x, *src_y, width, height,
 					     (cairo_surface_t **) &src,
 					     &src_attr);
     if (status)
 	return status;
 
     if (src->base.backend != &_cairo_directfb_surface_backend ||
@@ -837,17 +833,17 @@ static cairo_int_status_t
     *ret_src = src;
     *ret_src_attr = src_attr;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _directfb_finish_composite (cairo_directfb_surface_t   *dst,
-                            cairo_pattern_t            *src_pattern,
+                            const cairo_pattern_t      *src_pattern,
                             cairo_surface_t            *src,
                             cairo_surface_attributes_t *src_attr)
 {
     _cairo_pattern_release_surface (src_pattern, src, src_attr);
 }
 #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
 
 #if DFB_COMPOSITE
@@ -887,18 +883,18 @@ static DFBAccelerationMask
     case CAIRO_EXTEND_REFLECT:
     case CAIRO_EXTEND_PAD:
 	return DFXL_NONE;
     }
 }
 
 static cairo_int_status_t
 _cairo_directfb_surface_composite (cairo_operator_t  op,
-                                   cairo_pattern_t  *src_pattern,
-                                   cairo_pattern_t  *mask_pattern,
+                                   const cairo_pattern_t  *src_pattern,
+                                   const cairo_pattern_t  *mask_pattern,
                                    void             *abstract_dst,
                                    int  src_x,  int  src_y,
                                    int  mask_x, int  mask_y,
                                    int  dst_x,  int  dst_y,
                                    unsigned int      width,
                                    unsigned int      height)
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
@@ -1155,17 +1151,17 @@ static cairo_int_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 #endif
 
 #if DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t   op,
-                                              cairo_pattern_t   *pattern,
+                                              const cairo_pattern_t   *pattern,
                                               void              *abstract_dst,
                                               cairo_antialias_t  antialias,
                                               int  src_x,   int  src_y,
                                               int  dst_x,   int  dst_y,
                                               unsigned int       width,
                                               unsigned int       height,
                                               cairo_trapezoid_t *traps,
                                               int                num_traps)
@@ -1298,51 +1294,50 @@ static cairo_int_status_t
 {
     cairo_directfb_surface_t *surface = abstract_surface;
 
     D_DEBUG_AT (CairoDFB_Clip,
 		"%s( surface=%p, region=%p ).\n",
 		__FUNCTION__, surface, region);
 
     if (region) {
-	cairo_box_int_t *boxes;
 	int              n_boxes;
 	cairo_status_t   status;
 	int              i;
 
 	surface->has_clip = TRUE;
 
-	status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
+	n_boxes = _cairo_region_num_boxes (region);
+
 	if (n_boxes == 0)
 	    return CAIRO_STATUS_SUCCESS;
-	if (status)
-	    return status;
 
 	if (surface->n_clips != n_boxes) {
 	    if (surface->clips)
 		free (surface->clips);
 
 	    surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion));
 	    if (!surface->clips) {
 		surface->n_clips = 0;
-		_cairo_region_boxes_fini (region, boxes);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 
 	    surface->n_clips = n_boxes;
 	}
 
 	for (i = 0; i < n_boxes; i++) {
-	    surface->clips[i].x1 = boxes[i].p1.x;
-	    surface->clips[i].y1 = boxes[i].p1.y;
-	    surface->clips[i].x2 = boxes[i].p2.x - 1;
-	    surface->clips[i].y2 = boxes[i].p2.y - 1;
+	    cairo_box_int_t box;
+
+	    _cairo_region_get_box (region, i, &box);
+	    
+	    surface->clips[i].x1 = box.p1.x;
+	    surface->clips[i].y1 = box.p1.y;
+	    surface->clips[i].x2 = box.p2.x - 1;
+	    surface->clips[i].y2 = box.p2.y - 1;
 	}
-
-	_cairo_region_boxes_fini (region, boxes);
     } else {
 	surface->has_clip = FALSE;
 	if (surface->clips) {
 	    free (surface->clips);
 	    surface->clips = NULL;
 	    surface->n_clips = 0;
 	}
     }
@@ -1427,17 +1422,17 @@ static cairo_status_t
     int                          x         = 0;
     int                          y         = 0;
     int                          w         = 8;
     int                          h         = 8;
     int                          i;
 
     D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs );
 
-    _cairo_cache_freeze (scaled_font->glyphs);
+    _cairo_scaled_font_freeze_cache (scaled_font);
 
     if (scaled_font->surface_private) {
 	cache = scaled_font->surface_private;
 	x = cache->x;
 	y = cache->y;
     }
 
     for (i = 0; i < num_glyphs; i++) {
@@ -1445,30 +1440,30 @@ static cairo_status_t
 	cairo_image_surface_t *img;
 
 	D_DEBUG_AT (CairoDFB_Font, "  -> [%2d] = %4lu\n", i, glyphs[i].index );
 
 	status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
 					  CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					  &scaled_glyph);
 	if (status) {
-	    _cairo_cache_thaw (scaled_font->glyphs);
+	    _cairo_scaled_font_thaw_cache (scaled_font);
 	    return status;
 	}
 
 	img = scaled_glyph->surface;
 	switch (img->format) {
 	case CAIRO_FORMAT_A1:
 	case CAIRO_FORMAT_A8:
 	case CAIRO_FORMAT_ARGB32:
 	    break;
 	default:
 	    D_DEBUG_AT (CairoDFB_Font,
 			"  -> Unsupported font format %d!\n", img->format);
-	    _cairo_cache_thaw (scaled_font->glyphs);
+	    _cairo_scaled_font_thaw_cache (scaled_font);
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
 
 	points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0);
 	points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0);
 
 	//        D_DEBUG_AT (CairoDFB_Font, "            (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
 
@@ -1496,17 +1491,17 @@ static cairo_status_t
 
 	    x += img->width;
 	    h  = MAX (h, img->height);
 	    w  = MAX (w, x);
 
 	    /* Remember glyph location */
 	    rect = malloc (sizeof (DFBRectangle));
 	    if (rect == NULL) {
-		_cairo_cache_thaw (scaled_font->glyphs);
+		_cairo_scaled_font_thaw_cache (scaled_font);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 	    *rect = rects[n];
 
 	    scaled_glyph->surface_private = rect;
 	    chars[num_chars++] = scaled_glyph;
 
 	    D_DEBUG_AT (CairoDFB_Font, "  -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
@@ -1516,74 +1511,74 @@ static cairo_status_t
 
 	    D_DEBUG_AT (CairoDFB_Font, "  -> exists at  %4d,%2d\n", rects[n].x, rects[n].y);
 	}
 
 	n++;
     }
 
     if (n == 0) {
-	_cairo_cache_thaw (scaled_font->glyphs);
+	_cairo_scaled_font_thaw_cache (scaled_font);
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
     }
 
     h += y;
     w = MAX (w, 8);
     h = MAX (h, 8);
 
     /* XXX query maximum surface size */
     if (w > 2048 || h > 2048) {
-	_cairo_cache_thaw (scaled_font->glyphs);
+	_cairo_scaled_font_thaw_cache (scaled_font);
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     if (cache) {
 	if (cache->width < w || cache->height < h) {
 	    cairo_directfb_font_cache_t *new_cache;
 
 	    w = MAX (w, cache->width);
 	    h = MAX (h, cache->height);
 
 	    D_DEBUG_AT (CairoDFB_Font, "  -> Reallocating font cache (%dx%d).\n", w, h);
 
 	    status = _directfb_allocate_font_cache (surface->dfb,
 						    w, h,
 						    &new_cache);
 	    if (status) {
-		_cairo_cache_thaw (scaled_font->glyphs);
+		_cairo_scaled_font_thaw_cache (scaled_font);
 		return status;
 	    }
 
 	    new_cache->dfbsurface->Blit (new_cache->dfbsurface,
 					 cache->dfbsurface, NULL, 0, 0);
 
 	    _directfb_destroy_font_cache (cache);
 	    scaled_font->surface_private = cache = new_cache;
 	}
     } else {
 	D_DEBUG_AT (CairoDFB_Font, "  -> Allocating font cache (%dx%d).\n", w, h);
 
 	status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache);
 	if (status) {
-	    _cairo_cache_thaw (scaled_font->glyphs);
+	    _cairo_scaled_font_thaw_cache (scaled_font);
 	    return status;
 	}
 
 	scaled_font->surface_backend = &_cairo_directfb_surface_backend;
 	scaled_font->surface_private = cache;
     }
 
     if (num_chars) {
 	unsigned char *data;
 	int            pitch;
 
 	if (cache->dfbsurface->Lock (cache->dfbsurface,
 				     DSLF_WRITE, (void *)&data, &pitch))
 	{
-	    _cairo_cache_thaw (scaled_font->glyphs);
+	    _cairo_scaled_font_thaw_cache (scaled_font);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
 
 	D_DEBUG_AT (CairoDFB_Font, "  => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height);
 
 	for (i = 0; i < num_chars; i++) {
 	    cairo_image_surface_t *img  = chars[i]->surface;
 	    DFBRectangle          *rect = chars[i]->surface_private;
@@ -1639,17 +1634,17 @@ static cairo_status_t
 		    src += img->stride;
 		}
 	    }
 	}
 
 	cache->dfbsurface->Unlock (cache->dfbsurface);
     }
 
-    _cairo_cache_thaw (scaled_font->glyphs);
+    _cairo_scaled_font_thaw_cache (scaled_font);
 
     cache->x = x;
     cache->y = y;
 
     D_DEBUG_AT (CairoDFB_Font, "  => cache %d,%d, %p [%d]\n", x, y, cache, n);
 
     *ret_cache = cache;
     *ret_num   = n;
@@ -1681,23 +1676,24 @@ static void
 
      if (scaled_glyph->surface_private != NULL) {
           free (scaled_glyph->surface_private);
           scaled_glyph->surface_private = NULL;
      }
 }
 
 static cairo_int_status_t
-_cairo_directfb_surface_show_glyphs (void                *abstract_dst,
-                                     cairo_operator_t     op,
-                                     cairo_pattern_t     *pattern,
-                                     cairo_glyph_t       *glyphs,
-                                     int                  num_glyphs,
-                                     cairo_scaled_font_t *scaled_font,
-				     int		 *remaining_glyphs)
+_cairo_directfb_surface_show_glyphs (void		    *abstract_dst,
+                                     cairo_operator_t	     op,
+                                     const cairo_pattern_t  *pattern,
+                                     cairo_glyph_t	    *glyphs,
+                                     int		     num_glyphs,
+                                     cairo_scaled_font_t    *scaled_font,
+				     int		    *remaining_glyphs,
+				     cairo_rectangle_int_t  *extents)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
     cairo_status_t               status;
     DFBSurfaceBlittingFlags      flags;
     DFBSurfaceBlendFunction      sblend;
     DFBSurfaceBlendFunction      dblend;
     DFBRectangle                 rects[num_glyphs];
@@ -1812,16 +1808,18 @@ static cairo_surface_backend_t
 #else
         NULL,/*fill_rectangles*/
 #endif
 #if DFB_COMPOSITE_TRAPEZOIDS
         _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
 #else
         NULL,/*composite_trapezoids*/
 #endif
+        NULL, /* create_span_renderer */
+        NULL, /* check_span_renderer */
         NULL, /* copy_page */
         NULL, /* show_page */
         _cairo_directfb_surface_set_clip_region,/* set_clip_region */
         NULL, /* intersect_clip_path */
         _cairo_directfb_abstract_surface_get_extents,/* get_extents */
         NULL, /* old_show_glyphs */
         NULL, /* get_font_options */
         NULL, /* flush */
--- a/gfx/cairo/cairo/src/cairo-font-face-twin-data.c
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin-data.c
@@ -1,49 +1,55 @@
 /* See cairo-font-face-twin.c for copyright info */
 
 #include "cairoint.h"
 
 const int8_t _cairo_twin_outlines[] = {
 /* 0x0 '\0'  offset 0 */
-    0, 24, 42, 0, 2, 4,
+    0, 24, 42, 0, 2, 2,
     0, 24, /* snap_x */
-    -42, -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 24, -42,
     'l', 24, 0,
     'l', 0, 0,
     'e',
+    'X', 'X',
 /* 0x20 ' '  offset 28 */
-    0, 4, 0, 0, 2, 3,
-    -128, 0, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    0, 4, 0, 0, 0, 0,
+    /* snap_x */
+    /* snap_y */
     'e',
+    'X', 'X', 'X',
+    'X', 'X',
 /* 0x21 '!'  offset 40 */
-    0, 4, 42, 0, 3, 3,
-    0, 2, 4, /* snap_x */
-    -21, -15, 0, /* snap_y */
-    'm', 2, -42,
-    'l', 2, -14,
-    'm', 2, -4,
-    'c', 1, -4, 0, -3, 0, -2,
-    'c', 0, -1, 1, 0, 2, 0,
-    'c', 3, 0, 4, -1, 4, -2,
-    'c', 4, -3, 3, -4, 2, -4,
+    0, 0, 42, 0, 1, 3,
+    0, /* snap_x */
+    -42, -14, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, -14,
+    'm', 0, 0,
+    'l', 0, 0,
     'e',
+    'X', 'X', 'X', 'X', 'X', 'X',
+    'X', 'X', 'X', 'X', 'X', 'X',
+    'X', 'X', 'X', 'X', 'X', 'X',
+    'X', 'X', 'X', 'X', 'X', 'X',
+    'X', 'X', 'X',
 /* 0x22 '"'  offset 90 */
-    0, 16, 42, -28, 2, 3,
+    0, 16, 42, -28, 2, 2,
     0, 16, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -28, /* snap_y */
     'm', 0, -42,
     'l', 0, -28,
     'm', 16, -42,
     'l', 16, -28,
     'e',
+    'X',
 /* 0x23 '#'  offset 114 */
     0, 30, 50, 14, 2, 5,
     0, 30, /* snap_x */
     -24, -21, -15, -12, 0, /* snap_y */
     'm', 16, -50,
     'l', 2, 14,
     'm', 28, -50,
     'l', 14, 14,
@@ -97,37 +103,40 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 29, -28, 32, 0, 12, 0,
     'c', 0, 0, 0, -8, 0, -10,
     'c', 0, -24, 22, -20, 22, -34,
     'c', 22, -45, 10, -45, 10, -34,
     'c', 10, -27, 25, 0, 36, 0,
     'c', 39, 0, 40, -1, 40, -4,
     'e',
 /* 0x27 '''  offset 390 */
-    0, 4, 42, -30, 2, 3,
+    0, 4, 42, -30, 2, 2,
     0, 4, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -28, /* snap_y */
     'm', 2, -38,
     'c', -1, -38, -1, -42, 2, -42,
     'c', 6, -42, 5, -33, 0, -30,
     'e',
+    'X',
 /* 0x28 '('  offset 419 */
-    0, 14, 50, 14, 2, 3,
+    0, 14, 50, 14, 2, 2,
     0, 14, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -50, 14, /* snap_y */
     'm', 14, -50,
     'c', -5, -32, -5, -5, 14, 14,
     'e',
+    'X',
 /* 0x29 ')'  offset 441 */
-    0, 14, 50, 14, 2, 3,
+    0, 14, 50, 14, 2, 2,
     0, 14, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -15, 14, /* snap_y */
     'm', 0, -50,
     'c', 19, -34, 19, -2, 0, 14,
     'e',
+    'X',
 /* 0x2a '*'  offset 463 */
     0, 20, 30, -6, 3, 3,
     0, 10, 20, /* snap_x */
     -21, -15, 0, /* snap_y */
     'm', 10, -30,
     'l', 10, -6,
     'm', 0, -24,
     'l', 20, -12,
@@ -182,17 +191,17 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 9, -42, 0, -42, 0, -21,
     'c', 0, 0, 9, 0, 14, 0,
     'c', 19, 0, 28, 0, 28, -21,
     'c', 28, -42, 19, -42, 14, -42,
     'E',
 /* 0x31 '1'  offset 666 */
     0, 28, 42, 0, 2, 3,
     0, 17, 28 /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -34, 0, /* snap_y */
     'm', 7, -34,
     'c', 11, -35, 15, -38, 17, -42,
     'l', 17, 0,
     'e',
 /* 0x32 '2'  offset 691 */
     0, 28, 42, 0, 4, 4,
     0, 2, 26, 28, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
@@ -210,25 +219,26 @@ const int8_t _cairo_twin_outlines[] = {
     'm', 4, -42,
     'l', 26, -42,
     'l', 14, -26,
     'c', 21, -26, 28, -26, 28, -14,
     'c', 28, 0, 17, 0, 13, 0,
     'c', 8, 0, 3, -1, 0, -8,
     'e',
 /* 0x34 '4'  offset 780 */
-    0, 28, 42, 0, 3, 4,
+    0, 28, 42, 0, 3, 3,
     0, 20, 30, /* snap_x */
-    -21, -15, -14, 0, /* snap_y */
+    -42, -14, 0, /* snap_y */
     'm', 20, 0,
     'l', 20, -42,
     'l', 0, -14,
     'l', 30, -14,
     'e',
     'X', 'X', 'X',
+    'X',
 /* 0x35 '5'  offset 809 */
     0, 28, 42, 0, 2, 5,
     0, 28, /* snap_x */
     -42, -28, -21, -15, 0, /* snap_y */
     'm', 24, -42,
     'l', 4, -42,
     'l', 2, -24,
     'c', 5, -27, 10, -28, 13, -28,
@@ -302,51 +312,55 @@ const int8_t _cairo_twin_outlines[] = {
     'm', 4, -2,
     'c', 4, 1, 0, 1, 0, -2,
     'c', 0, -5, 4, -5, 4, -2,
     'c', 4, 3, 2, 6, 0, 8,
     'e',
 /* 0x3c '<'  offset 1162 */
     0, 32, 36, 0, 2, 3,
     0, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -36, -18, 0, /* snap_y */
     'm', 32, -36,
     'l', 0, -18,
     'l', 32, 0,
     'e',
 /* 0x3d '='  offset 1183 */
-    0, 36, 24, -12, 2, 5,
+    0, 36, 24, -12, 2, 2,
     0, 36, /* snap_x */
-    -24, -21, -15, -12, 0, /* snap_y */
+    -24, -15, /* snap_y */
     'm', 0, -24,
     'l', 36, -24,
     'm', 0, -12,
     'l', 36, -12,
     'e',
+    'X', 'X', 'X',
 /* 0x3e '>'  offset 1209 */
     0, 32, 36, 0, 2, 3,
     0, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -36, -18, 0, /* snap_y */
     'm', 0, -36,
     'l', 32, -18,
     'l', 0, 0,
     'e',
 /* 0x3f '?'  offset 1230 */
     0, 24, 42, 0, 3, 4,
     0, 12, 24, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
     'm', 0, -32,
     'c', 0, -34, 0, -42, 12, -42,
     'c', 24, -42, 24, -34, 24, -32,
     'c', 24, -29, 24, -24, 12, -20,
     'l', 12, -14,
-    'm', 12, -4,
-    'c', 9, -4, 9, 0, 12, 0,
-    'c', 15, 0, 15, -4, 12, -4,
+    'm', 12, 0,
+    'l', 12, 0,
     'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X',
 /* 0x40 '@'  offset 1288 */
     0, 42, 42, 0, 1, 6,
     30, /* snap_x */
     -42, -32, -21, -15, -10, 0, /* snap_y */
     'm', 30, -26,
     'c', 28, -31, 24, -32, 21, -32,
     'c', 10, -32, 10, -23, 10, -19,
     'c', 10, -13, 11, -10, 19, -10,
@@ -354,168 +368,178 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 27, -10, 30, -10, 34, -10,
     'c', 41, -10, 42, -19, 42, -22,
     'c', 42, -34, 34, -42, 21, -42,
     'c', 9, -42, 0, -34, 0, -21,
     'c', 0, -9, 8, 0, 21, 0,
     'c', 30, 0, 34, -3, 36, -6,
     'e',
 /* 0x41 'A'  offset 1375 */
-    0, 32, 42, 0, 2, 4,
+    0, 32, 42, 0, 2, 3,
     0, 32, /* snap_x */
-    -21, -15, -14, 0, /* snap_y */
+    -42, -14, 0, /* snap_y */
     'm', 0, 0,
     'l', 16, -42,
     'l', 32, 0,
     'm', 6, -14,
     'l', 26, -14,
     'e',
     'X', 'X', 'X',
+    'X',
 /* 0x42 'B'  offset 1406 */
-    0, 28, 42, 0, 2, 5,
+    0, 28, 42, 0, 2, 3,
     0, 28, /* snap_x */
-    -42, -22, -21, -15, 0, /* snap_y */
+    -42, -22, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 18, -42,
     'c', 32, -42, 32, -22, 18, -22,
     'l', 0, -22,
     'l', 18, -22,
     'c', 32, -22, 32, 0, 18, 0,
     'E',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X', 'X',
 /* 0x43 'C'  offset 1455 */
     0, 30, 42, 0, 2, 4,
     0, 30, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
     'm', 30, -32,
     'c', 26, -42, 21, -42, 16, -42,
     'c', 2, -42, 0, -29, 0, -21,
     'c', 0, -13, 2, 0, 16, 0,
     'c', 21, 0, 26, 0, 30, -10,
     'e',
 /* 0x44 'D'  offset 1499 */
-    0, 28, 42, 0, 2, 4,
+    0, 28, 42, 0, 2, 2,
     0, 28, /* snap_x */
-    -42, -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 14, -42,
     'c', 33, -42, 33, 0, 14, 0,
     'E',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X', 'X',
 /* 0x45 'E'  offset 1534 */
-    0, 26, 42, 0, 2, 5,
+    0, 26, 42, 0, 2, 3,
     0, 26, /* snap_x */
-    -42, -22, -21, -15, 0, /* snap_y */
+    -42, -22, 0, /* snap_y */
     'm', 26, -42,
     'l', 0, -42,
     'l', 0, 0,
     'l', 26, 0,
     'm', 0, -22,
     'l', 16, -22,
     'e',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X', 'X',
 /* 0x46 'F'  offset 1572 */
-    0, 26, 42, 0, 2, 5,
+    0, 26, 42, 0, 2, 3,
     0, 26, /* snap_x */
-    -42, -22, -21, -15, 0, /* snap_y */
+    -42, -22, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 26, -42,
     'm', 0, -22,
     'l', 16, -22,
     'e',
     'X', 'X', 'X',
+    'X', 'X',
 /* 0x47 'G'  offset 1604 */
     0, 30, 42, 0, 2, 5,
     0, 30, /* snap_x */
     -42, -21, -16, -15, 0, /* snap_y */
     'm', 30, -32,
     'c', 26, -42, 21, -42, 16, -42,
     'c', 2, -42, 0, -29, 0, -21,
     'c', 0, -13, 2, 0, 16, 0,
     'c', 28, 0, 30, -7, 30, -16,
     'l', 20, -16,
     'e',
     'X', 'X', 'X',
 /* 0x48 'H'  offset 1655 */
-    0, 28, 42, 0, 2, 4,
+    0, 28, 42, 0, 2, 3,
     0, 28, /* snap_x */
-    -22, -21, -15, 0, /* snap_y */
+    -42, -22, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'm', 28, -42,
     'l', 28, 0,
     'm', 0, -22,
     'l', 28, -22,
     'e',
+    'X',
 /* 0x49 'I'  offset 1686 */
-    0, 0, 42, 0, 1, 3,
+    0, 0, 42, 0, 1, 2,
     0, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'e',
+    'X',
 /* 0x4a 'J'  offset 1703 */
     0, 20, 42, 0, 2, 3,
     0, 20, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -15, 0, /* snap_y */
     'm', 20, -42,
     'l', 20, -10,
     'c', 20, 3, 0, 3, 0, -10,
     'l', 0, -14,
     'e',
 /* 0x4b 'K'  offset 1731 */
     0, 28, 42, 0, 2, 3,
     0, 28, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -15, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'm', 28, -42,
     'l', 0, -14,
     'm', 10, -24,
     'l', 28, 0,
     'e',
 /* 0x4c 'L'  offset 1761 */
-    0, 24, 42, 0, 2, 3,
+    0, 24, 42, 0, 2, 2,
     0, 24, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'l', 24, 0,
     'e',
     'X', 'X', 'X',
+    'X',
 /* 0x4d 'M'  offset 1785 */
-    0, 32, 42, 0, 2, 3,
+    0, 32, 42, 0, 2, 2,
     0, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 16, 0,
     'l', 32, -42,
     'l', 32, 0,
     'e',
     'X', 'X', 'X',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X',
 /* 0x4e 'N'  offset 1821 */
-    0, 28, 42, 0, 2, 3,
+    0, 28, 42, 0, 2, 2,
     0, 28, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
     'l', 28, 0,
     'l', 28, -42,
     'e',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X',
 /* 0x4f 'O'  offset 1851 */
     0, 32, 42, 0, 2, 4,
     0, 32, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
     'm', 16, -42,
     'c', 2, -42, 0, -29, 0, -21,
     'c', 0, -13, 2, 0, 16, 0,
     'c', 30, 0, 32, -13, 32, -21,
@@ -536,17 +560,17 @@ const int8_t _cairo_twin_outlines[] = {
     0, 32, 42, 4, 2, 4,
     0, 32, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
     'm', 16, -42,
     'c', 2, -42, 0, -29, 0, -21,
     'c', 0, -13, 2, 0, 16, 0,
     'c', 30, 0, 32, -13, 32, -21,
     'c', 32, -29, 30, -42, 16, -42,
-    'm', 18, -8,
+    'M', 18, -8,
     'l', 30, 4,
     'e',
 /* 0x52 'R'  offset 1981 */
     0, 28, 42, 0, 2, 5,
     0, 28, /* snap_x */
     -42, -22, -21, -15, 0, /* snap_y */
     'm', 0, 0,
     'l', 0, -42,
@@ -573,59 +597,63 @@ const int8_t _cairo_twin_outlines[] = {
     0, 14, 28, /* snap_x */
     -42, -21, -15, 0, /* snap_y */
     'm', 14, -42,
     'l', 14, 0,
     'm', 0, -42,
     'l', 28, -42,
     'e',
 /* 0x55 'U'  offset 2100 */
-    0, 28, 42, 0, 2, 3,
+    0, 28, 42, 0, 2, 2,
     0, 28, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, -12,
     'c', 0, 4, 28, 4, 28, -12,
     'l', 28, -42,
     'e',
+    'X',
 /* 0x56 'V'  offset 2128 */
-    0, 32, 42, 0, 2, 3,
+    0, 32, 42, 0, 2, 2,
     0, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 16, 0,
     'l', 32, -42,
     'e',
     'X', 'X', 'X',
+    'X',
 /* 0x57 'W'  offset 2152 */
-    0, 40, 42, 0, 2, 3,
+    0, 40, 42, 0, 2, 2,
     0, 40, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 10, 0,
     'l', 20, -42,
     'l', 30, 0,
     'l', 40, -42,
     'e',
     'X', 'X', 'X',
     'X', 'X', 'X',
     'X', 'X', 'X',
+    'X',
 /* 0x58 'X'  offset 2188 */
-    0, 28, 42, 0, 2, 3,
+    0, 28, 42, 0, 2, 2,
     0, 28, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 28, 0,
     'm', 28, -42,
     'l', 0, 0,
     'e',
+    'X',
 /* 0x59 'Y'  offset 2212 */
     0, 32, 42, 0, 3, 3,
     0, 16, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -21, 0, /* snap_y */
     'm', 0, -42,
     'l', 16, -22,
     'l', 16, 0,
     'm', 32, -42,
     'l', 16, -22,
     'e',
 /* 0x5a 'Z'  offset 2240 */
     0, 28, 42, 0, 2, 4,
@@ -668,47 +696,49 @@ const int8_t _cairo_twin_outlines[] = {
     0, 32, /* snap_x */
     -21, -15, 0, /* snap_y */
     'm', 0, -18,
     'l', 16, -46,
     'l', 32, -18,
     'e',
     'X', 'X', 'X',
 /* 0x5f '_'  offset 2363 */
-    0, 36, 0, 0, 2, 3,
+    0, 36, 0, 0, 2, 1,
     0, 36, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    0, /* snap_y */
     'm', 0, 0,
     'l', 36, 0,
     'e',
+    'X', 'X',
 /* 0x60 '`'  offset 2381 */
-    0, 4, 42, -30, 2, 3,
+    0, 4, 42, -30, 2, 2,
     0, 4, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 4, -42,
     'c', 2, -40, 0, -39, 0, -32,
     'c', 0, -31, 1, -30, 2, -30,
     'c', 5, -30, 5, -34, 2, -34,
     'e',
+    'X',
 /* 0x61 'a'  offset 2417 */
     0, 24, 28, 0, 2, 4,
     0, 24, /* snap_x */
     -28, -21, -15, 0, /* snap_y */
     'm', 24, -28,
     'l', 24, 0,
     'm', 24, -22,
     'c', 21, -27, 18, -28, 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 18, 0, 21, -1, 24, -6,
     'e',
 /* 0x62 'b'  offset 2467 */
     0, 24, 42, 0, 2, 4,
     0, 24, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -42, -28, -15, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'm', 0, -22,
     'c', 3, -26, 6, -28, 11, -28,
     'c', 22, -28, 24, -19, 24, -14,
     'c', 24, -9, 22, 0, 11, 0,
     'c', 6, 0, 3, -2, 0, -6,
     'e',
@@ -720,17 +750,17 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 21, -26, 18, -28, 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 18, 0, 21, -2, 24, -6,
     'e',
 /* 0x64 'd'  offset 2561 */
     0, 24, 42, 0, 2, 4,
     0, 24, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -42, -28, -15, 0, /* snap_y */
     'm', 24, -42,
     'l', 24, 0,
     'm', 24, -22,
     'c', 21, -26, 18, -28, 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 18, 0, 21, -2, 24, -6,
     'e',
@@ -767,111 +797,121 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 21, -26, 18, -28, 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 18, 0, 21, -2, 24, -6,
     'e',
 /* 0x68 'h'  offset 2758 */
     0, 22, 42, 0, 2, 4,
     0, 22, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -42, -28, -15, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'm', 0, -20,
     'c', 8, -32, 22, -31, 22, -20,
     'l', 22, 0,
     'e',
 /* 0x69 'i'  offset 2790 */
-    0, 4, 44, 0, 3, 3,
-    0, 2, 4, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    0, 0, 44, 0, 1, 3,
+    0, /* snap_x */
+    -42, -28, 0, /* snap_y */
     'm', 0, -42,
-    'c', 0, -39, 4, -39, 4, -42,
-    'c', 4, -45, 0, -45, 0, -42,
-    'm', 2, -28,
-    'l', 2, 0,
+    'l', 0, -42,
+    'm', 0, -28,
+    'l', 0, 0,
     'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X',
+    'X', 'X',
 /* 0x6a 'j'  offset 2826 */
-    -8, 4, 44, 14, 3, 4,
-    0, 2, 4, /* snap_x */
-    -21, -15, 0, 14, /* snap_y */
-    'm', 0, -42,
-    'c', 0, -39, 4, -39, 4, -42,
-    'c', 4, -45, 0, -45, 0, -42,
+    -8, 4, 44, 14, 3, 5,
+    -8, 2, 4, /* snap_x */
+    -42, -21, -15, 0, 14, /* snap_y */
+    'm', 2, -42,
+    'l', 2, -42,
     'm', 2, -28,
     'l', 2, 6,
     'c', 2, 13, -1, 14, -8, 14,
     'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X',
 /* 0x6b 'k'  offset 2870 */
     0, 22, 42, 0, 2, 3,
     0, 22, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, -28, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'm', 20, -28,
     'l', 0, -8,
     'm', 8, -16,
     'l', 22, 0,
     'e',
 /* 0x6c 'l'  offset 2900 */
-    0, 0, 42, 0, 1, 3,
+    0, 0, 42, 0, 1, 2,
     0, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -42, 0, /* snap_y */
     'm', 0, -42,
     'l', 0, 0,
     'e',
+    'X',
 /* 0x6d 'm'  offset 2917 */
-    0, 44, 28, 0, 3, 4,
+    0, 44, 28, 0, 3, 3,
     0, 22, 44, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -28, -21, 0, /* snap_y */
     'm', 0, -28,
     'l', 0, 0,
     'm', 0, -20,
     'c', 5, -29, 22, -33, 22, -20,
     'l', 22, 0,
     'm', 22, -20,
     'c', 27, -29, 44, -33, 44, -20,
     'l', 44, 0,
     'e',
+    'X',
 /* 0x6e 'n'  offset 2963 */
-    0, 22, 28, 0, 2, 4,
+    0, 22, 28, 0, 2, 3,
     0, 22, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -28, -21, 0, /* snap_y */
     'm', 0, -28,
     'l', 0, 0,
     'm', 0, -20,
     'c', 4, -28, 22, -34, 22, -20,
     'l', 22, 0,
     'e',
+    'X',
 /* 0x6f 'o'  offset 2995 */
     0, 26, 28, 0, 2, 4,
     0, 26, /* snap_x */
     -28, -21, -15, 0, /* snap_y */
     'm', 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 24, 0, 26, -9, 26, -14,
     'c', 26, -19, 24, -28, 13, -28,
-    'e',
+    'E',
 /* 0x70 'p'  offset 3039 */
     0, 24, 28, 14, 2, 4,
     0, 24, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -28, -21, 0, 14, /* snap_y */
     'm', 0, -28,
     'l', 0, 14,
     'm', 0, -22,
     'c', 3, -26, 6, -28, 11, -28,
     'c', 22, -28, 24, -19, 24, -14,
     'c', 24, -9, 22, 0, 11, 0,
     'c', 6, 0, 3, -2, 0, -6,
     'e',
 /* 0x71 'q'  offset 3089 */
     0, 24, 28, 14, 2, 4,
     0, 24, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -28, -21, 0, 14, /* snap_y */
     'm', 24, -28,
     'l', 24, 14,
     'm', 24, -22,
     'c', 21, -26, 18, -28, 13, -28,
     'c', 2, -28, 0, -19, 0, -14,
     'c', 0, -9, 2, 0, 13, 0,
     'c', 18, 0, 21, -2, 24, -6,
     'e',
@@ -893,68 +933,69 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 4, -28, 0, -26, 0, -22,
     'c', 0, -11, 22, -20, 22, -7,
     'c', 22, 0, 17, 0, 11, 0,
     'c', 6, 0, 0, -1, 0, -6,
     'e',
 /* 0x74 't'  offset 3219 */
     0, 16, 42, 0, 3, 4,
     0, 6, 16, /* snap_x */
-    -28, -21, -15, 0, /* snap_y */
+    -42, -28, -21, 0, /* snap_y */
     'm', 6, -42,
     'l', 6, -8,
     'c', 6, -2, 8, 0, 16, 0,
     'm', 0, -28,
     'l', 14, -28,
     'e',
 /* 0x75 'u'  offset 3252 */
     0, 22, 28, 0, 2, 3,
     0, 22, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -28, -15, 0, /* snap_y */
     'm', 0, -28,
     'l', 0, -8,
     'c', 0, 6, 18, 0, 22, -8,
     'm', 22, -28,
     'l', 22, 0,
     'e',
 /* 0x76 'v'  offset 3283 */
     0, 24, 28, 0, 2, 3,
     0, 24, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -28, -15, 0, /* snap_y */
     'm', 0, -28,
     'l', 12, 0,
     'l', 24, -28,
     'e',
     'X', 'X', 'X',
 /* 0x77 'w'  offset 3307 */
     0, 32, 28, 0, 2, 3,
     0, 32, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -28, -15, 0, /* snap_y */
     'm', 0, -28,
     'l', 8, 0,
     'l', 16, -28,
     'l', 24, 0,
     'l', 32, -28,
     'e',
     'X', 'X', 'X',
     'X', 'X', 'X',
     'X', 'X', 'X',
 /* 0x78 'x'  offset 3343 */
-    0, 22, 28, 0, 2, 3,
+    0, 22, 28, 0, 2, 2,
     0, 22, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -28, 0, /* snap_y */
     'm', 0, -28,
     'l', 22, 0,
     'm', 22, -28,
     'l', 0, 0,
     'e',
+    'X',
 /* 0x79 'y'  offset 3367 */
     -2, 24, 28, 14, 2, 4,
     0, 24, /* snap_x */
-    -21, -15, 0, 14, /* snap_y */
+    -28, -15, 0, 14, /* snap_y */
     'm', 0, -28,
     'l', 12, 0,
     'm', 24, -28,
     'l', 12, 0,
     'c', 6, 13, 0, 14, -2, 14,
     'e',
 /* 0x7a 'z'  offset 3399 */
     0, 22, 28, 0, 2, 4,
@@ -975,22 +1016,23 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 10, -44, 6, -42, 6, -36,
     'l', 6, -24,
     'l', 0, -24,
     'l', 6, -24,
     'l', 6, -8,
     'c', 6, -2, 10, 0, 16, 0,
     'e',
 /* 0x7c '|'  offset 3474 */
-    0, 0, 50, 14, 1, 3,
+    0, 0, 50, 14, 1, 2,
     0, /* snap_x */
-    -21, -15, 0, /* snap_y */
+    -50, 14, /* snap_y */
     'm', 0, -50,
     'l', 0, 14,
     'e',
+    'X',
 /* 0x7d '}'  offset 3491 */
     0, 16, 44, 0, 3, 5,
     0, 10, 16, /* snap_x */
     -44, -24, -21, -15, 0, /* snap_y */
     'm', 0, -44,
     'c', 6, -44, 10, -42, 10, -36,
     'l', 10, -24,
     'l', 16, -24,
--- a/gfx/cairo/cairo/src/cairo-font-face-twin.c
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin.c
@@ -31,179 +31,687 @@
  *
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
  *      Behdad Esfahbod <behdad@behdad.org>
  */
 
 #include "cairoint.h"
 
+#include <math.h>
+
 /*
- * This file implements a user-font rendering the decendant of the Hershey
+ * This file implements a user-font rendering the descendant of the Hershey
  * font coded by Keith Packard for use in the Twin window system.
  * The actual font data is in cairo-font-face-twin-data.c
  *
- * Ported to cairo user font by Behdad Esfahbod.
+ * Ported to cairo user font and extended by Behdad Esfahbod.
+ */
+
+
+
+static cairo_user_data_key_t twin_properties_key;
+
+
+/*
+ * Face properties
  */
 
+/* We synthesize multiple faces from the twin data.  Here is the parameters. */
+
+/* The following tables and matching code are copied from Pango */
+
+/* CSS weight */
+typedef enum {
+  TWIN_WEIGHT_THIN = 100,
+  TWIN_WEIGHT_ULTRALIGHT = 200,
+  TWIN_WEIGHT_LIGHT = 300,
+  TWIN_WEIGHT_BOOK = 380,
+  TWIN_WEIGHT_NORMAL = 400,
+  TWIN_WEIGHT_MEDIUM = 500,
+  TWIN_WEIGHT_SEMIBOLD = 600,
+  TWIN_WEIGHT_BOLD = 700,
+  TWIN_WEIGHT_ULTRABOLD = 800,
+  TWIN_WEIGHT_HEAVY = 900,
+  TWIN_WEIGHT_ULTRAHEAVY = 1000
+} twin_face_weight_t;
+
+/* CSS stretch */
+typedef enum {
+  TWIN_STRETCH_ULTRA_CONDENSED,
+  TWIN_STRETCH_EXTRA_CONDENSED,
+  TWIN_STRETCH_CONDENSED,
+  TWIN_STRETCH_SEMI_CONDENSED,
+  TWIN_STRETCH_NORMAL,
+  TWIN_STRETCH_SEMI_EXPANDED,
+  TWIN_STRETCH_EXPANDED,
+  TWIN_STRETCH_EXTRA_EXPANDED,
+  TWIN_STRETCH_ULTRA_EXPANDED
+} twin_face_stretch_t;
+
+typedef struct
+{
+  int value;
+  const char str[16];
+} FieldMap;
+
+static const FieldMap slant_map[] = {
+  { CAIRO_FONT_SLANT_NORMAL, "" },
+  { CAIRO_FONT_SLANT_NORMAL, "Roman" },
+  { CAIRO_FONT_SLANT_OBLIQUE, "Oblique" },
+  { CAIRO_FONT_SLANT_ITALIC, "Italic" }
+};
+
+static const FieldMap smallcaps_map[] = {
+  { FALSE, "" },
+  { TRUE, "Small-Caps" }
+};
+
+static const FieldMap weight_map[] = {
+  { TWIN_WEIGHT_THIN, "Thin" },
+  { TWIN_WEIGHT_ULTRALIGHT, "Ultra-Light" },
+  { TWIN_WEIGHT_ULTRALIGHT, "Extra-Light" },
+  { TWIN_WEIGHT_LIGHT, "Light" },
+  { TWIN_WEIGHT_BOOK, "Book" },
+  { TWIN_WEIGHT_NORMAL, "" },
+  { TWIN_WEIGHT_NORMAL, "Regular" },
+  { TWIN_WEIGHT_MEDIUM, "Medium" },
+  { TWIN_WEIGHT_SEMIBOLD, "Semi-Bold" },
+  { TWIN_WEIGHT_SEMIBOLD, "Demi-Bold" },
+  { TWIN_WEIGHT_BOLD, "Bold" },
+  { TWIN_WEIGHT_ULTRABOLD, "Ultra-Bold" },
+  { TWIN_WEIGHT_ULTRABOLD, "Extra-Bold" },
+  { TWIN_WEIGHT_HEAVY, "Heavy" },
+  { TWIN_WEIGHT_HEAVY, "Black" },
+  { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" },
+  { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Heavy" },
+  { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Black" },
+  { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Black" }
+};
+
+static const FieldMap stretch_map[] = {
+  { TWIN_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" },
+  { TWIN_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" },
+  { TWIN_STRETCH_CONDENSED,       "Condensed" },
+  { TWIN_STRETCH_SEMI_CONDENSED,  "Semi-Condensed" },
+  { TWIN_STRETCH_NORMAL,          "" },
+  { TWIN_STRETCH_SEMI_EXPANDED,   "Semi-Expanded" },
+  { TWIN_STRETCH_EXPANDED,        "Expanded" },
+  { TWIN_STRETCH_EXTRA_EXPANDED,  "Extra-Expanded" },
+  { TWIN_STRETCH_ULTRA_EXPANDED,  "Ultra-Expanded" }
+};
+
+static const FieldMap monospace_map[] = {
+  { FALSE, "" },
+  { TRUE, "Mono" },
+  { TRUE, "Monospace" }
+};
+
+
+typedef struct _twin_face_properties {
+    cairo_font_slant_t  slant;
+    twin_face_weight_t  weight;
+    twin_face_stretch_t stretch;
+
+    /* lets have some fun */
+    cairo_bool_t monospace;
+    cairo_bool_t smallcaps;
+} twin_face_properties_t;
+
+static cairo_bool_t
+field_matches (const char *s1,
+               const char *s2,
+               int len)
+{
+  int c1, c2;
+
+  while (len && *s1 && *s2)
+    {
+#define TOLOWER(c) \
+   (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+      c1 = TOLOWER (*s1);
+      c2 = TOLOWER (*s2);
+      if (c1 != c2) {
+        if (c1 == '-') {
+          s1++;
+          continue;
+        }
+        return FALSE;
+      }
+      s1++; s2++;
+      len--;
+    }
+
+  return len == 0 && *s1 == '\0';
+}
+
+static cairo_bool_t
+parse_int (const char *word,
+	   size_t      wordlen,
+	   int        *out)
+{
+  char *end;
+  long val = strtol (word, &end, 10);
+  int i = val;
+
+  if (end != word && (end == word + wordlen) && val >= 0 && val == i)
+    {
+      if (out)
+        *out = i;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static cairo_bool_t
+find_field (const char *what,
+	    const FieldMap *map,
+	    int n_elements,
+	    const char *str,
+	    int len,
+	    int *val)
+{
+  int i;
+  cairo_bool_t had_prefix = FALSE;
+
+  if (what)
+    {
+      i = strlen (what);
+      if (len > i && 0 == strncmp (what, str, i) && str[i] == '=')
+	{
+	  str += i + 1;
+	  len -= i + 1;
+	  had_prefix = TRUE;
+	}
+    }
+
+  for (i=0; i<n_elements; i++)
+    {
+      if (map[i].str[0] && field_matches (map[i].str, str, len))
+	{
+	  if (val)
+	    *val = map[i].value;
+	  return TRUE;
+	}
+    }
+
+  if (!what || had_prefix)
+    return parse_int (str, len, val);
+
+  return FALSE;
+}
+
+static void
+parse_field (twin_face_properties_t *props,
+	     const char *str,
+	     int len)
+{
+  if (field_matches ("Normal", str, len))
+    return;
+
+#define FIELD(NAME) \
+  if (find_field (STRINGIFY (NAME), NAME##_map, ARRAY_LENGTH (NAME##_map), str, len, \
+		  (int *)(void *)&props->NAME)) \
+      return; \
+
+  FIELD (weight);
+  FIELD (slant);
+  FIELD (stretch);
+  FIELD (smallcaps);
+  FIELD (monospace);
+
+#undef FIELD
+}
+
+static void
+face_props_parse (twin_face_properties_t *props,
+	     const char *s)
+{
+    const char *start, *end;
+
+    for (start = end = s; *end; end++) {
+	if (*end != ' ' && *end != ':')
+	    continue;
+
+	if (start < end)
+		parse_field (props, start, end - start);
+	start = end + 1;
+    }
+    if (start < end)
+	    parse_field (props, start, end - start);
+}
+
+static cairo_status_t
+twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
+					cairo_toy_font_face_t *toy_face)
+{
+    cairo_status_t status;
+    twin_face_properties_t *props;
+
+    props = malloc (sizeof (twin_face_properties_t));
+    if (unlikely (props == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    props->stretch  = TWIN_STRETCH_NORMAL;
+    props->monospace = FALSE;
+    props->smallcaps = FALSE;
+
+    props->slant = toy_face->slant;
+    props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
+		    TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
+    face_props_parse (props, toy_face->family);
+
+    status = cairo_font_face_set_user_data (twin_face,
+					    &twin_properties_key,
+					    props, free);
+    if (unlikely (status))
+	goto FREE_PROPS;
+
+    return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+    free (props);
+    return status;
+}
+
+
+/*
+ * Scaled properties
+ */
+
+typedef struct _twin_scaled_properties {
+	twin_face_properties_t *face_props;
+
+	cairo_bool_t snap; /* hint outlines */
+
+	double weight; /* unhinted pen width */
+	double penx, peny; /* hinted pen width */
+	double marginl, marginr; /* hinted side margins */
+
+	double stretch; /* stretch factor */
+} twin_scaled_properties_t;
+
+static void
+compute_hinting_scale (cairo_t *cr,
+		       double x, double y,
+		       double *scale, double *inv)
+{
+    cairo_user_to_device_distance (cr, &x, &y);
+    *scale = x == 0 ? y : y == 0 ? x :sqrt (x*x + y*y);
+    *inv = 1 / *scale;
+}
+
+static void
+compute_hinting_scales (cairo_t *cr,
+			double *x_scale, double *x_scale_inv,
+			double *y_scale, double *y_scale_inv)
+{
+    double x, y;
+
+    x = 1; y = 0;
+    compute_hinting_scale (cr, x, y, x_scale, x_scale_inv);
+
+    x = 0; y = 1;
+    compute_hinting_scale (cr, x, y, y_scale, y_scale_inv);
+}
+
+#define SNAPXI(p)	(_cairo_round ((p) * x_scale) * x_scale_inv)
+#define SNAPYI(p)	(_cairo_round ((p) * y_scale) * y_scale_inv)
+
+/* This controls the global font size */
+#define F(g)		((g) / 72.)
+
+static void
+twin_hint_pen_and_margins(cairo_t *cr,
+			  double *penx, double *peny,
+			  double *marginl, double *marginr)
+{
+    double x_scale, x_scale_inv;
+    double y_scale, y_scale_inv;
+    double margin;
+
+    compute_hinting_scales (cr,
+			    &x_scale, &x_scale_inv,
+			    &y_scale, &y_scale_inv);
+
+    *penx = SNAPXI (*penx);
+    if (*penx < x_scale_inv)
+	*penx = x_scale_inv;
+
+    *peny = SNAPYI (*peny);
+    if (*peny < y_scale_inv)
+	*peny = y_scale_inv;
+
+    margin = *marginl + *marginr;
+    *marginl = SNAPXI (*marginl);
+    if (*marginl < x_scale_inv)
+	*marginl = x_scale_inv;
+
+    *marginr = margin - *marginl;
+    if (*marginr < 0)
+	*marginr = 0;
+    *marginr = SNAPXI (*marginr);
+}
+
+static cairo_status_t
+twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
+				     cairo_t           *cr)
+{
+    cairo_status_t status;
+    twin_scaled_properties_t *props;
+
+    props = malloc (sizeof (twin_scaled_properties_t));
+    if (unlikely (props == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+
+    props->face_props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
+						       &twin_properties_key);
+
+    props->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;
+
+    /* weight */
+    props->weight = props->face_props->weight * (F (4) / TWIN_WEIGHT_NORMAL);
+
+    /* pen & margins */
+    props->penx = props->peny = props->weight;
+    props->marginl = props->marginr = F (4);
+    if (scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT)
+	twin_hint_pen_and_margins(cr,
+				  &props->penx, &props->peny,
+				  &props->marginl, &props->marginr);
+
+    /* stretch */
+    props->stretch = 1 + .1 * ((int) props->face_props->stretch - (int) TWIN_STRETCH_NORMAL);
+
+
+    /* Save it */
+    status = cairo_scaled_font_set_user_data (scaled_font,
+					      &twin_properties_key,
+					      props, free);
+    if (unlikely (status))
+	goto FREE_PROPS;
+
+    return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+    free (props);
+    return status;
+}
+
+
+/*
+ * User-font implementation
+ */
+
+static cairo_status_t
+twin_scaled_font_init (cairo_scaled_font_t  *scaled_font,
+		       cairo_t              *cr,
+		       cairo_font_extents_t *metrics)
+{
+  metrics->ascent  = F (54);
+  metrics->descent = 1 - metrics->ascent;
+
+  return twin_scaled_font_compute_properties (scaled_font, cr);
+}
+
+#define TWIN_GLYPH_MAX_SNAP_X 4
+#define TWIN_GLYPH_MAX_SNAP_Y 7
+
+typedef struct {
+    int n_snap_x;
+    int8_t snap_x[TWIN_GLYPH_MAX_SNAP_X];
+    double snapped_x[TWIN_GLYPH_MAX_SNAP_X];
+    int n_snap_y;
+    int8_t snap_y[TWIN_GLYPH_MAX_SNAP_Y];
+    double snapped_y[TWIN_GLYPH_MAX_SNAP_Y];
+} twin_snap_info_t;
 
 #define twin_glyph_left(g)      ((g)[0])
 #define twin_glyph_right(g)     ((g)[1])
 #define twin_glyph_ascent(g)    ((g)[2])
 #define twin_glyph_descent(g)   ((g)[3])
 
 #define twin_glyph_n_snap_x(g)  ((g)[4])
 #define twin_glyph_n_snap_y(g)  ((g)[5])
 #define twin_glyph_snap_x(g)    (&g[6])
 #define twin_glyph_snap_y(g)    (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
 #define twin_glyph_draw(g)      (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
 
-#define SNAPI(p)	(p)
-#define SNAPH(p)	(p)
+static void
+twin_compute_snap (cairo_t             *cr,
+		   twin_snap_info_t    *info,
+		   const signed char   *b)
+{
+    int			s, n;
+    const signed char	*snap;
+    double x_scale, x_scale_inv;
+    double y_scale, y_scale_inv;
+
+    compute_hinting_scales (cr,
+			    &x_scale, &x_scale_inv,
+			    &y_scale, &y_scale_inv);
+
+    snap = twin_glyph_snap_x (b);
+    n = twin_glyph_n_snap_x (b);
+    info->n_snap_x = n;
+    assert (n <= TWIN_GLYPH_MAX_SNAP_X);
+    for (s = 0; s < n; s++) {
+	info->snap_x[s] = snap[s];
+	info->snapped_x[s] = SNAPXI (F (snap[s]));
+    }
+
+    snap = twin_glyph_snap_y (b);
+    n = twin_glyph_n_snap_y (b);
+    info->n_snap_y = n;
+    assert (n <= TWIN_GLYPH_MAX_SNAP_Y);
+    for (s = 0; s < n; s++) {
+	info->snap_y[s] = snap[s];
+	info->snapped_y[s] = SNAPYI (F (snap[s]));
+    }
+}
 
-#define FX(g)		((g) / 64.)
-#define FY(g)		((g) / 64.)
+static double
+twin_snap (int8_t v, int n, int8_t *snap, double *snapped)
+{
+    int	s;
+
+    if (!n)
+	return F(v);
+
+    if (snap[0] == v)
+	return snapped[0];
+
+    for (s = 0; s < n - 1; s++)
+    {
+	if (snap[s+1] == v)
+	    return snapped[s+1];
 
+	if (snap[s] <= v && v <= snap[s+1])
+	{
+	    int before = snap[s];
+	    int after = snap[s+1];
+	    int dist = after - before;
+	    double snap_before = snapped[s];
+	    double snap_after = snapped[s+1];
+	    double dist_before = v - before;
+	    return snap_before + (snap_after - snap_before) * dist_before / dist;
+	}
+    }
+    return F(v);
+}
+
+#define SNAPX(p)	twin_snap (p, info.n_snap_x, info.snap_x, info.snapped_x)
+#define SNAPY(p)	twin_snap (p, info.n_snap_y, info.snap_y, info.snapped_y)
 
 static cairo_status_t
-twin_scaled_font_init (cairo_scaled_font_t  *scaled_font,
-		       cairo_t              *cr,
-		       cairo_font_extents_t *metrics)
+twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
+			       unsigned long         glyph,
+			       cairo_t              *cr,
+			       cairo_text_extents_t *metrics)
 {
-  metrics->ascent  = FY (50);
-  metrics->descent = FY (14);
-  return CAIRO_STATUS_SUCCESS;
+    double x1, y1, x2, y2, x3, y3;
+    double marginl;
+    twin_scaled_properties_t *props;
+    twin_snap_info_t info;
+    const int8_t *b;
+    const int8_t *g;
+    int8_t w;
+    double gw;
+
+    props = cairo_scaled_font_get_user_data (scaled_font, &twin_properties_key);
+
+    /* Save glyph space, we need it when stroking */
+    cairo_save (cr);
+
+    /* center the pen */
+    cairo_translate (cr, props->penx * .5, -props->peny * .5);
+
+    /* small-caps */
+    if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
+	glyph += 'A' - 'a';
+	/* 28 and 42 are small and capital letter heights of the glyph data */
+	cairo_scale (cr, 1, 28. / 42);
+    }
+
+    /* slant */
+    if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) {
+	cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0};
+	cairo_transform (cr, &shear);
+    }
+
+    b = _cairo_twin_outlines +
+	_cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph];
+    g = twin_glyph_draw(b);
+    w = twin_glyph_right(b);
+    gw = F(w);
+
+    marginl = props->marginl;
+
+    /* monospace */
+    if (props->face_props->monospace) {
+	double monow = F(24);
+	double extra =  props->penx + props->marginl + props->marginr;
+	cairo_scale (cr, (monow + extra) / (gw + extra), 1);
+	gw = monow;
+
+	/* resnap margin for new transform */
+	{
+	    double x, y, x_scale, x_scale_inv;
+	    x = 1; y = 0;
+	    compute_hinting_scale (cr, x, y, &x_scale, &x_scale_inv);
+	    marginl = SNAPXI (marginl);
+	}
+    }
+
+    cairo_translate (cr, marginl, 0);
+
+    /* stretch */
+    cairo_scale (cr, props->stretch, 1);
+
+    if (props->snap)
+	twin_compute_snap (cr, &info, b);
+    else
+	info.n_snap_x = info.n_snap_y = 0;
+
+    /* advance width */
+    metrics->x_advance = gw * props->stretch + props->penx + props->marginl + props->marginr;
+
+    /* glyph shape */
+    for (;;) {
+	switch (*g++) {
+	case 'M':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'm':
+	    x1 = SNAPX(*g++);
+	    y1 = SNAPY(*g++);
+	    cairo_move_to (cr, x1, y1);
+	    continue;
+	case 'L':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'l':
+	    x1 = SNAPX(*g++);
+	    y1 = SNAPY(*g++);
+	    cairo_line_to (cr, x1, y1);
+	    continue;
+	case 'C':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'c':
+	    x1 = SNAPX(*g++);
+	    y1 = SNAPY(*g++);
+	    x2 = SNAPX(*g++);
+	    y2 = SNAPY(*g++);
+	    x3 = SNAPX(*g++);
+	    y3 = SNAPY(*g++);
+	    cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
+	    continue;
+	case 'E':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'e':
+	    cairo_restore (cr); /* restore glyph space */
+	    cairo_set_tolerance (cr, 0.01);
+	    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+	    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+	    cairo_set_line_width (cr, 1);
+	    cairo_scale (cr, props->penx, props->peny);
+	    cairo_stroke (cr);
+	    break;
+	case 'X':
+	    /* filler */
+	    continue;
+	}
+	break;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
 				   unsigned long        unicode,
 				   unsigned long       *glyph)
 {
     /* We use an identity charmap.  Which means we could live
      * with no unicode_to_glyph method too.  But we define this
      * to map all unknown chars to a single unknown glyph to
      * reduce pressure on cache. */
 
-    if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
+    if (likely (unicode < ARRAY_LENGTH (_cairo_twin_charmap)))
 	*glyph = unicode;
     else
 	*glyph = 0;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-#define SNAPX(p)	_twin_snap (p, info.snap_x, info.n_snap_x)
-#define SNAPY(p)	_twin_snap (p, info.snap_y, info.n_snap_y)
 
-static double
-_twin_snap (double v, int a, int b)
-{
-    return v; /* XXX */
-}
-
-static cairo_status_t
-twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
-			       unsigned long         glyph,
-			       cairo_t              *cr,
-			       cairo_text_extents_t *metrics)
-{
-    double x1, y1, x2, y2, x3, y3;
-    const int8_t *b = _cairo_twin_outlines +
-		      _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
-    const int8_t *g = twin_glyph_draw(b);
-
-    struct {
-      cairo_bool_t snap;
-      int snap_x;
-      int snap_y;
-      int n_snap_x;
-      int n_snap_y;
-    } info = {FALSE};
-
-    cairo_set_line_width (cr, 0.06);
-    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
-    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+/*
+ * Face constructor
+ */
 
-    for (;;) {
-	switch (*g++) {
-	case 'M':
-	    cairo_close_path (cr);
-	    /* fall through */
-	case 'm':
-	    x1 = FX(*g++);
-	    y1 = FY(*g++);
-	    if (info.snap)
-	    {
-		x1 = SNAPX (x1);
-		y1 = SNAPY (y1);
-	    }
-	    cairo_move_to (cr, x1, y1);
-	    continue;
-	case 'L':
-	    cairo_close_path (cr);
-	    /* fall through */
-	case 'l':
-	    x1 = FX(*g++);
-	    y1 = FY(*g++);
-	    if (info.snap)
-	    {
-		x1 = SNAPX (x1);
-		y1 = SNAPY (y1);
-	    }
-	    cairo_line_to (cr, x1, y1);
-	    continue;
-	case 'C':
-	    cairo_close_path (cr);
-	    /* fall through */
-	case 'c':
-	    x1 = FX(*g++);
-	    y1 = FY(*g++);
-	    x2 = FX(*g++);
-	    y2 = FY(*g++);
-	    x3 = FX(*g++);
-	    y3 = FY(*g++);
-	    if (info.snap)
-	    {
-		x1 = SNAPX (x1);
-		y1 = SNAPY (y1);
-		x2 = SNAPX (x2);
-		y2 = SNAPY (y2);
-		x3 = SNAPX (x3);
-		y3 = SNAPY (y3);
-	    }
-	    cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
-	    continue;
-	case 'E':
-	    cairo_close_path (cr);
-	    /* fall through */
-	case 'e':
-	    cairo_stroke (cr);
-	    break;
-	case 'X':
-	    /* filler */
-	    continue;
-	}
-	break;
-    }
-
-    metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
-    metrics->x_advance +=  cairo_get_line_width (cr)/* XXX 2*x.margin */;
-    if (info.snap)
-	metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
-
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_font_face_t *
-_cairo_font_face_twin_create (cairo_font_slant_t slant,
-			      cairo_font_weight_t weight)
+cairo_status_t
+_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				      cairo_font_face_t      **font_face)
 {
+    cairo_status_t status;
     cairo_font_face_t *twin_font_face;
 
     twin_font_face = cairo_user_font_face_create ();
     cairo_user_font_face_set_init_func             (twin_font_face, twin_scaled_font_init);
     cairo_user_font_face_set_render_glyph_func     (twin_font_face, twin_scaled_font_render_glyph);
     cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
+    status = twin_font_face_set_properties_from_toy (twin_font_face, toy_face);
+    if (status) {
+	cairo_font_face_destroy (twin_font_face);
+	return status;
+    }
 
-    return twin_font_face;
+    *font_face = twin_font_face;
+
+    return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -33,91 +33,26 @@
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  *      Graydon Hoare <graydon@redhat.com>
  *      Owen Taylor <otaylor@redhat.com>
  */
 
-#define _BSD_SOURCE /* for strdup() */
 #include "cairoint.h"
 
-static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
-
 /* #cairo_font_face_t */
 
-const cairo_toy_font_face_t _cairo_font_face_nil = {
-    {
+const cairo_font_face_t _cairo_font_face_nil = {
     { 0 },				/* hash_entry */
     CAIRO_STATUS_NO_MEMORY,		/* status */
     CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
     { 0, 0, 0, NULL },			/* user_data */
-    &_cairo_toy_font_face_backend
-    },
-    CAIRO_FONT_FAMILY_DEFAULT,		/* family */
-    TRUE,				/* owns_family */
-    CAIRO_FONT_SLANT_DEFAULT,		/* slant */
-    CAIRO_FONT_WEIGHT_DEFAULT		/* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_null_pointer = {
-    {
-    { 0 },				/* hash_entry */
-    CAIRO_STATUS_NULL_POINTER,		/* status */
-    CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-    { 0, 0, 0, NULL },			/* user_data */
-    &_cairo_toy_font_face_backend
-    },
-    CAIRO_FONT_FAMILY_DEFAULT,		/* family */
-    TRUE,				/* owns_family */
-    CAIRO_FONT_SLANT_DEFAULT,		/* slant */
-    CAIRO_FONT_WEIGHT_DEFAULT		/* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_string = {
-    {
-    { 0 },				/* hash_entry */
-    CAIRO_STATUS_INVALID_STRING,	/* status */
-    CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-    { 0, 0, 0, NULL },			/* user_data */
-    &_cairo_toy_font_face_backend
-    },
-    CAIRO_FONT_FAMILY_DEFAULT,		/* family */
-    TRUE,				/* owns_family */
-    CAIRO_FONT_SLANT_DEFAULT,		/* slant */
-    CAIRO_FONT_WEIGHT_DEFAULT		/* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_slant = {
-    {
-    { 0 },				/* hash_entry */
-    CAIRO_STATUS_INVALID_SLANT,		/* status */
-    CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-    { 0, 0, 0, NULL },			/* user_data */
-    &_cairo_toy_font_face_backend
-    },
-    CAIRO_FONT_FAMILY_DEFAULT,		/* family */
-    TRUE,				/* owns_family */
-    CAIRO_FONT_SLANT_DEFAULT,		/* slant */
-    CAIRO_FONT_WEIGHT_DEFAULT		/* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_weight = {
-    {
-    { 0 },				/* hash_entry */
-    CAIRO_STATUS_INVALID_WEIGHT,	/* status */
-    CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-    { 0, 0, 0, NULL },			/* user_data */
-    &_cairo_toy_font_face_backend
-    },
-    CAIRO_FONT_FAMILY_DEFAULT,		/* family */
-    TRUE,				/* owns_family */
-    CAIRO_FONT_SLANT_DEFAULT,		/* slant */
-    CAIRO_FONT_WEIGHT_DEFAULT		/* weight */
+    NULL
 };
 
 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;
@@ -218,16 +153,19 @@ slim_hidden_def (cairo_font_face_destroy
  *
  * Return value: The type of @font_face.
  *
  * Since: 1.2
  **/
 cairo_font_type_t
 cairo_font_face_get_type (cairo_font_face_t *font_face)
 {
+    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
+	return CAIRO_FONT_TYPE_TOY;
+
     return font_face->backend->type;
 }
 
 /**
  * cairo_font_face_get_reference_count:
  * @font_face: a #cairo_font_face_t
  *
  * Returns the current reference count of @font_face.
@@ -309,426 +247,16 @@ cairo_font_face_set_user_data (cairo_fon
     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
 	return font_face->status;
 
     return _cairo_user_data_array_set_data (&font_face->user_data,
 					    key, user_data, destroy);
 }
 slim_hidden_def (cairo_font_face_set_user_data);
 
-static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
-
-static int
-_cairo_toy_font_face_keys_equal (const void *key_a,
-				 const void *key_b);
-
-/* We maintain a hash table from family/weight/slant =>
- * #cairo_font_face_t for #cairo_toy_font_t. The primary purpose of
- * this mapping is to provide unique #cairo_font_face_t values so that
- * our cache and mapping from #cairo_font_face_t => #cairo_scaled_font_t
- * works. Once the corresponding #cairo_font_face_t objects fall out of
- * downstream caches, we don't need them in this hash table anymore.
- *
- * Modifications to this hash table are protected by
- * _cairo_font_face_mutex.
- */
-static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL;
-
-static cairo_hash_table_t *
-_cairo_toy_font_face_hash_table_lock (void)
-{
-    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
-
-    if (cairo_toy_font_face_hash_table == NULL)
-    {
-	cairo_toy_font_face_hash_table =
-	    _cairo_hash_table_create (_cairo_toy_font_face_keys_equal);
-
-	if (cairo_toy_font_face_hash_table == NULL) {
-	    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
-	    return NULL;
-	}
-    }
-
-    return cairo_toy_font_face_hash_table;
-}
-
-static void
-_cairo_toy_font_face_hash_table_unlock (void)
-{
-    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
-}
-
-/**
- * _cairo_toy_font_face_init_key:
- *
- * Initialize those portions of #cairo_toy_font_face_t needed to use
- * it as a hash table key, including the hash code buried away in
- * font_face->base.hash_entry. No memory allocation is performed here
- * so that no fini call is needed. We do this to make it easier to use
- * an automatic #cairo_toy_font_face_t variable as a key.
- **/
-static void
-_cairo_toy_font_face_init_key (cairo_toy_font_face_t *key,
-			       const char	     *family,
-			       cairo_font_slant_t     slant,
-			       cairo_font_weight_t    weight)
-{
-    unsigned long hash;
-
-    key->family = family;
-    key->owns_family = FALSE;
-
-    key->slant = slant;
-    key->weight = weight;
-
-    /* 1607 and 1451 are just a couple of arbitrary primes. */
-    hash = _cairo_hash_string (family);
-    hash += ((unsigned long) slant) * 1607;
-    hash += ((unsigned long) weight) * 1451;
-
-    assert (hash != 0);
-    key->base.hash_entry.hash = hash;
-}
-
-static cairo_status_t
-_cairo_toy_font_face_init (cairo_toy_font_face_t *font_face,
-			   const char	         *family,
-			   cairo_font_slant_t	  slant,
-			   cairo_font_weight_t	  weight)
-{
-    char *family_copy;
-
-    family_copy = strdup (family);
-    if (family_copy == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _cairo_toy_font_face_init_key (font_face, family_copy,
-				      slant, weight);
-    font_face->owns_family = TRUE;
-
-    _cairo_font_face_init (&font_face->base, &_cairo_toy_font_face_backend);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
-{
-    /* We assert here that we own font_face->family before casting
-     * away the const qualifer. */
-    assert (font_face->owns_family);
-    free ((char*) font_face->family);
-}
-
-static int
-_cairo_toy_font_face_keys_equal (const void *key_a,
-				 const void *key_b)
-{
-    const cairo_toy_font_face_t *face_a = key_a;
-    const cairo_toy_font_face_t *face_b = key_b;
-
-    return (strcmp (face_a->family, face_b->family) == 0 &&
-	    face_a->slant == face_b->slant &&
-	    face_a->weight == face_b->weight);
-}
-
-/**
- * cairo_toy_font_face_create:
- * @family: a font family name, encoded in UTF-8
- * @slant: the slant for the font
- * @weight: the weight for the font
- *
- * Creates a font face from a triplet of family, slant, and weight.
- * These font faces are used in implementation of the the #cairo_t "toy"
- * font API.
- *
- * If @family is the zero-length string "", the platform-specific default
- * family is assumed.  The default family then can be queried using
- * cairo_toy_font_face_get_family().
- *
- * The cairo_select_font_face() function uses this to create font faces.
- * See that function for limitations of toy font faces.
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- *  cairo_font_face_destroy() when you are done using it.
- *
- * Since: 1.8
- **/
-cairo_font_face_t *
-cairo_toy_font_face_create (const char          *family,
-			    cairo_font_slant_t   slant,
-			    cairo_font_weight_t  weight)
-{
-    cairo_status_t status;
-    cairo_toy_font_face_t key, *font_face;
-    cairo_hash_table_t *hash_table;
-
-    if (family == NULL)
-	return (cairo_font_face_t*) &_cairo_font_face_null_pointer;
-
-    /* Make sure we've got valid UTF-8 for the family */
-    status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL);
-    if (status == CAIRO_STATUS_INVALID_STRING)
-	return (cairo_font_face_t*) &_cairo_font_face_invalid_string;
-    else if (status)
-	return (cairo_font_face_t*) &_cairo_font_face_nil;
-
-    switch (slant) {
-	case CAIRO_FONT_SLANT_NORMAL:
-	case CAIRO_FONT_SLANT_ITALIC:
-	case CAIRO_FONT_SLANT_OBLIQUE:
-	    break;
-	default:
-	    return (cairo_font_face_t*) &_cairo_font_face_invalid_slant;
-    }
-
-    switch (weight) {
-	case CAIRO_FONT_WEIGHT_NORMAL:
-	case CAIRO_FONT_WEIGHT_BOLD:
-	    break;
-	default:
-	    return (cairo_font_face_t*) &_cairo_font_face_invalid_weight;
-    }
-
-    if (*family == '\0')
-	family = CAIRO_FONT_FAMILY_DEFAULT;
-
-    hash_table = _cairo_toy_font_face_hash_table_lock ();
-    if (hash_table == NULL)
-	goto UNWIND;
-
-    _cairo_toy_font_face_init_key (&key, family, slant, weight);
-
-    /* Return existing font_face if it exists in the hash table. */
-    if (_cairo_hash_table_lookup (hash_table,
-				  &key.base.hash_entry,
-				  (cairo_hash_entry_t **) &font_face))
-    {
-	if (! font_face->base.status)  {
-	    /* We increment the reference count here manually to avoid
-	       double-locking. */
-	    _cairo_reference_count_inc (&font_face->base.ref_count);
-	    _cairo_toy_font_face_hash_table_unlock ();
-	    return &font_face->base;
-	}
-
-	/* remove the bad font from the hash table */
-	_cairo_hash_table_remove (hash_table, &key.base.hash_entry);
-	font_face->base.hash_entry.hash = 0;
-    }
-
-    /* Otherwise create it and insert into hash table. */
-    font_face = malloc (sizeof (cairo_toy_font_face_t));
-    if (font_face == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto UNWIND_HASH_TABLE_LOCK;
-    }
-
-    status = _cairo_toy_font_face_init (font_face, family, slant, weight);
-    if (status)
-	goto UNWIND_FONT_FACE_MALLOC;
-
-    status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
-    if (status)
-	goto UNWIND_FONT_FACE_INIT;
-
-    _cairo_toy_font_face_hash_table_unlock ();
-
-    return &font_face->base;
-
- UNWIND_FONT_FACE_INIT:
-    _cairo_toy_font_face_fini (font_face);
- UNWIND_FONT_FACE_MALLOC:
-    free (font_face);
- UNWIND_HASH_TABLE_LOCK:
-    _cairo_toy_font_face_hash_table_unlock ();
- UNWIND:
-    return (cairo_font_face_t*) &_cairo_font_face_nil;
-}
-slim_hidden_def (cairo_toy_font_face_create);
-
-static void
-_cairo_toy_font_face_destroy (void *abstract_face)
-{
-    cairo_toy_font_face_t *font_face = abstract_face;
-    cairo_hash_table_t *hash_table;
-
-    if (font_face == NULL ||
-	    CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->base.ref_count))
-	return;
-
-    hash_table = _cairo_toy_font_face_hash_table_lock ();
-    /* All created objects must have been mapped in the hash table. */
-    assert (hash_table != NULL);
-
-    if (font_face->base.hash_entry.hash != 0)
-	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
-
-    _cairo_toy_font_face_hash_table_unlock ();
-
-    _cairo_toy_font_face_fini (font_face);
-}
-
-static cairo_status_t
-_cairo_toy_font_face_scaled_font_get_implementation (void                *abstract_font_face,
-						     cairo_font_face_t **font_face_out)
-{
-    cairo_toy_font_face_t *font_face = abstract_font_face;
-    cairo_status_t status;
-
-    if (font_face->base.status)
-	return font_face->base.status;
-
-    if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
-    {
-	const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
-
-	if (backend->get_implementation == NULL) {
-	    *font_face_out = &font_face->base;
-	    return CAIRO_STATUS_SUCCESS;
-	}
-
-	status = backend->get_implementation (font_face,
-					      font_face_out);
-
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return _cairo_font_face_set_error (&font_face->base, status);
-    }
-
-    status = _cairo_user_scaled_font_backend.get_implementation (font_face,
-								 font_face_out);
-
-    return _cairo_font_face_set_error (&font_face->base, status);
-}
-
-static cairo_status_t
-_cairo_toy_font_face_scaled_font_create (void                *abstract_font_face,
-					 const cairo_matrix_t       *font_matrix,
-					 const cairo_matrix_t       *ctm,
-					 const cairo_font_options_t *options,
-					 cairo_scaled_font_t	   **scaled_font)
-{
-    cairo_toy_font_face_t *font_face = abstract_font_face;
-    cairo_status_t status;
-
-    if (font_face->base.status)
-	return font_face->base.status;
-
-    status = cairo_font_options_status ((cairo_font_options_t *) options);
-    if (status)
-	return status;
-
-    if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
-    {
-	const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
-
-	*scaled_font = NULL;
-	status =  backend->create_toy (font_face,
-				       font_matrix,
-				       ctm,
-				       options,
-				       scaled_font);
-
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return _cairo_font_face_set_error (&font_face->base, status);
-
-	if (*scaled_font)
-	    cairo_scaled_font_destroy (*scaled_font);
-    }
-
-    status = _cairo_user_scaled_font_backend.create_toy (font_face,
-							 font_matrix,
-							 ctm,
-							 options,
-							 scaled_font);
-
-    return _cairo_font_face_set_error (&font_face->base, status);
-}
-
-static cairo_bool_t
-_cairo_font_face_is_toy (cairo_font_face_t *font_face)
-{
-    return font_face->backend == &_cairo_toy_font_face_backend;
-}
-
-/**
- * cairo_toy_font_face_get_family:
- * @font_face: A toy font face
- *
- * Gets the familly name of a toy font.
- *
- * Return value: The family name.  This string is owned by the font face
- * and remains valid as long as the font face is alive (referenced).
- *
- * Since: 1.8
- **/
-const char *
-cairo_toy_font_face_get_family (cairo_font_face_t *font_face)
-{
-    cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
-    if (! _cairo_font_face_is_toy (font_face)) {
-	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
-	    return CAIRO_FONT_FAMILY_DEFAULT;
-    }
-    assert (toy_font_face->owns_family);
-    return toy_font_face->family;
-}
-
-/**
- * cairo_toy_font_face_get_slant:
- * @font_face: A toy font face
- *
- * Gets the slant a toy font.
- *
- * Return value: The slant value
- *
- * Since: 1.8
- **/
-cairo_font_slant_t
-cairo_toy_font_face_get_slant (cairo_font_face_t *font_face)
-{
-    cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
-    if (! _cairo_font_face_is_toy (font_face)) {
-	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
-	    return CAIRO_FONT_SLANT_DEFAULT;
-    }
-    return toy_font_face->slant;
-}
-slim_hidden_def (cairo_toy_font_face_get_slant);
-
-/**
- * cairo_toy_font_face_get_weight:
- * @font_face: A toy font face
- *
- * Gets the weight a toy font.
- *
- * Return value: The weight value
- *
- * Since: 1.8
- **/
-cairo_font_weight_t
-cairo_toy_font_face_get_weight (cairo_font_face_t *font_face)
-{
-    cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
-    if (! _cairo_font_face_is_toy (font_face)) {
-	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
-	    return CAIRO_FONT_WEIGHT_DEFAULT;
-    }
-    return toy_font_face->weight;
-}
-slim_hidden_def (cairo_toy_font_face_get_weight);
-
-static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
-    CAIRO_FONT_TYPE_TOY,
-    _cairo_toy_font_face_destroy,
-    _cairo_toy_font_face_scaled_font_get_implementation,
-    _cairo_toy_font_face_scaled_font_create
-};
-
 void
 _cairo_unscaled_font_init (cairo_unscaled_font_t               *unscaled_font,
 			   const cairo_unscaled_font_backend_t *backend)
 {
     CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
     unscaled_font->backend = backend;
 }
 
@@ -755,22 +283,8 @@ void
 
     if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
 	return;
 
     unscaled_font->backend->destroy (unscaled_font);
 
     free (unscaled_font);
 }
-
-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);
-    cairo_toy_font_face_hash_table = NULL;
-    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
-}
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -40,17 +40,17 @@
 
 #define _BSD_SOURCE /* for strdup() */
 #include "cairoint.h"
 
 #include "cairo-ft-private.h"
 
 #include <float.h>
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
+#if CAIRO_HAS_FC_FONT
 #include <fontconfig/fontconfig.h>
 #include <fontconfig/fcfreetype.h>
 #endif
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_IMAGE_H
@@ -118,42 +118,56 @@ struct _cairo_ft_unscaled_font {
 
 static int
 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
 				    const void *key_b);
 
 static void
 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
-static cairo_status_t
-_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
-				   FcPattern                  *pattern);
-#endif
-
 typedef enum _cairo_ft_extra_flags {
     CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
     CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
 } cairo_ft_extra_flags_t;
 
 typedef struct _cairo_ft_options {
     cairo_font_options_t    base;
     int			    load_flags;	 /* flags for FT_Load_Glyph */
     cairo_ft_extra_flags_t  extra_flags; /* other flags that affect results */
 } cairo_ft_options_t;
 
 struct _cairo_ft_font_face {
     cairo_font_face_t base;
+
     cairo_ft_unscaled_font_t *unscaled;
     cairo_ft_options_t ft_options;
     cairo_ft_font_face_t *next;
+
+#if CAIRO_HAS_FC_FONT
+    FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
+#endif
 };
 
 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
 
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+				   FcPattern                  *pattern);
+
+static cairo_status_t
+_cairo_ft_resolve_pattern (FcPattern		      *pattern,
+			   const cairo_matrix_t       *font_matrix,
+			   const cairo_matrix_t       *ctm,
+			   const cairo_font_options_t *options,
+			   cairo_ft_unscaled_font_t  **unscaled,
+			   cairo_ft_options_t	      *ft_options);
+
+#endif
+
 /*
  * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
  * The hash table itself isn't limited in size. However, we limit the
  * number of FT_Face objects we keep around; when we've exceeded that
  * limit and need to create a new FT_Face, we dump the FT_Face from a
  * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
  * there are any).
  */
@@ -174,109 +188,99 @@ static void
 	FT_Done_Face (unscaled->face);
 	unscaled->face = NULL;
 	unscaled->have_scale = FALSE;
 
 	font_map->num_open_faces--;
     }
 }
 
-static void
+static cairo_status_t
 _cairo_ft_unscaled_font_map_create (void)
 {
     cairo_ft_unscaled_font_map_t *font_map;
 
     /* This function is only intended to be called from
      * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
      * detect some other call path. */
     assert (cairo_ft_unscaled_font_map == NULL);
 
     font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));
-    if (font_map == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL;
-    }
+    if (unlikely (font_map == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font_map->hash_table =
 	_cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
 
-    if (font_map->hash_table == NULL)
+    if (unlikely (font_map->hash_table == NULL))
 	goto FAIL;
 
-    if (FT_Init_FreeType (&font_map->ft_library))
+    if (unlikely (FT_Init_FreeType (&font_map->ft_library)))
 	goto FAIL;
 
     font_map->num_open_faces = 0;
 
     cairo_ft_unscaled_font_map = font_map;
-    return;
+    return CAIRO_STATUS_SUCCESS;
 
 FAIL:
-    if (font_map) {
-	if (font_map->hash_table)
-	    _cairo_hash_table_destroy (font_map->hash_table);
-	free (font_map);
-    }
-    cairo_ft_unscaled_font_map = NULL;
+    if (font_map->hash_table)
+	_cairo_hash_table_destroy (font_map->hash_table);
+    free (font_map);
+
+    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+}
+
+
+static void
+_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
+{
+    cairo_ft_unscaled_font_t *unscaled = entry;
+    cairo_ft_unscaled_font_map_t *font_map = closure;
+
+    _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_fini (unscaled);
+    free (unscaled);
 }
 
 static void
 _cairo_ft_unscaled_font_map_destroy (void)
 {
-    cairo_ft_unscaled_font_t *unscaled;
     cairo_ft_unscaled_font_map_t *font_map;
 
     CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
-
-    if (cairo_ft_unscaled_font_map) {
-	font_map = cairo_ft_unscaled_font_map;
-
-	/* This is rather inefficient, but destroying the hash table
-	 * is something we only do during debugging, (during
-	 * cairo_debug_reset_static_data), when efficiency is not
-	 * relevant. */
-        while (1) {
-	    unscaled = _cairo_hash_table_random_entry (font_map->hash_table,
-						       NULL);
-	    if (unscaled == NULL)
-		break;
-	    _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_fini (unscaled);
-	    free (unscaled);
-	}
-
+    font_map = cairo_ft_unscaled_font_map;
+    cairo_ft_unscaled_font_map = NULL;
+    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
+
+    if (font_map != NULL) {
+	_cairo_hash_table_foreach (font_map->hash_table,
+				   _cairo_ft_unscaled_font_map_pluck_entry,
+				   font_map);
 	assert (font_map->num_open_faces == 0);
 
 	FT_Done_FreeType (font_map->ft_library);
 
 	_cairo_hash_table_destroy (font_map->hash_table);
 
 	free (font_map);
-
-	cairo_ft_unscaled_font_map = NULL;
     }
-
-    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
 }
 
 static cairo_ft_unscaled_font_map_t *
 _cairo_ft_unscaled_font_map_lock (void)
 {
     CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
 
-    if (cairo_ft_unscaled_font_map == NULL)
-    {
-	_cairo_ft_unscaled_font_map_create ();
-
-	if (cairo_ft_unscaled_font_map == NULL) {
+    if (unlikely (cairo_ft_unscaled_font_map == NULL)) {
+	if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
 	    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	    return NULL;
 	}
     }
 
     return cairo_ft_unscaled_font_map;
 }
 
 static void
@@ -343,18 +347,19 @@ static cairo_status_t
 	_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)
+	if (unlikely (filename_copy == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
 	_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;
@@ -419,83 +424,83 @@ static cairo_ft_unscaled_font_t *
 					 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;
 
     font_map = _cairo_ft_unscaled_font_map_lock ();
-    if (font_map == NULL)
+    if (unlikely (font_map == NULL))
 	goto UNWIND;
 
     _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))
-    {
+    unscaled = _cairo_hash_table_lookup (font_map->hash_table,
+					 &key.base.hash_entry);
+    if (unscaled != NULL) {
 	_cairo_unscaled_font_reference (&unscaled->base);
 	_cairo_ft_unscaled_font_map_unlock ();
 	return unscaled;
     }
 
     /* Otherwise create it and insert into hash table. */
     unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
-    if (unscaled == NULL) {
+    if (unlikely (unscaled == NULL)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	goto UNWIND_FONT_MAP_LOCK;
     }
 
     status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
-    if (status)
+    if (unlikely (status))
 	goto UNWIND_UNSCALED_MALLOC;
 
+    assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
     status = _cairo_hash_table_insert (font_map->hash_table,
 				       &unscaled->base.hash_entry);
-    if (status)
+    if (unlikely (status))
 	goto UNWIND_UNSCALED_FONT_INIT;
 
     _cairo_ft_unscaled_font_map_unlock ();
 
     return unscaled;
 
 UNWIND_UNSCALED_FONT_INIT:
     _cairo_ft_unscaled_font_fini (unscaled);
 UNWIND_UNSCALED_MALLOC:
     free (unscaled);
 UNWIND_FONT_MAP_LOCK:
     _cairo_ft_unscaled_font_map_unlock ();
 UNWIND:
     return NULL;
 }
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
+
+#if CAIRO_HAS_FC_FONT
 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;
+    if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) == FcResultMatch)
+	goto DONE;
+
+    if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename) == FcResultMatch) {
+	/* If FC_INDEX is not set, we just use 0 */
+        FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
+	goto DONE;
     }
 
+    return NULL;
+
+DONE:
     return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
-
-UNWIND:
-    return NULL;
 }
 #endif
 
 static cairo_ft_unscaled_font_t *
 _cairo_ft_unscaled_font_create_from_face (FT_Face face)
 {
     return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
 }
@@ -508,16 +513,22 @@ static void
 
     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);
 
+    if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
+	/* somebody recreated the font whilst we waited for the lock */
+	_cairo_ft_unscaled_font_map_unlock ();
+	return;
+    }
+
     _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)
@@ -528,22 +539,21 @@ static void
     unscaled->face = NULL;
 
     _cairo_ft_unscaled_font_map_unlock ();
 
     _cairo_ft_unscaled_font_fini (unscaled);
 }
 
 static cairo_bool_t
-_has_unlocked_face (void *entry)
+_has_unlocked_face (const void *entry)
 {
-    cairo_ft_unscaled_font_t *unscaled = entry;
-
-    return (unscaled->lock_count == 0 &&
-	    unscaled->face && !unscaled->from_face);
+    const cairo_ft_unscaled_font_t *unscaled = entry;
+
+    return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
 }
 
 /* Ensures that an unscaled font has a face object. If we exceed
  * MAX_OPEN_FACES, try to close some.
  *
  * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
  * set the scale on the face, but just returns it at the last scale.
  */
@@ -626,17 +636,17 @@ static cairo_status_t
      * 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_basis_scale_factors (scale,
 						  &x_scale, &y_scale,
 						  1);
-    if (status)
+    if (unlikely (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)
       x_scale = 1.0;
@@ -676,17 +686,17 @@ static cairo_status_t
 	scale->xy == unscaled->current_scale.xy &&
 	scale->yy == unscaled->current_scale.yy)
 	return CAIRO_STATUS_SUCCESS;
 
     unscaled->have_scale = TRUE;
     unscaled->current_scale = *scale;
 
     status = _compute_transform (&sf, scale);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     unscaled->x_scale = sf.x_scale;
     unscaled->y_scale = sf.y_scale;
 
     mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
     mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
     mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
@@ -881,17 +891,17 @@ static cairo_status_t
 	    }
 	    /*
 	     * Filter the glyph to soften the color fringes
 	     */
 	    width_rgba = width;
 	    stride = bitmap->pitch;
 	    stride_rgba = (width_rgba * 4 + 3) & ~3;
 	    data_rgba = calloc (stride_rgba, height);
-	    if (data_rgba == NULL) {
+	    if (unlikely (data_rgba == NULL)) {
 		if (own_buffer)
 		    free (bitmap->buffer);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 
 	    os = 1;
 	    switch (font_options->subpixel_order) {
 	    case CAIRO_SUBPIXEL_ORDER_VRGB:
@@ -1080,28 +1090,28 @@ static cairo_status_t
 	    bitmap.num_grays  = 256;
 	    stride = (width * hmul + 3) & -4;
 	}
 
 	bitmap.pitch = stride;
 	bitmap.width = width * hmul;
 	bitmap.rows = height * vmul;
 	bitmap.buffer = calloc (stride, bitmap.rows);
-	if (bitmap.buffer == NULL)
+	if (unlikely (bitmap.buffer == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
 
 	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
 	    free (bitmap.buffer);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
 
 	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
-	if (status)
+	if (unlikely (status))
 	    return status;
     }
 
     /*
      * Note: the font's coordinate system is upside down from ours, so the
      * Y coordinate of the control box needs to be negated.  Moreover, device
      * offsets are position of glyph origin relative to top left while xMin
      * and yMax are offsets of top left relative to origin.  Another negation.
@@ -1132,17 +1142,17 @@ static cairo_status_t
      */
     error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
     /* XXX ignoring all other errors for now.  They are not fatal, typically
      * just a glyph-not-found. */
     if (error == FT_Err_Out_Of_Memory)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     /*
      * Note: the font's coordinate system is upside down from ours, so the
      * Y coordinate of the control box needs to be negated.  Moreover, device
      * offsets are position of glyph origin relative to top left while
      * bitmap_left and bitmap_top are offsets of top left relative to origin.
      * Another negation.
@@ -1219,32 +1229,32 @@ static cairo_status_t
 
     /* Create the transformed bitmap
      */
     width = x_max - x_min;
     height = y_max - y_min;
 
     transformed_to_original = original_to_transformed;
     status = cairo_matrix_invert (&transformed_to_original);
-    if (status)
+    if (unlikely (status))
 	return status;
 
     /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
     width = (width + 3) & ~3;
     image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
-    if (image->status)
+    if (unlikely (image->status))
 	return image->status;
 
     /* Initialize it to empty
      */
     status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
 				            CAIRO_COLOR_TRANSPARENT,
 					    0, 0,
 					    width, height);
-    if (status) {
+    if (unlikely (status)) {
 	cairo_surface_destroy (image);
 	return status;
     }
 
     /* Draw the original bitmap transformed into the new bitmap
      */
     _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
     cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
@@ -1252,17 +1262,17 @@ static cairo_status_t
     status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
 			               &pattern.base, NULL, image,
 				       0, 0, 0, 0, 0, 0,
 				       width,
 				       height);
 
     _cairo_pattern_fini (&pattern.base);
 
-    if (status) {
+    if (unlikely (status)) {
 	cairo_surface_destroy (image);
 	return status;
     }
 
     /* Now update the cache entry for the new bitmap, recomputing
      * the origin based on the final transform.
      */
     cairo_matrix_transform_point (&original_to_transformed,
@@ -1288,19 +1298,19 @@ 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;
-
-#ifndef CAIRO_DISABLE_FONTCONFIG
+static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
+
+#if CAIRO_HAS_FC_FONT
 /* 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;
     cairo_ft_options_t ft_options;
@@ -1426,17 +1436,17 @@ static void
 			  FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
 	embolden = FcFalse;
     
     if (embolden)
 	ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
 
     *ret = ft_options;
 }
-#endif /* CAIRO_DISABLE_FONTCONFIG */
+#endif
 
 static void
 _cairo_ft_options_merge (cairo_ft_options_t *options,
 			 cairo_ft_options_t *other)
 {
     int load_flags = other->load_flags;
     int load_target = FT_LOAD_TARGET_NORMAL;
 
@@ -1517,47 +1527,47 @@ static cairo_status_t
 {
     cairo_ft_scaled_font_t *scaled_font;
     FT_Face face;
     FT_Size_Metrics *metrics;
     cairo_font_extents_t fs_metrics;
     cairo_status_t status;
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
-    if (!face)
+    if (unlikely (face == NULL)) /* backend error */
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
-    if (scaled_font == NULL) {
+    if (unlikely (scaled_font == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL;
     }
 
     _cairo_unscaled_font_reference (&unscaled->base);
     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);
-    if (status) {
-	_cairo_unscaled_font_destroy (&unscaled->base);
-	free (scaled_font);
-	goto FAIL;
-    }
+    if (unlikely (status))
+	goto CLEANUP_SCALED_FONT;
 
     status = _cairo_ft_unscaled_font_set_scale (unscaled,
 				                &scaled_font->base.scale);
-    if (status) {
+    if (unlikely (status)) {
+	/* This can only fail if we encounter an error with the underlying
+	 * font, so propagate the error back to the font-face. */
+	_cairo_ft_unscaled_font_unlock_face (unscaled);
 	_cairo_unscaled_font_destroy (&unscaled->base);
 	free (scaled_font);
-	goto FAIL;
+	return status;
     }
 
 
     metrics = &face->size->metrics;
 
     /*
      * Get to unscaled metrics so that the upper level can get back to
      * user space
@@ -1601,150 +1611,39 @@ static cairo_status_t
 	    fs_metrics.max_y_advance = 0;
 	} else {
 	    fs_metrics.max_x_advance = 0;
 	    fs_metrics.max_y_advance = face->max_advance_height / scale;
 	}
     }
 
     status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
+    if (unlikely (status))
+	goto CLEANUP_SCALED_FONT;
+
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     *font_out = &scaled_font->base;
-
- FAIL:
+    return CAIRO_STATUS_SUCCESS;
+
+  CLEANUP_SCALED_FONT:
+    _cairo_unscaled_font_destroy (&unscaled->base);
+    free (scaled_font);
+  FAIL:
     _cairo_ft_unscaled_font_unlock_face (unscaled);
-
-    return status;
+    *font_out = _cairo_scaled_font_create_in_error (status);
+    return CAIRO_STATUS_SUCCESS; /* non-backend error */
 }
 
 cairo_bool_t
 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
 {
     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)
-{
-#ifndef CAIRO_DISABLE_FONTCONFIG
-    FcPattern *pattern, *resolved;
-    cairo_ft_unscaled_font_t *unscaled;
-    FcResult result;
-    int fcslant;
-    int fcweight;
-    cairo_matrix_t scale;
-    cairo_status_t status;
-    cairo_ft_font_transform_t sf;
-    cairo_ft_options_t ft_options;
-
-    cairo_matrix_multiply (&scale, font_matrix, ctm);
-    status = _compute_transform (&sf, &scale);
-    if (status)
-	return status;
-
-    pattern = FcPatternCreate ();
-    if (!pattern)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    if (!FcPatternAddString (pattern,
-		             FC_FAMILY, (unsigned char *) toy_face->family))
-    {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    switch (toy_face->slant)
-    {
-    case CAIRO_FONT_SLANT_ITALIC:
-        fcslant = FC_SLANT_ITALIC;
-        break;
-    case CAIRO_FONT_SLANT_OBLIQUE:
-	fcslant = FC_SLANT_OBLIQUE;
-        break;
-    case CAIRO_FONT_SLANT_NORMAL:
-    default:
-        fcslant = FC_SLANT_ROMAN;
-        break;
-    }
-
-    if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    switch (toy_face->weight)
-    {
-    case CAIRO_FONT_WEIGHT_BOLD:
-        fcweight = FC_WEIGHT_BOLD;
-        break;
-    case CAIRO_FONT_WEIGHT_NORMAL:
-    default:
-        fcweight = FC_WEIGHT_MEDIUM;
-        break;
-    }
-
-    if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    status = _cairo_ft_font_options_substitute (font_options, pattern);
-    if (status)
-	goto FREE_PATTERN;
-
-    FcDefaultSubstitute (pattern);
-
-    resolved = FcFontMatch (NULL, pattern, &result);
-    if (!resolved) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_PATTERN;
-    }
-
-    unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
-    if (!unscaled) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FREE_RESOLVED;
-    }
-
-    _get_pattern_ft_options (resolved, &ft_options);
-
-    status = _cairo_ft_scaled_font_create (unscaled,
-					   &toy_face->base,
-					   font_matrix, ctm,
-					   font_options, ft_options,
-					   font);
-
-    _cairo_unscaled_font_destroy (&unscaled->base);
-
- FREE_RESOLVED:
-    FcPatternDestroy (resolved);
-
- FREE_PATTERN:
-    FcPatternDestroy (pattern);
-
-    return status;
-#else
-    return CAIRO_INT_STATUS_UNSUPPORTED;
-#endif  /* CAIRO_DISABLE_FONTCONFIG */
-}
-
 static void
 _cairo_ft_scaled_font_fini (void *abstract_font)
 {
     cairo_ft_scaled_font_t *scaled_font = abstract_font;
 
     if (scaled_font == NULL)
         return;
 
@@ -1876,17 +1775,17 @@ static cairo_status_t
     /* Font glyphs have an inverted Y axis compared to cairo. */
     FT_Outline_Transform (&glyph->outline, &invert_y);
     if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
 	_cairo_path_fixed_destroy (path);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     status = _cairo_path_fixed_close_path (path);
-    if (status) {
+    if (unlikely (status)) {
 	_cairo_path_fixed_destroy (path);
 	return status;
     }
 
     *pathp = path;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1931,17 +1830,17 @@ static cairo_int_status_t
     cairo_status_t status;
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
 				                &scaled_font->base.scale);
-    if (status)
+    if (unlikely (status))
 	goto FAIL;
 
     /* Ignore global advance unconditionally */
     load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
 
     if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
 	(info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
 	load_flags |= FT_LOAD_NO_BITMAP;
@@ -2079,24 +1978,26 @@ static cairo_int_status_t
 	cairo_image_surface_t	*surface;
 
 	if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
 	    status = _render_glyph_outline (face, &scaled_font->ft_options.base,
 					    &surface);
 	} else {
 	    status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
 					   &surface);
-	    if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) {
+	    if (likely (status == CAIRO_STATUS_SUCCESS) &&
+		unscaled->have_shape)
+	    {
 		status = _transform_glyph_bitmap (&unscaled->current_shape,
 						  &surface);
-		if (status)
+		if (unlikely (status))
 		    cairo_surface_destroy (&surface->base);
 	    }
 	}
-	if (status)
+	if (unlikely (status))
 	    goto FAIL;
 
 	_cairo_scaled_glyph_set_surface (scaled_glyph,
 					 &scaled_font->base,
 					 surface);
     }
 
     if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
@@ -2128,17 +2029,17 @@ static cairo_int_status_t
 
 	}
 	if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
 	    status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
 					       &path);
 	else
 	    status = CAIRO_INT_STATUS_UNSUPPORTED;
 
-	if (status)
+	if (unlikely (status))
 	    goto FAIL;
 
 	_cairo_scaled_glyph_set_path (scaled_glyph,
 				      &scaled_font->base,
 				      path);
     }
  FAIL:
     _cairo_ft_unscaled_font_unlock_face (unscaled);
@@ -2154,21 +2055,22 @@ static unsigned long
     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
     FT_Face face;
     FT_UInt index;
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
 	return 0;
 
-#ifdef CAIRO_DISABLE_FONTCONFIG
-    index = FT_Get_Char_Index (face, ucs4); 
+#if CAIRO_HAS_FC_FONT
+    index = FcFreeTypeCharIndex (face, ucs4);
 #else
-    index = FcFreeTypeCharIndex (face, ucs4);
+    index = FT_Get_Char_Index (face, ucs4);
 #endif
+
     _cairo_ft_unscaled_font_unlock_face (unscaled);
     return index;
 }
 
 static cairo_int_status_t
 _cairo_ft_load_truetype_table (void	       *abstract_font,
                               unsigned long     tag,
                               long              offset,
@@ -2223,31 +2125,98 @@ static cairo_int_status_t
 	}
     }
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
+static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
-    NULL,
-    _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_index_to_ucs4
 };
 
 /* #cairo_ft_font_face_t */
 
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
+					cairo_font_face_t **out);
+
+static cairo_status_t
+_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				    cairo_font_face_t      **font_face)
+{
+    FcPattern *pattern;
+    int fcslant;
+    int fcweight;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    pattern = FcPatternCreate ();
+    if (!pattern)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    if (!FcPatternAddString (pattern,
+		             FC_FAMILY, (unsigned char *) toy_face->family))
+    {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    switch (toy_face->slant)
+    {
+    case CAIRO_FONT_SLANT_ITALIC:
+        fcslant = FC_SLANT_ITALIC;
+        break;
+    case CAIRO_FONT_SLANT_OBLIQUE:
+	fcslant = FC_SLANT_OBLIQUE;
+        break;
+    case CAIRO_FONT_SLANT_NORMAL:
+    default:
+        fcslant = FC_SLANT_ROMAN;
+        break;
+    }
+
+    if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    switch (toy_face->weight)
+    {
+    case CAIRO_FONT_WEIGHT_BOLD:
+        fcweight = FC_WEIGHT_BOLD;
+        break;
+    case CAIRO_FONT_WEIGHT_NORMAL:
+    default:
+        fcweight = FC_WEIGHT_MEDIUM;
+        break;
+    }
+
+    if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    status = _cairo_ft_font_face_create_for_pattern (pattern, font_face);
+
+ FREE_PATTERN:
+    FcPatternDestroy (pattern);
+
+    return status;
+}
+#endif
+
 static void
 _cairo_ft_font_face_destroy (void *abstract_face)
 {
     cairo_ft_font_face_t *font_face = abstract_face;
 
     cairo_ft_font_face_t *tmp_face = NULL;
     cairo_ft_font_face_t *last_face = NULL;
 
@@ -2294,58 +2263,118 @@ static void
 	    }
 
 	    last_face = tmp_face;
 	}
 
 	_cairo_unscaled_font_destroy (&font_face->unscaled->base);
 	font_face->unscaled = NULL;
     }
+
+#if CAIRO_HAS_FC_FONT
+    if (font_face->pattern)
+	FcPatternDestroy (font_face->pattern);
+#endif
 }
 
 static cairo_status_t
 _cairo_ft_font_face_scaled_font_create (void                     *abstract_face,
 					const cairo_matrix_t       *font_matrix,
 					const cairo_matrix_t       *ctm,
 					const cairo_font_options_t *options,
 					cairo_scaled_font_t       **scaled_font)
 {
-    cairo_ft_font_face_t *font_face = abstract_face;
-    cairo_ft_options_t ft_options;
+    cairo_ft_font_face_t      *font_face = abstract_face;
+    cairo_ft_unscaled_font_t  *unscaled = NULL;
+    cairo_ft_options_t         ft_options;
 
     /* 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?
+     */
+
+#if CAIRO_HAS_FC_FONT
+    /* If we have an unresolved pattern, resolve it and create
+     * unscaled font.  Otherwise, use the ones stored in font_face.
      */
-
-    ft_options = font_face->ft_options;
-
-    return  _cairo_ft_scaled_font_create (font_face->unscaled,
+    if (font_face->pattern) {
+	cairo_status_t status;
+
+	status = _cairo_ft_resolve_pattern (font_face->pattern,
+					    font_matrix,
+					    ctm,
+					    options,
+					    &unscaled,
+					    &ft_options);
+	if (unlikely (status)) {
+	    /* XXX It is possible for a failure to generate the unscaled font
+	     * here could indicate that the font_face itself is broken - for
+	     * which we should propagate the error.
+	     */
+	    *scaled_font = _cairo_scaled_font_create_in_error (status);
+	    return CAIRO_STATUS_SUCCESS;
+	}
+
+    } else
+#endif
+    {
+	unscaled = font_face->unscaled;
+	ft_options = font_face->ft_options;
+    }
+
+    return  _cairo_ft_scaled_font_create (unscaled,
 					  &font_face->base,
 					  font_matrix, ctm,
 					  options, ft_options,
 					  scaled_font);
 }
 
-static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
+const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
     CAIRO_FONT_TYPE_FT,
+#if CAIRO_HAS_FC_FONT
+    _cairo_ft_font_face_create_for_toy,
+#else
+    NULL,
+#endif
     _cairo_ft_font_face_destroy,
-    NULL, /* direct implementation */
     _cairo_ft_font_face_scaled_font_create
 };
 
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
+					cairo_font_face_t **out)
+{
+    cairo_ft_font_face_t *font_face;
+
+    font_face = malloc (sizeof (cairo_ft_font_face_t));
+    if (unlikely (font_face == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    font_face->unscaled = NULL;
+    font_face->next = NULL;
+
+    font_face->pattern = FcPatternDuplicate (pattern);
+    if (unlikely (pattern == NULL)) {
+	free (font_face);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
+
+    *out = &font_face->base;
+    return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
 static cairo_font_face_t *
 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 			    cairo_ft_options_t	     *ft_options)
 {
     cairo_ft_font_face_t *font_face, **prev_font_face;
 
     /* Looked for an existing matching font face */
     for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
@@ -2362,37 +2391,41 @@ static cairo_font_face_t *
 	    /* The font_face has been left in an error state, abandon it. */
 	    *prev_font_face = font_face->next;
 	    break;
 	}
     }
 
     /* No match found, create a new one */
     font_face = malloc (sizeof (cairo_ft_font_face_t));
-    if (!font_face) {
+    if (unlikely (!font_face)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_font_face_t *)&_cairo_font_face_nil;
     }
 
     font_face->unscaled = unscaled;
     _cairo_unscaled_font_reference (&unscaled->base);
 
     font_face->ft_options = *ft_options;
 
     font_face->next = unscaled->faces;
     unscaled->faces = font_face;
 
+#if CAIRO_HAS_FC_FONT
+    font_face->pattern = NULL;
+#endif
+
     _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
 
     return &font_face->base;
 }
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
 /* implement the platform-specific interface */
 
+#if CAIRO_HAS_FC_FONT
 static cairo_status_t
 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
 				   FcPattern                  *pattern)
 {
     FcValue v;
 
     if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
     {
@@ -2500,43 +2533,109 @@ cairo_ft_font_options_substitute (const 
 				  FcPattern                  *pattern)
 {
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	return;
 
     _cairo_ft_font_options_substitute (options, pattern);
 }
 
+static cairo_status_t
+_cairo_ft_resolve_pattern (FcPattern		      *pattern,
+			   const cairo_matrix_t       *font_matrix,
+			   const cairo_matrix_t       *ctm,
+			   const cairo_font_options_t *font_options,
+			   cairo_ft_unscaled_font_t  **unscaled,
+			   cairo_ft_options_t	      *ft_options)
+{
+    cairo_status_t status;
+
+    cairo_matrix_t scale;
+    FcPattern *resolved;
+    cairo_ft_font_transform_t sf;
+    FcResult result;
+
+    scale = *ctm;
+    scale.x0 = scale.y0 = 0;
+    cairo_matrix_multiply (&scale,
+                           font_matrix,
+                           &scale);
+
+    status = _compute_transform (&sf, &scale);
+    if (status)
+	return status;
+
+    pattern = FcPatternDuplicate (pattern);
+
+    if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    status = _cairo_ft_font_options_substitute (font_options, pattern);
+    if (status)
+	goto FREE_PATTERN;
+
+    FcDefaultSubstitute (pattern);
+
+    resolved = FcFontMatch (NULL, pattern, &result);
+    if (!resolved) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_PATTERN;
+    }
+
+    *unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
+    if (!*unscaled) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto FREE_RESOLVED;
+    }
+
+    _get_pattern_ft_options (resolved, ft_options);
+
+FREE_RESOLVED:
+    FcPatternDestroy (resolved);
+
+FREE_PATTERN:
+    FcPatternDestroy (pattern);
+
+    return status;
+}
+
 /**
  * cairo_ft_font_face_create_for_pattern:
- * @pattern: A fully resolved fontconfig
- *   pattern. A pattern can be resolved, by, among other things, calling
- *   FcConfigSubstitute(), FcDefaultSubstitute(), then
- *   FcFontMatch(). Cairo will call FcPatternReference() on this
- *   pattern, so you should not further modify the pattern, but you can
- *   release your reference to the pattern with FcPatternDestroy() if
- *   you no longer need to access it.
+ * @pattern: A fontconfig pattern.  Cairo makes a copy of the pattern
+ * if it needs to.  You are free to modify or free @pattern after this call.
  *
  * 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_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.
+ * font face.  Otherwise the FC_FILE element is checked.  If it's set,
+ * that and the value of the FC_INDEX element (defaults to zero) of @pattern
+ * are used to load a font face from file.
+ *
+ * If both steps from the previous paragraph fails, @pattern will be passed
+ * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
+ * and the resulting font pattern is used.
  *
  * 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
@@ -2545,28 +2644,35 @@ cairo_ft_font_options_substitute (const 
 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;
     cairo_ft_options_t ft_options;
 
     unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
-    if (unscaled == NULL) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_font_face_t *)&_cairo_font_face_nil;
+    if (unlikely (unscaled == NULL)) {
+	cairo_status_t status;
+	/* Store the pattern.  We will resolve it and create unscaled
+	 * font when creating scaled fonts */
+	status = _cairo_ft_font_face_create_for_pattern (pattern,
+							 &font_face);
+	if (unlikely (status))
+	    return (cairo_font_face_t *) &_cairo_font_face_nil;
+
+	return font_face;
     }
 
     _get_pattern_ft_options (pattern, &ft_options);
     font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
     _cairo_unscaled_font_destroy (&unscaled->base);
 
     return font_face;
 }
-#endif /* CAIRO_DISABLE_FONTCONFIG */
+#endif
 
 /**
  * cairo_ft_font_face_create_for_ft_face:
  * @face: A FreeType face object, already opened. This must
  *   be kept around until the face's ref_count drops to
  *   zero and it is freed. Since the face may be referenced
  *   internally to Cairo, the best way to determine when it
  *   is safe to free the face is to pass a
@@ -2613,17 +2719,17 @@ cairo_font_face_t *
 cairo_ft_font_face_create_for_ft_face (FT_Face         face,
 				       int             load_flags)
 {
     cairo_ft_unscaled_font_t *unscaled;
     cairo_font_face_t *font_face;
     cairo_ft_options_t ft_options;
 
     unscaled = _cairo_ft_unscaled_font_create_from_face (face);
-    if (unscaled == NULL) {
+    if (unlikely (unscaled == NULL)) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_font_face_t *)&_cairo_font_face_nil;
     }
 
     ft_options.load_flags = load_flags;
     ft_options.extra_flags = 0;
     _cairo_font_options_init_default (&ft_options.base);
 
@@ -2649,17 +2755,17 @@ cairo_ft_font_face_create_for_ft_face (F
  * 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
+ * code that acquires an FT_Face object with this call must add its
  * own locking to protect any use of that object, (and which also must
  * protect any other calls into cairo as almost any cairo function
  * might result in a call into the freetype library).
  *
  * Return value: The #FT_Face object for @font, scaled appropriately,
  * or %NULL if @scaled_font is in an error state (see
  * cairo_scaled_font_status()) or there is insufficient memory.
  **/
@@ -2674,24 +2780,24 @@ cairo_ft_scaled_font_lock_face (cairo_sc
 	_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) {
+    if (unlikely (face == NULL)) {
 	status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
 	return NULL;
     }
 
     status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
 				                &scaled_font->base.scale);
-    if (status) {
+    if (unlikely (status)) {
 	_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
 	status = _cairo_scaled_font_set_error (&scaled_font->base, status);
 	return NULL;
     }
 
     /* Note: We deliberately release the unscaled font's mutex here,
      * so that we are not holding a lock across two separate calls to
      * cairo function, (which would give the application some
@@ -2755,13 +2861,25 @@ cairo_bool_t
 	return FALSE;
     
     ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
     if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
 	return TRUE;
     return FALSE;
 }
 
+unsigned int
+_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
+{
+    cairo_ft_scaled_font_t *ft_scaled_font;
+
+    if (! _cairo_scaled_font_is_ft (scaled_font))
+	return 0;
+
+    ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
+    return ft_scaled_font->ft_options.load_flags;
+}
+
 void
 _cairo_ft_font_reset_static_data (void)
 {
     _cairo_ft_unscaled_font_map_destroy ();
 }
--- a/gfx/cairo/cairo/src/cairo-ft-private.h
+++ b/gfx/cairo/cairo/src/cairo-ft-private.h
@@ -59,12 +59,15 @@ 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);
 
+cairo_private unsigned int
+_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font);
+
 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
@@ -38,42 +38,45 @@
 #define CAIRO_FT_H
 
 #include "cairo.h"
 
 #if CAIRO_HAS_FT_FONT
 
 /* Fontconfig/Freetype platform-specific font interface */
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#endif
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
-CAIRO_BEGIN_DECLS
+#if CAIRO_HAS_FC_FONT
+#include <fontconfig/fontconfig.h>
+#endif
 
-#ifndef CAIRO_DISABLE_FONTCONFIG
-cairo_public cairo_font_face_t *
-cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
-
-cairo_public void
-cairo_ft_font_options_substitute (const cairo_font_options_t *options,
-				  FcPattern                  *pattern);
-#endif
+CAIRO_BEGIN_DECLS
 
 cairo_public cairo_font_face_t *
 cairo_ft_font_face_create_for_ft_face (FT_Face         face,
 				       int             load_flags);
 
 cairo_public FT_Face
 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
 
 cairo_public void
 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
 
+#if CAIRO_HAS_FC_FONT
+
+cairo_public cairo_font_face_t *
+cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
+
+cairo_public void
+cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+				  FcPattern                  *pattern);
+
+#endif
+
 CAIRO_END_DECLS
 
 #else  /* CAIRO_HAS_FT_FONT */
 # error Cairo was not compiled with support for the freetype font backend
 #endif /* CAIRO_HAS_FT_FONT */
 
 #endif /* CAIRO_FT_H */
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -28,32 +28,32 @@
 #include "cairo-glitz.h"
 #include "cairo-glitz-private.h"
 
 typedef struct _cairo_glitz_surface {
     cairo_surface_t   base;
 
     glitz_surface_t   *surface;
     glitz_format_t    *format;
-    cairo_bool_t      has_clip;
-    cairo_region_t    clip;
+
+    cairo_bool_t       has_clip;
+    glitz_box_t       *clip_boxes;
+    int                num_clip_boxes;
 } cairo_glitz_surface_t;
 
 static const cairo_surface_backend_t *
 _cairo_glitz_surface_get_backend (void);
 
 static cairo_status_t
 _cairo_glitz_surface_finish (void *abstract_surface)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
 
-    if (surface->has_clip) {
-        glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
-        _cairo_region_fini (&surface->clip);
-    }
+    if (surface->clip_boxes)
+	free (surface->clip_boxes);
 
     glitz_surface_destroy (surface->surface);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static glitz_format_name_t
 _glitz_format_from_content (cairo_content_t content)
@@ -84,357 +84,202 @@ static cairo_surface_t *
     glitz_format_t	  *gformat;
 
     drawable = glitz_surface_get_drawable (src->surface);
 
     gformat =
 	glitz_find_standard_format (drawable,
 				    _glitz_format_from_content (content));
     if (!gformat)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	return NULL;
 
     surface = glitz_surface_create (drawable, gformat,
 				    width <= 0 ? 1 : width,
 				    height <= 0 ? 1 : height,
 				    0, NULL);
 
     if (surface == NULL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     crsurface = cairo_glitz_surface_create (surface);
 
     glitz_surface_destroy (surface);
 
     return crsurface;
 }
 
-static cairo_bool_t
-_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
+static cairo_status_t
+_cairo_glitz_get_boxes_from_region (cairo_region_t *region,
+				    glitz_box_t **boxes,
+				    int *nboxes)
 {
-    switch (masks->bpp) {
-    case 32:
-	if (masks->alpha_mask == 0xff000000 &&
-	    masks->red_mask == 0x00ff0000 &&
-	    masks->green_mask == 0x0000ff00 &&
-	    masks->blue_mask == 0x000000ff)
-	{
-	    *format = CAIRO_FORMAT_ARGB32;
-	    return TRUE;
-	}
-	if (masks->alpha_mask == 0x00000000 &&
-	    masks->red_mask == 0x00ff0000 &&
-	    masks->green_mask == 0x0000ff00 &&
-	    masks->blue_mask == 0x000000ff)
-	{
-	    *format = CAIRO_FORMAT_RGB24;
-	    return TRUE;
-	}
-	break;
-    case 8:
-	if (masks->alpha_mask == 0xff)
-	{
-	    *format = CAIRO_FORMAT_A8;
-	    return TRUE;
-	}
-	break;
-    case 1:
-	if (masks->alpha_mask == 0x1)
-	{
-	    *format = CAIRO_FORMAT_A1;
-	    return TRUE;
-	}
-	break;
-    }
-    return FALSE;
-}
+    pixman_box32_t *pboxes;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-static cairo_status_t
-_cairo_glitz_get_boxes_from_region (cairo_region_t *region, glitz_box_t **boxes, int *nboxes)
-{
-    cairo_box_int_t *cboxes;
-    cairo_status_t status;
     int n, i;
 
-    status = _cairo_region_get_boxes (region, &n, &cboxes);
-    if (status)
-	return status;
-
+    n = 0;
+    pboxes = pixman_region32_rectangles (&region->rgn, &n);
     if (n == 0) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto done;
+	*nboxes = 0;
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    *boxes = _cairo_malloc_ab (n, sizeof(glitz_box_t));
-    if (*boxes == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto done;
+    if (n > *nboxes) {
+	*boxes = _cairo_malloc_ab (n, sizeof (glitz_box_t));
+	if (*boxes == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto done;
+	}
     }
 
     for (i = 0; i < n; i++) {
-        (*boxes)[i].x1 = cboxes[i].p1.x;
-        (*boxes)[i].y1 = cboxes[i].p1.y;
-        (*boxes)[i].x2 = cboxes[i].p2.x;
-        (*boxes)[i].y2 = cboxes[i].p2.y;
+        (*boxes)[i].x1 = pboxes[i].x1;
+        (*boxes)[i].y1 = pboxes[i].y1;
+        (*boxes)[i].x2 = pboxes[i].x2;
+        (*boxes)[i].y2 = pboxes[i].y2;
     }
 
     *nboxes = n;
 done:
-    _cairo_region_boxes_fini (region, cboxes);
     return status;
 }
 
 static cairo_status_t
 _cairo_glitz_surface_get_image (cairo_glitz_surface_t   *surface,
 				cairo_rectangle_int_t   *interest,
 				cairo_image_surface_t  **image_out,
 				cairo_rectangle_int_t   *rect_out)
 {
     cairo_image_surface_t *image;
-    int			  x1, y1, x2, y2;
-    int			  width, height;
-    unsigned char	  *pixels;
+    cairo_rectangle_int_t extents;
+    cairo_format_t format;
     cairo_format_masks_t  masks;
     glitz_buffer_t	  *buffer;
     glitz_pixel_format_t  pf;
-    cairo_format_t	  format;
-
-    x1 = 0;
-    y1 = 0;
-    x2 = glitz_surface_get_width (surface->surface);
-    y2 = glitz_surface_get_height (surface->surface);
 
-    if (interest)
-    {
-	if (interest->x > x1)
-	    x1 = interest->x;
-	if (interest->y > y1)
-	    y1 = interest->y;
-	if (interest->x + interest->width < x2)
-	    x2 = interest->x + interest->width;
-	if (interest->y + interest->height < y2)
-	    y2 = interest->y + interest->height;
+    extents.x = 0;
+    extents.y = 0;
+    extents.width  = glitz_surface_get_width (surface->surface);
+    extents.height = glitz_surface_get_height (surface->surface);
 
-	if (x1 >= x2 || y1 >= y2)
-	{
+    if (interest != NULL) {
+	if (! _cairo_rectangle_intersect (&extents, interest)) {
 	    *image_out = NULL;
 	    return CAIRO_STATUS_SUCCESS;
 	}
     }
 
-    width  = x2 - x1;
-    height = y2 - y1;
-
-    if (rect_out)
-    {
-	rect_out->x = x1;
-	rect_out->y = y1;
-	rect_out->width = width;
-	rect_out->height = height;
-    }
+    if (rect_out != NULL)
+	*rect_out = extents;
 
     if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) {
 	if (surface->format->color.red_size > 0) {
-	    masks.bpp = 32;
-
 	    if (surface->format->color.alpha_size > 0)
-		masks.alpha_mask = 0xff000000;
+		format = CAIRO_FORMAT_ARGB32;
 	    else
-		masks.alpha_mask = 0x0;
-
-	    masks.red_mask = 0xff0000;
-	    masks.green_mask = 0xff00;
-	    masks.blue_mask = 0xff;
+		format = CAIRO_FORMAT_RGB24;
 	} else {
-	    masks.bpp = 8;
-	    masks.blue_mask = masks.green_mask = masks.red_mask = 0x0;
-	    masks.alpha_mask = 0xff;
+	    format = CAIRO_FORMAT_A8;
 	}
-    } else {
-	masks.bpp = 32;
-	masks.alpha_mask = 0xff000000;
-	masks.red_mask = 0xff0000;
-	masks.green_mask = 0xff00;
-	masks.blue_mask = 0xff;
-    }
+    } else
+	format = CAIRO_FORMAT_ARGB32;
 
+    image = (cairo_image_surface_t*)
+	cairo_image_surface_create (format, extents.width, extents.height);
+    if (image->base.status)
+	return image->base.status;
+
+    _pixman_format_to_masks (image->pixman_format, &masks);
     pf.fourcc = GLITZ_FOURCC_RGB;
     pf.masks.bpp = masks.bpp;
     pf.masks.alpha_mask = masks.alpha_mask;
-    pf.masks.red_mask = masks.red_mask;
+    pf.masks.red_mask   = masks.red_mask;
     pf.masks.green_mask = masks.green_mask;
-    pf.masks.blue_mask = masks.blue_mask;
+    pf.masks.blue_mask  = masks.blue_mask;
     pf.xoffset = 0;
     pf.skip_lines = 0;
 
     /* XXX: we should eventually return images with negative stride,
        need to verify that libpixman have no problem with this first. */
-    pf.bytes_per_line = (((width * masks.bpp) / 8) + 3) & -4;
+    pf.bytes_per_line = image->stride;
     pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
 
-    pixels = _cairo_malloc_ab (height, pf.bytes_per_line);
-    if (!pixels)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    buffer = glitz_buffer_create_for_data (pixels);
-    if (!buffer) {
-	free (pixels);
+    buffer = glitz_buffer_create_for_data (image->data);
+    if (buffer == NULL) {
+	cairo_surface_destroy (&image->base);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     /* clear out the glitz clip; the clip affects glitz_get_pixels */
     if (surface->has_clip)
 	glitz_surface_set_clip_region (surface->surface,
 				       0, 0, NULL, 0);
 
     glitz_get_pixels (surface->surface,
-		      x1, y1,
-		      width, height,
+		      extents.x, extents.y,
+		      extents.width, extents.height,
 		      &pf,
 		      buffer);
 
     glitz_buffer_destroy (buffer);
 
     /* restore the clip, if any */
     if (surface->has_clip) {
-	glitz_box_t *box;
-	cairo_status_t status;
-        int n;
-
-        status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n);
-        if (status) {
-            free (pixels);
-            return status;
-        }
-
-	glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
-
-        free (box);
+	glitz_surface_set_clip_region (surface->surface,
+				       0, 0,
+				       surface->clip_boxes,
+				       surface->num_clip_boxes);
     }
 
-    /*
-     * Prefer to use a standard pixman format instead of the
-     * general masks case.
-     */
-    if (_CAIRO_MASK_FORMAT (&masks, &format)) {
-	image = (cairo_image_surface_t *)
-	    cairo_image_surface_create_for_data (pixels,
-						 format,
-						 x2 - x1,
-						 y2 - y1,
-						 pf.bytes_per_line);
-	if (image->base.status)
-	    goto FAIL;
-    } else {
-	/*
-	 * XXX This can't work.  We must convert the data to one of the
-	 * supported pixman formats.  Pixman needs another function
-	 * which takes data in an arbitrary format and converts it
-	 * to something supported by that library.
-	 */
-	image = (cairo_image_surface_t *)
-	    _cairo_image_surface_create_with_masks (pixels,
-						    &masks,
-						    x2 - x1,
-						    y2 - y1,
-						    pf.bytes_per_line);
-	if (image->base.status)
-	    goto FAIL;
-    }
-
-    _cairo_image_surface_assume_ownership_of_data (image);
-
     *image_out = image;
 
     return CAIRO_STATUS_SUCCESS;
-
-FAIL:
-    free (pixels);
-    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-}
-
-static void
-cairo_format_get_masks (cairo_format_t  format,
-			uint32_t       *bpp,
-                        uint32_t       *alpha,
-			uint32_t       *red,
-			uint32_t       *green,
-			uint32_t       *blue)
-{
-    *red = 0x0;
-    *green = 0x0;
-    *blue = 0x0;
-    *alpha = 0x0;
-
-    switch (format)
-    {
-    case CAIRO_FORMAT_ARGB32:
-        *alpha = 0xff000000;
-    case CAIRO_FORMAT_RGB24:
-    default:
-	*bpp =   32;
-	*red =   0x00ff0000;
-	*green = 0x0000ff00;
-	*blue =  0x000000ff;
-	break;
-
-    case CAIRO_FORMAT_A8:
-	*bpp = 8;
-        *alpha = 0xff;
-	break;
-
-    case CAIRO_FORMAT_A1:
-	*bpp = 1;
-        *alpha = 0x1;
-	break;
-    }
 }
 
 static cairo_status_t
 _cairo_glitz_surface_set_image (void		      *abstract_surface,
 				cairo_image_surface_t *image,
 				int                    src_x,
 				int                    src_y,
 				int                    width,
 				int                    height,
 				int		       x_dst,
 				int		       y_dst)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
     glitz_buffer_t	  *buffer;
     glitz_pixel_format_t  pf;
-    uint32_t		  bpp, am, rm, gm, bm;
+    cairo_format_masks_t  masks;
     char		  *data;
 
-    cairo_format_get_masks (image->format, &bpp, &am, &rm, &gm, &bm);
+    _pixman_format_to_masks (image->pixman_format, &masks);
 
     pf.fourcc = GLITZ_FOURCC_RGB;
-    pf.masks.bpp = bpp;
-    pf.masks.alpha_mask = am;
-    pf.masks.red_mask = rm;
-    pf.masks.green_mask = gm;
-    pf.masks.blue_mask = bm;
+    pf.masks.bpp = masks.bpp;
+    pf.masks.alpha_mask = masks.alpha_mask;
+    pf.masks.red_mask   = masks.red_mask;
+    pf.masks.green_mask = masks.green_mask;
+    pf.masks.blue_mask  = masks.blue_mask;
     pf.xoffset = src_x;
     pf.skip_lines = src_y;
 
     /* check for negative stride */
-    if (image->stride < 0)
-    {
+    if (image->stride < 0) {
 	pf.bytes_per_line = -image->stride;
 	pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
 	data = (char *) image->data + image->stride * (image->height - 1);
-    }
-    else
-    {
+    } else {
 	pf.bytes_per_line = image->stride;
 	pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
 	data = (char *) image->data;
     }
 
     buffer = glitz_buffer_create_for_data (data);
-    if (!buffer)
+    if (buffer == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     glitz_set_pixels (surface->surface,
 		      x_dst, y_dst,
 		      width, height,
 		      &pf,
 		      buffer);
 
@@ -528,76 +373,60 @@ static cairo_status_t
 	*clone_offset_y = 0;
 	*clone_out = cairo_surface_reference (src);
 
 	return CAIRO_STATUS_SUCCESS;
     }
     else if (_cairo_surface_is_image (src))
     {
 	cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
-	cairo_content_t	      content;
-	cairo_rectangle_int_t image_extent;
-	cairo_rectangle_int_t extent;
-
-	content = _cairo_content_from_format (image_src->format);
 
 	clone = (cairo_glitz_surface_t *)
-	    _cairo_glitz_surface_create_similar (surface, content,
-						 image_src->width,
-						 image_src->height);
+	    _cairo_glitz_surface_create_similar (surface, src->content,
+						 width, height);
 	if (clone == NULL)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	if (clone->base.status)
 	    return clone->base.status;
 
-	image_extent.x = 0;
-	image_extent.y = 0;
-	image_extent.width = image_src->width;
-	image_extent.height = image_src->height;
-	extent.x = src_x;
-	extent.y = src_y;
-	extent.width = width;
-	extent.height = height;
-
-	_cairo_rectangle_intersect(&extent, &image_extent);
-
 	status = _cairo_glitz_surface_set_image (clone, image_src,
-					         extent.x, extent.y,
-						 extent.width, extent.height,
-						 extent.x, extent.y);
+					         src_x, src_y,
+						 width, height,
+						 0, 0);
 	if (status) {
 	    cairo_surface_destroy (&clone->base);
 	    return status;
 	}
 
 	*clone_out = &clone->base;
-
+	*clone_offset_x = src_x;
+	*clone_offset_y = src_y;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static void
 _cairo_glitz_surface_set_matrix (cairo_glitz_surface_t *surface,
 				 cairo_matrix_t	       *matrix)
 {
     glitz_transform_t transform;
 
-    transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
-    transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
-    transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
+    transform.matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
+    transform.matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
+    transform.matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
 
-    transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
-    transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
-    transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
+    transform.matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
+    transform.matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
+    transform.matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
 
     transform.matrix[2][0] = 0;
     transform.matrix[2][1] = 0;
-    transform.matrix[2][2] = _cairo_fixed_from_double (1);
+    transform.matrix[2][2] = _cairo_fixed_16_16_from_double (1);
 
     glitz_surface_set_transform (surface->surface, &transform);
 }
 
 static glitz_operator_t
 _glitz_operator (cairo_operator_t op)
 {
     switch (op) {
@@ -713,17 +542,17 @@ typedef struct _cairo_glitz_surface_attr
     glitz_fill_t		fill;
     glitz_filter_t		filter;
     glitz_fixed16_16_t		*params;
     int				n_params;
     cairo_bool_t		acquired;
 } cairo_glitz_surface_attributes_t;
 
 static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surface (cairo_pattern_t	              *pattern,
+_cairo_glitz_pattern_acquire_surface (const cairo_pattern_t	       *pattern,
 				      cairo_glitz_surface_t	       *dst,
 				      int			       x,
 				      int			       y,
 				      unsigned int		       width,
 				      unsigned int		       height,
 				      cairo_glitz_surface_t	 **surface_out,
 				      cairo_glitz_surface_attributes_t *attr)
 {
@@ -831,32 +660,32 @@ static cairo_int_status_t
 			  (glitz_pixel_format_t *)&format, buffer);
 
 	glitz_buffer_destroy (buffer);
 
 	if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
 	{
 	    cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
 
-	    params[0] = grad->p1.x;
-	    params[1] = grad->p1.y;
-	    params[2] = grad->p2.x;
-	    params[3] = grad->p2.y;
+	    params[0] = _cairo_fixed_to_16_16 (grad->p1.x);
+	    params[1] = _cairo_fixed_to_16_16 (grad->p1.y);
+	    params[2] = _cairo_fixed_to_16_16 (grad->p2.x);
+	    params[3] = _cairo_fixed_to_16_16 (grad->p2.y);
 	    attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
 	}
 	else
 	{
 	    cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
 
-	    params[0] = grad->c1.x;
-	    params[1] = grad->c1.y;
-	    params[2] = grad->r1;
-	    params[3] = grad->c2.x;
-	    params[4] = grad->c2.y;
-	    params[5] = grad->r2;
+	    params[0] = _cairo_fixed_to_16_16 (grad->c1.x);
+	    params[1] = _cairo_fixed_to_16_16 (grad->c1.y);
+	    params[2] = _cairo_fixed_to_16_16 (grad->r1);
+	    params[3] = _cairo_fixed_to_16_16 (grad->c2.x);
+	    params[4] = _cairo_fixed_to_16_16 (grad->c2.y);
+	    params[5] = _cairo_fixed_to_16_16 (grad->r2);
 	    attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
 	}
 
 	switch (pattern->extend) {
 	case CAIRO_EXTEND_NONE:
 	    attr->fill = GLITZ_FILL_TRANSPARENT;
 	    break;
 	case CAIRO_EXTEND_REPEAT:
@@ -932,29 +761,29 @@ static cairo_int_status_t
     }
 
     *surface_out = src;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_glitz_pattern_release_surface (cairo_pattern_t		      *pattern,
+_cairo_glitz_pattern_release_surface (const cairo_pattern_t	      *pattern,
 				      cairo_glitz_surface_t	      *surface,
 				      cairo_glitz_surface_attributes_t *attr)
 {
     if (attr->acquired)
 	_cairo_pattern_release_surface (pattern, &surface->base, &attr->base);
     else
 	cairo_surface_destroy (&surface->base);
 }
 
 static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t	                *src,
-				       cairo_pattern_t	                *mask,
+_cairo_glitz_pattern_acquire_surfaces (const cairo_pattern_t	       *src,
+				       const cairo_pattern_t	       *mask,
 				       cairo_glitz_surface_t	        *dst,
 				       int			        src_x,
 				       int			        src_y,
 				       int			        mask_x,
 				       int			        mask_y,
 				       unsigned int		        width,
 				       unsigned int		        height,
 				       cairo_glitz_surface_t	    **src_out,
@@ -980,47 +809,41 @@ static cairo_int_status_t
 	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, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
 	mask = NULL;
-    } else {
-	status = _cairo_pattern_init_copy (&tmp.base, src);
-	if (status)
-	    return status;
+	src = &tmp.base;
     }
 
-    status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+    status = _cairo_glitz_pattern_acquire_surface (src, dst,
 						   src_x, src_y,
 						   width, height,
 						   src_out, sattr);
 
-    _cairo_pattern_fini (&tmp.base);
+    if (src == &tmp.base)
+	_cairo_pattern_fini (&tmp.base);
 
     if (status)
 	return status;
 
     if (mask)
     {
-	status = _cairo_pattern_init_copy (&tmp.base, mask);
-	if (status)
-	    return status;
-
-	status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+	status = _cairo_glitz_pattern_acquire_surface (mask, dst,
 						       mask_x, mask_y,
 						       width, height,
 						       mask_out, mattr);
 
-	if (status)
-	    _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr);
-
-	_cairo_pattern_fini (&tmp.base);
+	if (status) {
+	    /* XXX src == &tmp.base -> invalid (currently inconsequential) */
+	    _cairo_glitz_pattern_release_surface (src, *src_out, sattr);
+	}
 
 	return status;
     }
     else
     {
 	*mask_out = NULL;
     }
 
@@ -1034,18 +857,18 @@ static void
     _cairo_glitz_surface_set_matrix (surface, &a->base.matrix);
     glitz_surface_set_fill (surface->surface, a->fill);
     glitz_surface_set_filter (surface->surface, a->filter,
 			      a->params, a->n_params);
 }
 
 static cairo_int_status_t
 _cairo_glitz_surface_composite (cairo_operator_t op,
-				cairo_pattern_t  *src_pattern,
-				cairo_pattern_t  *mask_pattern,
+				const cairo_pattern_t *src_pattern,
+				const cairo_pattern_t *mask_pattern,
 				void		 *abstract_dst,
 				int		 src_x,
 				int		 src_y,
 				int		 mask_x,
 				int		 mask_y,
 				int		 dst_x,
 				int		 dst_y,
 				unsigned int	 width,
@@ -1082,190 +905,258 @@ static cairo_int_status_t
 			 mask->surface,
 			 dst->surface,
 			 src_x + src_attr.base.x_offset,
 			 src_y + src_attr.base.y_offset,
 			 mask_x + mask_attr.base.x_offset,
 			 mask_y + mask_attr.base.y_offset,
 			 dst_x, dst_y,
 			 width, height);
-
-	if (mask_attr.n_params)
-	    free (mask_attr.params);
-
-	_cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr);
     }
     else
     {
 	glitz_composite (_glitz_operator (op),
 			 src->surface,
 			 NULL,
 			 dst->surface,
 			 src_x + src_attr.base.x_offset,
 			 src_y + src_attr.base.y_offset,
 			 0, 0,
 			 dst_x, dst_y,
 			 width, height);
     }
 
+    if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (status == CAIRO_STATUS_SUCCESS &&
+	! _cairo_operator_bounded_by_source (op))
+    {
+	int src_width, src_height;
+	int mask_width, mask_height;
+
+	src_width = glitz_surface_get_width (src->surface);
+	src_height = glitz_surface_get_height (src->surface);
+	if (mask)
+	{
+	    mask_width = glitz_surface_get_width (mask->surface);
+	    mask_height = glitz_surface_get_height (mask->surface);
+	}
+	else
+	{
+	    mask_width = 0;
+	    mask_height = 0;
+	}
+	status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+							   &src_attr.base,
+							   src_width, src_height,
+							   mask ? &mask_attr.base : NULL,
+							   mask_width, mask_height,
+							   src_x, src_y,
+							   mask_x, mask_y,
+							   dst_x, dst_y, width, height);
+    }
+
+    if (mask)
+    {
+	if (mask_attr.n_params)
+	    free (mask_attr.params);
+
+	_cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr);
+    }
+
     if (src_attr.n_params)
 	free (src_attr.params);
 
     _cairo_glitz_pattern_release_surface (src_pattern, src, &src_attr);
 
-    if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_glitz_surface_fill_rectangles (void		      *abstract_dst,
 				      cairo_operator_t	       op,
 				      const cairo_color_t     *color,
 				      cairo_rectangle_int_t   *rects,
 				      int		       n_rects)
 {
     cairo_glitz_surface_t *dst = abstract_dst;
     cairo_glitz_surface_t *src;
+    glitz_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (glitz_rectangle_t)];
+    glitz_rectangle_t *glitz_rects = stack_rects;
+    glitz_rectangle_t *current_rect;
+    int i;
+
+    if (n_rects > ARRAY_LENGTH (stack_rects)) {
+        glitz_rects = _cairo_malloc_ab (n_rects, sizeof (glitz_rectangle_t));
+        if (glitz_rects == NULL)
+            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    for (i = 0; i < n_rects; i++) {
+        glitz_rects[i].x = rects[i].x;
+        glitz_rects[i].y = rects[i].y;
+        glitz_rects[i].width = rects[i].width;
+        glitz_rects[i].height = rects[i].height;
+    }
 
     switch (op) {
+    case CAIRO_OPERATOR_CLEAR:
     case CAIRO_OPERATOR_SOURCE: {
 	glitz_color_t glitz_color;
+	glitz_format_t *format;
 
 	glitz_color.red = color->red_short;
 	glitz_color.green = color->green_short;
 	glitz_color.blue = color->blue_short;
 	glitz_color.alpha = color->alpha_short;
 
-	glitz_set_rectangles (dst->surface, &glitz_color,
-			      (glitz_rectangle_t *) rects, n_rects);
-    } break;
-    case CAIRO_OPERATOR_CLEAR: {
-	static const glitz_color_t glitz_color = { 0, 0, 0, 0 };
+	/*
+	 * XXX even if the dst surface don't have an alpha channel, the
+	 * above alpha still effect the dst surface because the
+	 * underlying glitz drawable may have an alpha channel. So
+	 * replacing the color with an opaque one is needed.
+	 */
+	format = glitz_surface_get_format (dst->surface);
+	if (format->color.alpha_size == 0)
+	    glitz_color.alpha = 0xffff;
 
-	glitz_set_rectangles (dst->surface, &glitz_color,
-			      (glitz_rectangle_t *) rects, n_rects);
+        glitz_set_rectangles (dst->surface, &glitz_color,
+                              glitz_rects, n_rects);
     } break;
     case CAIRO_OPERATOR_SATURATE:
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     case CAIRO_OPERATOR_OVER:
     case CAIRO_OPERATOR_IN:
     case CAIRO_OPERATOR_OUT:
     case CAIRO_OPERATOR_ATOP:
     case CAIRO_OPERATOR_DEST:
     case CAIRO_OPERATOR_DEST_OVER:
     case CAIRO_OPERATOR_DEST_IN:
     case CAIRO_OPERATOR_DEST_OUT:
     case CAIRO_OPERATOR_DEST_ATOP:
     case CAIRO_OPERATOR_XOR:
     case CAIRO_OPERATOR_ADD:
     default:
 	if (_glitz_ensure_target (dst->surface))
+	{
+	    if (glitz_rects != stack_rects)
+		free (glitz_rects);
 	    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);
 	if (src->base.status)
+	{
+	    if (glitz_rects != stack_rects)
+		free (glitz_rects);
 	    return src->base.status;
+	}
 
 	glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
 
+	current_rect = glitz_rects;
 	while (n_rects--)
 	{
 	    glitz_composite (_glitz_operator (op),
 			     src->surface,
 			     NULL,
 			     dst->surface,
 			     0, 0,
 			     0, 0,
-			     rects->x, rects->y,
-			     rects->width, rects->height);
-	    rects++;
+			     current_rect->x, current_rect->y,
+			     current_rect->width, current_rect->height);
+	    current_rect++;
 	}
 
 	cairo_surface_destroy (&src->base);
 	break;
     }
 
+    if (glitz_rects != stack_rects)
+	free (glitz_rects);
+
     if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_glitz_surface_composite_trapezoids (cairo_operator_t  op,
-					   cairo_pattern_t   *pattern,
+					   const cairo_pattern_t *pattern,
 					   void		     *abstract_dst,
 					   cairo_antialias_t antialias,
 					   int		     src_x,
 					   int		     src_y,
 					   int		     dst_x,
 					   int		     dst_y,
 					   unsigned int	     width,
 					   unsigned int	     height,
 					   cairo_trapezoid_t *traps,
 					   int		     n_traps)
 {
-    cairo_pattern_union_t	     tmp_src_pattern;
-    cairo_pattern_t		     *src_pattern;
     cairo_glitz_surface_attributes_t attributes;
     cairo_glitz_surface_t	     *dst = abstract_dst;
     cairo_glitz_surface_t	     *src;
     cairo_glitz_surface_t	     *mask = NULL;
     glitz_buffer_t		     *buffer = NULL;
     void			     *data = NULL;
     cairo_int_status_t		     status;
     unsigned short		     alpha;
+    pixman_trapezoid_t		 stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
+    pixman_trapezoid_t		*pixman_traps = stack_traps;
+    int i;
 
     if (antialias != CAIRO_ANTIALIAS_DEFAULT &&
 	antialias != CAIRO_ANTIALIAS_GRAY)
+    {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (dst->base.status)
-	return dst->base.status;
+    }
 
     if (op == CAIRO_OPERATOR_SATURATE)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (_glitz_ensure_target (dst->surface))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
-    {
-	status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
-	if (status)
-	    return status;
+    /* Convert traps to pixman traps */
+    if (n_traps > ARRAY_LENGTH (stack_traps)) {
+	pixman_traps = _cairo_malloc_ab (n_traps, sizeof (pixman_trapezoid_t));
+	if (pixman_traps == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-	status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
-						       dst,
-						       src_x, src_y,
-						       width, height,
-						       &src, &attributes);
-	src_pattern = &tmp_src_pattern.base;
+    for (i = 0; i < n_traps; i++) {
+	pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
+	pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
+	pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
+	pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
+	pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
+	pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
+	pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
+	pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
+	pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
+	pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
     }
-    else
-    {
-	status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
-						       src_x, src_y,
-						       width, height,
-						       &src, &attributes);
-	src_pattern = pattern;
-    }
+
+    status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
+						   src_x, src_y,
+						   width, height,
+						   &src, &attributes);
+    if (status)
+	goto FAIL;
+
     alpha = 0xffff;
 
-    if (status)
-	return status;
-
-    if (op == CAIRO_OPERATOR_ADD || n_traps <= 1)
-    {
+    if (op == CAIRO_OPERATOR_ADD || n_traps <= 1) {
 	static const glitz_color_t	clear_black = { 0, 0, 0, 0 };
 	glitz_color_t		color;
 	glitz_geometry_format_t	format;
 	int			n_trap_added;
 	int			offset = 0;
 	int			data_size = 0;
 	int			size = 30 * n_traps; /* just a guess */
 
@@ -1277,143 +1168,124 @@ static cairo_int_status_t
 	format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X;
 	format.vertex.mask.offset = 2 * sizeof (glitz_float_t);
 
 	mask = (cairo_glitz_surface_t *)
 	    _cairo_glitz_surface_create_similar (&dst->base,
 						 CAIRO_CONTENT_ALPHA,
 						 2, 1);
 	if (mask == NULL) {
-	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
-	    if (src_pattern == &tmp_src_pattern.base)
-		_cairo_pattern_fini (&tmp_src_pattern.base);
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	    status =  CAIRO_INT_STATUS_UNSUPPORTED;
+	    goto FAIL;
 	}
 	if (mask->base.status) {
-	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
-	    if (src_pattern == &tmp_src_pattern.base)
-		_cairo_pattern_fini (&tmp_src_pattern.base);
-
-	    return mask->base.status;
+	    status = mask->base.status;
+	    goto FAIL;
 	}
 
 	color.red = color.green = color.blue = color.alpha = 0xffff;
 
 	glitz_set_rectangle (mask->surface, &clear_black, 0, 0, 1, 1);
 	glitz_set_rectangle (mask->surface, &color, 1, 0, 1, 1);
 
 	glitz_surface_set_fill (mask->surface, GLITZ_FILL_NEAREST);
 	glitz_surface_set_filter (mask->surface,
 				  GLITZ_FILTER_BILINEAR,
 				  NULL, 0);
 
 	size *= format.vertex.bytes_per_vertex;
 
-	while (n_traps)
-	{
-	    if (data_size < size)
-	    {
+	while (n_traps) {
+	    if (data_size < size) {
 		void *p;
+
 		data_size = size;
 		p = realloc (data, data_size);
-		if (!p)
-		{
-		    _cairo_glitz_pattern_release_surface (src_pattern, src,
-							  &attributes);
-		    if (src_pattern == &tmp_src_pattern.base)
-			_cairo_pattern_fini (&tmp_src_pattern.base);
-		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		if (p == NULL) {
+		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		    goto FAIL;
 		}
 		data = p;
 
 		if (buffer)
 		    glitz_buffer_destroy (buffer);
 
 		buffer = glitz_buffer_create_for_data (data);
-		if (!buffer) {
+		if (buffer == NULL) {
+		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 		    free (data);
-		    _cairo_glitz_pattern_release_surface (src_pattern, src,
-							  &attributes);
-		    if (src_pattern == &tmp_src_pattern.base)
-			_cairo_pattern_fini (&tmp_src_pattern.base);
-		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		    goto FAIL;
 		}
 	    }
 
 	    offset +=
 		glitz_add_trapezoids (buffer,
 				      offset, size - offset,
 				      format.vertex.type, mask->surface,
-				      (glitz_trapezoid_t *) traps, n_traps,
+				      (glitz_trapezoid_t *) pixman_traps, n_traps,
 				      &n_trap_added);
 
 	    n_traps -= n_trap_added;
 	    traps   += n_trap_added;
 	    size    *= 2;
 	}
 
 	glitz_set_geometry (dst->surface,
 			    GLITZ_GEOMETRY_TYPE_VERTEX,
 			    &format, buffer);
 	glitz_set_array (dst->surface, 0, 3,
 			 offset / format.vertex.bytes_per_vertex,
 			 0, 0);
-    }
-    else
-    {
+    } else {
 	cairo_image_surface_t *image;
 	unsigned char	      *ptr;
 	int		      stride;
 
 	stride = (width + 3) & -4;
 	data = calloc (stride, height);
-	if (!data)
-	{
-	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
-	    if (src_pattern == &tmp_src_pattern.base)
-		_cairo_pattern_fini (&tmp_src_pattern.base);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (data == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto FAIL;
 	}
 
 	/* using negative stride */
 	ptr = (unsigned char *) data + stride * (height - 1);
 
 	image = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (ptr,
 						 CAIRO_FORMAT_A8,
 						 width, height,
 						 -stride);
-	if (image->base.status)
-	{
-	    cairo_surface_destroy (&src->base);
+	status = image->base.status;
+	if (status) {
 	    free (data);
-	    return image->base.status;
+	    goto FAIL;
 	}
 
 	pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
-                               n_traps, (pixman_trapezoid_t *) traps);
+                               n_traps, (pixman_trapezoid_t *) pixman_traps);
 
 	mask = (cairo_glitz_surface_t *)
 	    _cairo_surface_create_similar_scratch (&dst->base,
 						   CAIRO_CONTENT_ALPHA,
 						   width, height);
-	if (mask->base.status) {
-	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+	status = mask->base.status;
+	if (status) {
 	    free (data);
 	    cairo_surface_destroy (&image->base);
-	    return mask->base.status;
+	    goto FAIL;
 	}
 
 	status = _cairo_glitz_surface_set_image (mask, image,
 		                                 0, 0, width, height, 0, 0);
 
-	cairo_surface_destroy(&image->base);
+	cairo_surface_destroy (&image->base);
 
 	if (status)
-	    return status;
+	    goto FAIL;
     }
 
     _cairo_glitz_surface_set_attributes (src, &attributes);
 
     glitz_composite (_glitz_operator (op),
 		     src->surface,
 		     mask->surface,
 		     dst->surface,
@@ -1430,86 +1302,82 @@ static cairo_int_status_t
 			GLITZ_GEOMETRY_TYPE_NONE,
 			NULL, NULL);
 
     if (buffer)
 	glitz_buffer_destroy (buffer);
 
     free (data);
 
-    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
-    if (src_pattern == &tmp_src_pattern.base)
-	_cairo_pattern_fini (&tmp_src_pattern.base);
+    if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) {
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	goto FAIL;
+    }
 
-    if (mask)
+    if (! _cairo_operator_bounded_by_mask (op)) {
+	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+								 &attributes.base,
+								 glitz_surface_get_width  (src->surface),
+								 glitz_surface_get_height (src->surface),
+								 width, height,
+								 src_x, src_y,
+								 0, 0,
+								 dst_x, dst_y,
+								 width, height);
+    }
+
+FAIL:
+    _cairo_glitz_pattern_release_surface (pattern, src, &attributes);
+
+    if (mask != NULL)
 	cairo_surface_destroy (&mask->base);
 
-    if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (pixman_traps != stack_traps)
+	free (pixman_traps);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static cairo_int_status_t
 _cairo_glitz_surface_set_clip_region (void		*abstract_surface,
                                       cairo_region_t	*region)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
 
-    if (region)
-    {
-	glitz_box_t *box;
-	int	    n;
+    if (region != NULL) {
 	cairo_status_t status;
 
-	if (!surface->has_clip) {
-            _cairo_region_init (&surface->clip);
-            surface->has_clip = TRUE;
-        }
-
-	status = _cairo_region_copy (&surface->clip, region);
-	if (status) {
-            _cairo_region_fini (&surface->clip);
-	    surface->has_clip = FALSE;
+	status = _cairo_glitz_get_boxes_from_region (region,
+						     &surface->clip_boxes,
+						     &surface->num_clip_boxes);
+	if (status)
             return status;
-        }
 
-	status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n);
-	if (status) {
-            _cairo_region_fini (&surface->clip);
-	    surface->has_clip = FALSE;
-            return status;
-        }
-
-	glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
-
-        free (box);
-    }
-    else
-    {
+	glitz_surface_set_clip_region (surface->surface,
+				       0, 0,
+				       surface->clip_boxes,
+				       surface->num_clip_boxes);
+	surface->has_clip = TRUE;
+    } else {
 	glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);