b=453765; Upgrade cairo to 1.7.4-136-g5ea2555; r=me
☠☠ backed out by 05d84aa9ca1c ☠ ☠
authorVladimir Vukicevic <vladimir@pobox.com>
Thu, 04 Sep 2008 21:44:42 -0700
changeset 18829 6014c4fca4a141d791c1d012a269ad35e4f73218
parent 18828 0094ca20c1929f8387d325ceb3b260728c5dafc0
child 18830 bc244c4d2fbdd79921a62c424dbf5b8bda2724ed
child 18831 05d84aa9ca1c6ea0cfa30f54e0006b5e28785ccd
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs453765
milestone1.9.1b1pre
b=453765; Upgrade cairo to 1.7.4-136-g5ea2555; r=me
gfx/cairo/README
gfx/cairo/cairo-version-fixes.patch
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-cache.c
gfx/cairo/cairo/src/cairo-cff-subset.c
gfx/cairo/cairo/src/cairo-clip-private.h
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-compiler-private.h
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-features-win32.h
gfx/cairo/cairo/src/cairo-features.h.in
gfx/cairo/cairo/src/cairo-font-face.c
gfx/cairo/cairo/src/cairo-font-options.c
gfx/cairo/cairo/src/cairo-freelist-private.h
gfx/cairo/cairo/src/cairo-ft-font.c
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-misc.c
gfx/cairo/cairo/src/cairo-mutex-impl-private.h
gfx/cairo/cairo/src/cairo-mutex-private.h
gfx/cairo/cairo/src/cairo-mutex-type-private.h
gfx/cairo/cairo/src/cairo-no-features.h
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-fixed-private.h
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-operators-private.h
gfx/cairo/cairo/src/cairo-pdf-operators.c
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-pen.c
gfx/cairo/cairo/src/cairo-png.c
gfx/cairo/cairo/src/cairo-ps-surface-private.h
gfx/cairo/cairo/src/cairo-ps-surface.c
gfx/cairo/cairo/src/cairo-quartz-font.c
gfx/cairo/cairo/src/cairo-reference-count-private.h
gfx/cairo/cairo/src/cairo-region-private.h
gfx/cairo/cairo/src/cairo-rename.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-truetype-subset-private.h
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-private.h
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h
gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-unicode.c
gfx/cairo/cairo/src/cairo-user-font-private.h
gfx/cairo/cairo/src/cairo-user-font.c
gfx/cairo/cairo/src/cairo-version.c
gfx/cairo/cairo/src/cairo-version.h
gfx/cairo/cairo/src/cairo-wideint-type-private.h
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-xlib-display.c
gfx/cairo/cairo/src/cairo-xlib-private.h
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface-private.h
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/check-link.c
gfx/cairo/cairo/src/test-meta-surface.c
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/clip-clone.patch
gfx/cairo/libpixman/src/Makefile.in
gfx/cairo/libpixman/src/pixman-combine32.h
gfx/cairo/libpixman/src/pixman-combine64.h
gfx/cairo/libpixman/src/pixman-mmx.c
gfx/cairo/libpixman/src/pixman-pict.c
gfx/cairo/libpixman/src/pixman-private.h
gfx/cairo/libpixman/src/pixman-sse.c
gfx/cairo/libpixman/src/pixman-sse.h
gfx/cairo/libpixman/src/pixman-sse2.c
gfx/cairo/libpixman/src/pixman-sse2.h
gfx/cairo/libpixman/src/pixman-utils.c
gfx/cairo/libpixman/src/pixman-version.h
gfx/cairo/libpixman/src/pixman.h
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,18 +2,18 @@ Snapshots of cairo and glitz for mozilla
 
 We only include the relevant parts of each release (generally, src/*.[ch]),
 as we have Makefile.in's that integrate into the Mozilla build system.  For
 documentation and similar, please see the official tarballs at
 http://www.cairographics.org/.
 
 VERSIONS:
 
-  cairo (1.6.4-350-g1a9809b)
-  pixman (pixman-0.11.8-7-gdb3fb5e)
+  cairo (1.7.4-136-g5ea2555)
+  pixman (pixman-0.11.8-17-gf9d3f37)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
 ==== Patches ====
 
 Some specific things:
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo-version-fixes.patch
@@ -0,0 +1,26 @@
+diff --git a/gfx/cairo/cairo/src/cairo-version.c b/gfx/cairo/cairo/src/cairo-version.c
+--- a/gfx/cairo/cairo/src/cairo-version.c
++++ b/gfx/cairo/cairo/src/cairo-version.c
+@@ -42,7 +42,7 @@
+ 
+ /* get the "real" version info instead of dummy cairo-version.h */
+ #undef CAIRO_VERSION_H
+-#include "../cairo-version.h"
++#include "cairo-features.h"
+ 
+ /**
+  * cairo_version:
+diff --git a/gfx/cairo/cairo/src/cairo-version.h b/gfx/cairo/cairo/src/cairo-version.h
+--- a/gfx/cairo/cairo/src/cairo-version.h
++++ b/gfx/cairo/cairo/src/cairo-version.h
+@@ -7,8 +7,10 @@
+ #ifndef CAIRO_VERSION_H
+ #define CAIRO_VERSION_H
+ 
++#if 0
+ #define CAIRO_VERSION_MAJOR USE_cairo_version_OR_cairo_version_string_INSTEAD
+ #define CAIRO_VERSION_MINOR USE_cairo_version_OR_cairo_version_string_INSTEAD
+ #define CAIRO_VERSION_MICRO USE_cairo_version_OR_cairo_version_string_INSTEAD
++#endif
+ 
+ #endif
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -114,20 +114,21 @@ CSRCS   = \
         cairo-slope.c \
         cairo-spline.c \
         cairo-stroke-style.c \
         cairo-surface.c \
         cairo-surface-fallback.c \
         cairo-traps.c \
         cairo-unicode.c \
 	cairo-user-font.c \
+	cairo-version.c \
         cairo-wideint.c \
         $(NULL)
 
-EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
+EXPORTS = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
 
 # cairo-type1-subset.c should be here, but it's only supported on freetype platforms
 
 PSPDF_BASE_CSRCS = \
 	cairo-base85-stream.c \
 	cairo-type1-fallback.c \
 	cairo-type3-glyph-surface.c \
 	cairo-truetype-subset.c \
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -616,17 +616,17 @@ static cairo_int_status_t
     return status;
 }
 
 static cairo_bool_t
 _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
 
-    return _cairo_surface_has_show_text_glyphs (surface->target);
+    return cairo_surface_has_show_text_glyphs (surface->target);
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
 					  cairo_operator_t	     op,
 					  cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -234,60 +234,53 @@ cairo_bool_t
 }
 
 /**
  * _cairo_cache_remove_random:
  * @cache: a cache
  *
  * Remove a random entry from the cache.
  *
- * Return value: %CAIRO_STATUS_SUCCESS if an entry was successfully
- * removed. %CAIRO_INT_STATUS_CACHE_EMPTY if there are no entries that
- * can be removed.
+ * Return value: %TRUE if an entry was successfully removed.
+ * %FALSE if there are no entries that can be removed.
  **/
-static cairo_int_status_t
+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)
-	return CAIRO_INT_STATUS_CACHE_EMPTY;
+	return FALSE;
 
     _cairo_cache_remove (cache, entry);
 
-    return CAIRO_STATUS_SUCCESS;
+    return TRUE;
 }
 
 /**
  * _cairo_cache_shrink_to_accommodate:
  * @cache: a cache
  * @additional: additional size requested in bytes
  *
  * If cache is not frozen, eject entries randomly until the size of
  * the cache is at least @additional bytes less than
  * cache->max_size. That is, make enough room to accommodate a new
  * entry of size @additional.
  **/
 static void
 _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
-				   unsigned long  additional)
+				    unsigned long  additional)
 {
-    cairo_int_status_t status;
-
     if (cache->freeze_count)
 	return;
 
     while (cache->size + additional > cache->max_size) {
-	status = _cairo_cache_remove_random (cache);
-	if (status) {
-	    if (status == CAIRO_INT_STATUS_CACHE_EMPTY)
-		return;
-	    ASSERT_NOT_REACHED;
-	}
+	if (! _cairo_cache_remove_random (cache))
+	    return;
     }
 }
 
 /**
  * _cairo_cache_insert:
  * @cache: a cache
  * @entry: an entry to be inserted
  *
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -36,16 +36,19 @@
 
 /*
  * Useful links:
  * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
  */
 
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 #include <string.h>
 
 /* CFF Dict Operators. If the high byte is 0 the command is encoded
  * with a single byte. */
 #define BASEFONTNAME_OP  0x0c16
 #define CIDCOUNT_OP      0x0c22
@@ -2277,8 +2280,10 @@ cairo_status_t
 
 void
 _cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
 {
     free (subset->base_font);
     free (subset->widths);
     free (subset->data);
 }
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-clip-private.h
+++ b/gfx/cairo/cairo/src/cairo-clip-private.h
@@ -31,18 +31,21 @@
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  */
 
 #ifndef CAIRO_CLIP_PRIVATE_H
 #define CAIRO_CLIP_PRIVATE_H
 
+#include "cairo-types-private.h"
 #include "cairo-compiler-private.h"
 #include "cairo-path-fixed-private.h"
+#include "cairo-reference-count-private.h"
+#include "cairo-region-private.h"
 
 extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
 
 struct _cairo_clip_path {
     cairo_reference_count_t	 ref_count;
     cairo_path_fixed_t		 path;
     cairo_fill_rule_t		 fill_rule;
     double			 tolerance;
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -54,17 +54,17 @@ void
     else
 	clip->mode = CAIRO_CLIP_MODE_MASK;
 
     clip->all_clipped = FALSE;
 
     clip->surface = NULL;
     clip->surface_rect.x = 0;
     clip->surface_rect.y = 0;
-    clip->surface_rect.width = 0;
+    clip->surface_rect.width  = 0;
     clip->surface_rect.height = 0;
 
     clip->serial = 0;
 
     _cairo_region_init (&clip->region);
     clip->has_region = FALSE;
 
     clip->path = NULL;
@@ -81,16 +81,17 @@ cairo_status_t
     clip->surface_rect = other->surface_rect;
 
     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) {
 	    _cairo_region_fini (&clip->region);
 	    cairo_surface_destroy (clip->surface);
 	    return status;
 	}
         clip->has_region = TRUE;
     } else {
@@ -375,24 +376,23 @@ static cairo_int_status_t
     if (clip->mode != CAIRO_CLIP_MODE_REGION)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     status = _cairo_traps_extract_region (traps, &region);
 
     if (status)
 	return status;
 
-    status = CAIRO_STATUS_SUCCESS;
-
     if (!clip->has_region) {
         status = _cairo_region_copy (&clip->region, &region);
 	if (status == CAIRO_STATUS_SUCCESS)
 	    clip->has_region = TRUE;
     } else {
 	cairo_region_t intersection;
+
         _cairo_region_init (&intersection);
 
 	status = _cairo_region_intersect (&intersection,
 		                         &clip->region,
 		                         &region);
 
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = _cairo_region_copy (&clip->region, &intersection);
@@ -722,17 +722,17 @@ static cairo_bool_t
     double y1 = clip_rect->y;
     double x2 = clip_rect->x + clip_rect->width;
     double y2 = clip_rect->y + clip_rect->height;
 
     _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->width  = x2 - x1;
     user_rect->height = y2 - y1;
 
     return is_tight;
 }
 
 cairo_rectangle_list_t *
 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 {
@@ -759,19 +759,22 @@ cairo_rectangle_list_t *
 	    rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
 	    if (rectangles == NULL) {
 		_cairo_region_boxes_fini (&clip->region, boxes);
 		_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 = { boxes[i].p1.x, boxes[i].p1.y,
-						    boxes[i].p2.x - boxes[i].p1.x,
-						    boxes[i].p2.y - boxes[i].p1.y };
+               cairo_rectangle_int_t clip_rect;
+
+               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;
 
 		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;
 		}
 	    }
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -33,17 +33,19 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_COMPILER_PRIVATE_H
 #define CAIRO_COMPILER_PRIVATE_H
 
-CAIRO_BEGIN_DECLS
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
 # define slim_hidden_proto(name)		slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private
 # define slim_hidden_proto_no_warn(name)	slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn
 # define slim_hidden_def(name)			slim_hidden_def1(name, slim_hidden_int_name(name))
 # define slim_hidden_int_name(name) INT_##name
 # define slim_hidden_proto1(name, internal)				\
   extern __typeof (name) name						\
@@ -103,16 +105,17 @@ CAIRO_BEGIN_DECLS
 	extern __typeof (new) old		\
 	__asm__ ("" #old)			\
 	__attribute__((__alias__("" #new)))
 #else
 # define CAIRO_FUNCTION_ALIAS(old, new)
 #endif
 
 #ifndef __GNUC__
+#undef __attribute__
 #define __attribute__(x)
 #endif
 
 #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
 #define snprintf _snprintf
 #endif
 
 #ifdef _MSC_VER
@@ -120,11 +123,9 @@ CAIRO_BEGIN_DECLS
 #define inline __inline
 #endif
 
 #ifdef __STRICT_ANSI__
 #undef inline
 #define inline __inline__
 #endif
 
-CAIRO_END_DECLS
-
 #endif
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -58,25 +58,29 @@
 /*
  * Composite works fine.
  */
 #define DFB_COMPOSITE 1 
 
 /*
  * CompositeTrapezoids works (without antialiasing).
  */
-#define DFB_COMPOSITE_TRAPEZOIDS 0
+#define DFB_COMPOSITE_TRAPEZOIDS 1
 
 /*
  * ShowGlyphs works fine.
  */
 #define DFB_SHOW_GLYPHS 1
 
 
-D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend");
+D_DEBUG_DOMAIN( CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire" );
+D_DEBUG_DOMAIN( CairoDFB_Clip,    "CairoDFB/Clip",    "Cairo DirectFB Clipping" );
+D_DEBUG_DOMAIN( CairoDFB_Font,    "CairoDFB/Font",    "Cairo DirectFB Font Rendering" );
+D_DEBUG_DOMAIN( CairoDFB_Render,  "CairoDFB/Render",  "Cairo DirectFB Rendering" );
+D_DEBUG_DOMAIN( CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface" );
 
 /*****************************************************************************/
 
 
 typedef struct _cairo_directfb_surface {
     cairo_surface_t      base;
     cairo_format_t       format;
     cairo_content_t      content;
@@ -334,17 +338,17 @@ static cairo_status_t
                            void                     **image_extra,
                            DFBSurfaceLockFlags        lock_flags)
 {   
     IDirectFBSurface *buffer = NULL;
     DFBRectangle source_rect;
     cairo_format_t cairo_format;
     void *data;
     int   pitch; 
-        
+
     if (surface->format == (cairo_format_t) -1) {
         DFBSurfaceCapabilities caps;
         
         if (intrest_rec) {
             source_rect.x = intrest_rec->x;
             source_rect.y = intrest_rec->y;
             source_rect.w = intrest_rec->width; 
             source_rect.h = intrest_rec->height; 
@@ -361,47 +365,47 @@ static cairo_status_t
             if (w < source_rect.w || h < source_rect.h) {
                 surface->tmpsurface->Release (surface->tmpsurface);
                 surface->tmpsurface = NULL;
             }
         }
         
         cairo_format = _cairo_format_from_content (surface->content);
         if (!surface->tmpsurface) {
-            D_DEBUG_AT (Cairo_DirectFB, "Allocating buffer for surface %p.\n", surface);
+            D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
        
             surface->tmpsurface = 
                 _directfb_buffer_surface_create (surface->dfb, 
                                                  _cairo_to_directfb_format (cairo_format),
                                                  source_rect.w, source_rect.h);
             if (!surface->tmpsurface)
                 goto ERROR;
         }
         buffer = surface->tmpsurface;
         
-        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
+/*        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
         if (caps & DSCAPS_FLIPPING) {
             DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, 
                                  .x2 = source_rect.x + source_rect.w - 1,
                                  .y2 = source_rect.y + source_rect.h - 1 };
             surface->dfbsurface->Flip (surface->dfbsurface, &region, DSFLIP_BLIT);
-        } 
+        } */
         buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0);
     }
     else {
         /*might be a subsurface get the offset*/
         surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
         cairo_format = surface->format;
         buffer = surface->dfbsurface;     
     }
     
     *image_extra = buffer;
     
     if (buffer->Lock (buffer, lock_flags, &data, &pitch)) {
-        D_DEBUG_AT (Cairo_DirectFB, "Couldn't lock surface!\n");
+        D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n");
         goto ERROR;
     }
             
     *image_out = (cairo_image_surface_t *)
                     cairo_image_surface_create_for_data (data, cairo_format,
                                             source_rect.w, source_rect.h, pitch);
     if (*image_out == NULL) 
         goto ERROR;
@@ -438,17 +442,17 @@ static cairo_surface_t *
                                         cairo_content_t  content,
                                         int              width,
                                         int              height)
 {
     cairo_directfb_surface_t *source  = abstract_src;
     cairo_directfb_surface_t *surface;
     cairo_format_t            format;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Surface, 
                 "%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));
@@ -492,18 +496,17 @@ static cairo_surface_t *
     return &surface->base;
 }
 
 static cairo_status_t
 _cairo_directfb_surface_finish (void *data)
 {
     cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
+    D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface);
         
     if (surface->clips) {
         free (surface->clips);
         surface->clips   = NULL;
         surface->n_clips = 0;
     }
     
     if (surface->color) {
@@ -529,71 +532,71 @@ static cairo_status_t
 
 static cairo_status_t
 _cairo_directfb_surface_acquire_source_image (void                   *abstract_surface,
                                               cairo_image_surface_t **image_out,
                                               void                  **image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Acquire, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
     
     return _directfb_acquire_surface (surface, NULL, image_out, 
                                       NULL, image_extra, DSLF_READ);
 }
 
 static void
 _cairo_directfb_surface_release_source_image (void                  *abstract_surface,
                                               cairo_image_surface_t *image,
                                               void                  *image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Acquire, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
     
     buffer->Unlock (buffer);
     
     cairo_surface_destroy (&image->base);
 }
 
 static cairo_status_t
 _cairo_directfb_surface_acquire_dest_image (void                     *abstract_surface,
                                             cairo_rectangle_int_t    *interest_rect,
                                             cairo_image_surface_t   **image_out,
                                             cairo_rectangle_int_t    *image_rect_out,
                                             void                    **image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
-                "%s( surface=%p, interest_rect={ %d %d %d %d } ).\n", 
-                __FUNCTION__, surface, 
+    D_DEBUG_AT (CairoDFB_Acquire, 
+                "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n", 
+                __FUNCTION__, surface, surface->width, surface->height,
                 interest_rect ? interest_rect->x : 0,
                 interest_rect ? interest_rect->y : 0,
-                interest_rect ? interest_rect->width : surface->width,
-                interest_rect ? interest_rect->height : surface->height);
+                interest_rect ? interest_rect->width  : (unsigned) surface->width,
+                interest_rect ? interest_rect->height : (unsigned) surface->height);
     
     return _directfb_acquire_surface (surface, interest_rect, image_out, 
                                       image_rect_out, image_extra, DSLF_READ | DSLF_WRITE);
 }
 
 static void
 _cairo_directfb_surface_release_dest_image (void                  *abstract_surface,
                                             cairo_rectangle_int_t *interest_rect,
                                             cairo_image_surface_t *image,
                                             cairo_rectangle_int_t *image_rect,
                                             void                  *image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra; 
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Acquire, 
                 "%s( surface=%p ).\n", __FUNCTION__, surface);
     
     buffer->Unlock (buffer);
 
     if (surface->dfbsurface != buffer) {
         DFBRegion region = { .x1 = interest_rect->x, .y1 = interest_rect->y,
                              .x2 = interest_rect->x+interest_rect->width-1,
                              .y2 = interest_rect->y+interest_rect->height-1 };
@@ -613,17 +616,17 @@ static cairo_status_t
                                        int               src_y,
                                        int               width,
                                        int               height,
                                        cairo_surface_t **clone_out)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     cairo_directfb_surface_t *clone;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Surface, 
                 "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src);
 
     if (src->backend == surface->base.backend) {
         cairo_surface_reference (src);
         *clone_out = src;
          
         return CAIRO_STATUS_SUCCESS;
     }
@@ -721,17 +724,17 @@ static cairo_int_status_t
         if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
             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 (Cairo_DirectFB, "Replacing src pattern by mask pattern.\n");
+            D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
                 
             tmp = src_pattern;
             tmp_x = *src_x; tmp_y = *src_y;
             
             src_pattern = mask_pattern;
             *src_x = *mask_x; *src_y = *mask_y;
             
             mask_pattern = tmp;
@@ -878,34 +881,34 @@ static cairo_int_status_t
                                    unsigned int      height)
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
     cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
     DFBAccelerationMask         accel, mask;
     cairo_int_status_t          ret;
     
-    D_DEBUG_AT (Cairo_DirectFB,
+    D_DEBUG_AT (CairoDFB_Render,
                 "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
                    " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
                    " dst_y=%d, width=%u, height=%u ).\n",
                 __FUNCTION__, op, src_pattern, mask_pattern, dst, 
                 src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
     
     ret = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
                                        &src_x, &src_y, &mask_x, &mask_y, 
                                        width, height, &src, &src_attr);
     if (ret)
         return ret;
         
     accel = _directfb_categorize_operation (&src_attr);
     
     dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &mask);
     if (!(mask & accel)) {
-        D_DEBUG_AT (Cairo_DirectFB, "No acceleration (%08x)!\n", accel);
+        D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel);
         if (accel != DFXL_BLIT) {
             _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
             return CAIRO_INT_STATUS_UNSUPPORTED;
         }
     }
     
     src_x += src_attr.x_offset;
     src_y += src_attr.y_offset;
@@ -915,31 +918,31 @@ static cairo_int_status_t
             DFBRectangle sr;
         
             sr.x = src_x + _cairo_lround (src_attr.matrix.x0);
             sr.y = src_y + _cairo_lround (src_attr.matrix.y0);
             sr.w = width;
             sr.h = height;
         
             if (src_attr.extend == CAIRO_EXTEND_NONE) {
-                D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n");
+                D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n");
         
                 RUN_CLIPPED( dst, NULL,
                              dst->dfbsurface->Blit (dst->dfbsurface,
                                             src->dfbsurface, &sr, dst_x, dst_y));
             }
             else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
                 DFBRegion clip;
             
                 clip.x1 = dst_x;
                 clip.y1 = dst_y;
                 clip.x2 = dst_x + width  - 1;
                 clip.y2 = dst_y + height - 1;
             
-                D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n");
+                D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n");
             
                 RUN_CLIPPED( dst, &clip,
                              dst->dfbsurface->TileBlit (dst->dfbsurface, 
                                             src->dfbsurface, &sr, dst_x, dst_y));
             }
         }   break;
         
         case DFXL_STRETCHBLIT: {
@@ -956,17 +959,17 @@ static cairo_int_status_t
             sr.w = _cairo_lround (x2-x1);
             sr.h = _cairo_lround (y2-y1);
             
             dr.x = dst_x;
             dr.y = dst_y;
             dr.w = width;
             dr.h = height;
             
-            D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
+            D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n");
 
             RUN_CLIPPED (dst, NULL,
                          dst->dfbsurface->StretchBlit (dst->dfbsurface, 
                                                        src->dfbsurface, &sr, &dr));
         }   break;
         
         case DFXL_TEXTRIANGLES: {
             DFBRegion clip;
@@ -1014,17 +1017,17 @@ static cairo_int_status_t
             v[3].s = x1 / w;
             v[3].t = y2 / h;
             
             clip.x1 = dst_x;
             clip.y1 = dst_y;
             clip.x2 = dst_x + width  - 1;
             clip.y2 = dst_y + height - 1;
         
-            D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
+            D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
             
             RUN_CLIPPED (dst, &clip,
                          dst->dfbsurface->TextureTriangles (dst->dfbsurface, 
                                             src->dfbsurface, v, NULL, 4, DTTF_FAN));
         }   break;
         
         default:
             D_BUG ("Unexpected operation");
@@ -1047,17 +1050,17 @@ static cairo_int_status_t
 {
     cairo_directfb_surface_t *dst   = abstract_surface;
     DFBSurfaceDrawingFlags    flags;
     DFBSurfaceBlendFunction   sblend;
     DFBSurfaceBlendFunction   dblend;
     DFBRectangle              r[n_rects];
     int                       i;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    D_DEBUG_AT (CairoDFB_Render, 
                 "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
                 __FUNCTION__, dst, op, color, rects, n_rects);
 
     if (_directfb_get_operator (op, &sblend, &dblend))
         return CAIRO_INT_STATUS_UNSUPPORTED;
         
     if (color->alpha_short >= 0xff00) {
         if (sblend == DSBF_SRCALPHA)
@@ -1123,17 +1126,17 @@ static cairo_int_status_t
                                               int                num_traps )
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
     cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
     cairo_status_t              ret;
     DFBAccelerationMask         accel;
     
-    D_DEBUG_AT (Cairo_DirectFB,
+    D_DEBUG_AT (CairoDFB_Render,
                 "%s( op=%d, pattern=%p, dst=%p, antialias=%d,"
                    " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d,"
                    " width=%u, height=%u, traps=%p, num_traps=%d ).\n",
                 __FUNCTION__, op, pattern, dst, antialias,
                 src_x, src_y, dst_x, dst_y, width, height, traps, num_traps);
 
     if (antialias != CAIRO_ANTIALIAS_NONE)
         return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1230,17 +1233,17 @@ static cairo_int_status_t
                 n += 6;
             }
             
             traps++;
         }
         
 #undef ADD_TRI
               
-        D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
+        D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
             
         RUN_CLIPPED (dst, NULL,
                      dst->dfbsurface->TextureTriangles (dst->dfbsurface, src->dfbsurface, 
                                                     vertex, NULL, n, DTTF_LIST));
                                             
         ret = CAIRO_STATUS_SUCCESS;
     }
     
@@ -1251,27 +1254,29 @@ static cairo_int_status_t
 #endif /* DFB_COMPOSITE_TRAPEZOIDS */
 
 static cairo_int_status_t
 _cairo_directfb_surface_set_clip_region (void           *abstract_surface,
                                          cairo_region_t *region)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
-    D_DEBUG_AT (Cairo_DirectFB, 
+    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;
 
         status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
+        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));
@@ -1305,17 +1310,17 @@ static cairo_int_status_t
 }
 
 static cairo_int_status_t
 _cairo_directfb_abstract_surface_get_extents (void                  *abstract_surface,
                                               cairo_rectangle_int_t *rectangle)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     
-    D_DEBUG_AT (Cairo_DirectFB,
+    D_DEBUG_AT (CairoDFB_Surface,
                 "%s( surface=%p, rectangle=%p ).\n",
                 __FUNCTION__, surface, rectangle);
     
     if (rectangle) {
         if (!surface->local) {
             surface->dfbsurface->GetSize (surface->dfbsurface,
                                           &surface->width, &surface->height);
         }   
@@ -1374,52 +1379,67 @@ static cairo_status_t
     cairo_directfb_font_cache_t *cache     = NULL; 
     int                          n         = 0;
     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 );
+
     if (scaled_font->surface_private) {
         cache = scaled_font->surface_private;
         x = cache->x;
         y = cache->y;
     }
-    
+
+    _cairo_cache_freeze( scaled_font->glyphs );
+
     for (i = 0; i < num_glyphs; i++) {
         cairo_scaled_glyph_t  *scaled_glyph;
         cairo_image_surface_t *img;
         
+        D_DEBUG_AT (CairoDFB_Font, "  -> [%2d] = %4lu\n", i, glyphs[i].index );
+
         ret = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
                                           CAIRO_SCALED_GLYPH_INFO_SURFACE,
                                           &scaled_glyph);
-        if (ret)
+        if (ret) {
+            _cairo_cache_thaw( scaled_font->glyphs );
             return ret;
+        }
         
         img = scaled_glyph->surface;
         switch (img->format) {
             case CAIRO_FORMAT_A1:
             case CAIRO_FORMAT_A8:
             case CAIRO_FORMAT_ARGB32:
                 break;
             default:
-                D_DEBUG_AT (Cairo_DirectFB,
-                            "Unsupported font format %d!\n", img->format);
+                D_DEBUG_AT (CairoDFB_Font,
+                            "  -> Unsupported font format %d!\n", img->format);
+                _cairo_cache_thaw( scaled_font->glyphs );
                 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 );
+
         if (points[n].x >= surface->width  ||
             points[n].y >= surface->height ||
             points[n].x+img->width  <= 0   ||
             points[n].y+img->height <= 0)
-            continue;
+        {
+             D_DEBUG_AT (CairoDFB_Font,
+                         "  -> Unsupported font format %d!\n", img->format);
+             continue;
+        }
         
         if (!scaled_glyph->surface_private) {
             DFBRectangle *rect;
             
             if (x+img->width > 2048) {
                 x = 0;
                 y = h;
                 h = 0;
@@ -1431,95 +1451,111 @@ static cairo_status_t
             rects[n].h = img->height;
  
             x += img->width;
             h  = MAX (h, img->height);
             w  = MAX (w, x);
             
             /* Remember glyph location */ 
             rect = malloc (sizeof(DFBRectangle));
-            if (!rect)
+            if (!rect) {
+                _cairo_cache_thaw( scaled_font->glyphs );
                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+            }
             *rect = rects[n];
             
             scaled_glyph->surface_private = rect;
             chars[num_chars++] = scaled_glyph;
             
-            /*D_DEBUG_AT (Cairo_DirectFB, 
-                        "Glyph %lu will be loaded at (%d,%d).\n",
-                        glyphs[i].index, rects[n].x, rects[n].y);*/
+            D_DEBUG_AT (CairoDFB_Font, "  -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
+                        rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph);
         }
         else {
             rects[n] = *((DFBRectangle *)scaled_glyph->surface_private);
             
-            /*D_DEBUG_AT (Cairo_DirectFB, 
-                        "Glyph %lu already loaded at (%d,%d).\n",
-                        glyphs[i].index, rects[n].x, rects[n].y);*/
+            D_DEBUG_AT (CairoDFB_Font, "  -> exists at  %4d,%2d\n", rects[n].x, rects[n].y);
         }
             
         n++;
     }
     
-    if (!n)
+    if (!n) {
+        _cairo_cache_thaw( scaled_font->glyphs );
         return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
     
     h += y;
     w = MAX (w, 8);
     h = MAX (h, 8);
      
     if (cache) {
         if (cache->width < w || cache->height < h) {
             cairo_directfb_font_cache_t *new_cache;
             
             w = MAX (w, cache->width);
             h = MAX (h, cache->height);
             
-            D_DEBUG_AT (Cairo_DirectFB,
-                        "Reallocating font cache (%dx%d).\n", w, h);
+            D_DEBUG_AT (CairoDFB_Font, "  -> Reallocating font cache (%dx%d).\n", w, h);
             
             new_cache = _directfb_allocate_font_cache (surface->dfb, w, h);
-            if (!new_cache)
+            if (!new_cache) {
+                _cairo_cache_thaw( scaled_font->glyphs );
                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+            }
             
             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 (Cairo_DirectFB,
-                    "Allocating font cache (%dx%d).\n", w, h);
+        D_DEBUG_AT (CairoDFB_Font, "  -> Allocating font cache (%dx%d).\n", w, h);
         
         cache = _directfb_allocate_font_cache (surface->dfb, w, h);
-        if (!cache)
+        if (!cache) {
+            _cairo_cache_thaw( scaled_font->glyphs );
             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+        }
             
         scaled_font->surface_backend = &cairo_directfb_surface_backend;
         scaled_font->surface_private = cache;
     }
     
     if (num_chars) {
         unsigned char *data;
         int            pitch;
     
         if (cache->dfbsurface->Lock (cache->dfbsurface, 
                                      DSLF_WRITE, (void *)&data, &pitch))
+        {
+            _cairo_cache_thaw( scaled_font->glyphs );
             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;
             unsigned char         *dst  = data;
-            unsigned char         *src  = img->data;
+            unsigned char         *src;
             int                    j;
             
+            D_DEBUG_AT (CairoDFB_Font, "  -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]);
+
+            src = img->data;
+
+            D_DEBUG_AT (CairoDFB_Font, "     from %p\n", src);
+
             dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x);
                         
+            D_DEBUG_AT (CairoDFB_Font, "     to %4d,%2d (%p)\n", rect->x, rect->y, dst);
+
             if (img->format == CAIRO_FORMAT_A1) {
                 for (h = rect->h; h; h--) {
                     if (_directfb_argb_font) {
                         for (j = 0; j < rect->w; j++)
                             ((uint32_t *)dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0;
                     }
                     else {
                         for (j = 0; j < rect->w; j++)
@@ -1558,44 +1594,48 @@ static cairo_status_t
                     src += img->stride;
                 }
             }
         }
         
         cache->dfbsurface->Unlock (cache->dfbsurface);
     }
 
+    _cairo_cache_thaw( scaled_font->glyphs );
+
     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;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 {
     cairo_directfb_font_cache_t *cache = scaled_font->surface_private;
     
-    D_DEBUG_AT (Cairo_DirectFB,
+    D_DEBUG_AT (CairoDFB_Font,
                 "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font);
     
     if (cache) {
         _directfb_destroy_font_cache (cache);
         scaled_font->surface_private = NULL;
     }
 }
 
 static void
 _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
                                            cairo_scaled_font_t  *scaled_font)
 {
-     D_DEBUG_AT (Cairo_DirectFB,
+     D_DEBUG_AT (CairoDFB_Font,
                  "%s( scaled_glyph=%p, scaled_font=%p ).\n",
                  __FUNCTION__, scaled_glyph, scaled_font);
 
      if (scaled_glyph->surface_private) {
           free (scaled_glyph->surface_private);
           scaled_glyph->surface_private = NULL;
      }
 }
@@ -1615,17 +1655,17 @@ static cairo_int_status_t
     DFBSurfaceBlittingFlags      flags;
     DFBSurfaceBlendFunction      sblend;
     DFBSurfaceBlendFunction      dblend;
     DFBColor                     color;
     DFBRectangle                 rects[num_glyphs];
     DFBPoint                     points[num_glyphs];
     int                          num;
     
-    D_DEBUG_AT (Cairo_DirectFB,
+    D_DEBUG_AT (CairoDFB_Font,
                 "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
                 __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font);
                             
     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
         return CAIRO_INT_STATUS_UNSUPPORTED;
         
     if (_directfb_get_operator (op, &sblend, &dblend) ||
         sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) 
@@ -1656,17 +1696,17 @@ static cairo_int_status_t
         }
     } 
         
     dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
     dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
     dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
     dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a);
     
-    D_DEBUG_AT (Cairo_DirectFB, "Running BatchBlit().\n");
+    D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n");
         
     RUN_CLIPPED (dst, NULL,
                  dst->dfbsurface->BatchBlit (dst->dfbsurface,
                                          cache->dfbsurface, rects, points, num));
         
     return CAIRO_STATUS_SUCCESS;
 }
 #endif /* DFB_SHOW_GLYPHS */
@@ -1754,37 +1794,37 @@ cairo_directfb_surface_backend_init (IDi
 #if DFB_COMPOSITE_TRAPEZOIDS
         cairo_directfb_surface_backend.composite_trapezoids = NULL;
 #endif
 #if DFB_SHOW_GLYPHS
         cairo_directfb_surface_backend.scaled_font_fini = NULL;
         cairo_directfb_surface_backend.scaled_glyph_fini = NULL;
         cairo_directfb_surface_backend.show_glyphs = NULL;
 #endif
-        D_DEBUG_AT (Cairo_DirectFB, "Acceleration disabled.\n");
+        D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n");
     }
     else {
         DFBGraphicsDeviceDescription dsc;
         
         dfb->GetDeviceDescription (dfb, &dsc);
     
 #if DFB_COMPOSITE
-        if (!(dsc.acceleration_mask & DFXL_BLIT))
-            cairo_directfb_surface_backend.composite = NULL;
+//        if (!(dsc.acceleration_mask & DFXL_BLIT))
+//            cairo_directfb_surface_backend.composite = NULL;
 #endif
 
 #if DFB_COMPOSITE_TRAPEZOIDS
-        if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
-            cairo_directfb_surface_backend.composite_trapezoids = NULL;
+//        if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
+//            cairo_directfb_surface_backend.composite_trapezoids = NULL;
 #endif
     }
     
     if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
         _directfb_argb_font = 1;
-        D_DEBUG_AT (Cairo_DirectFB, "Using ARGB fonts.\n");
+        D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n");
     }
 
     done = 1;
 }   
 
 
 cairo_surface_t *
 cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-features-win32.h
@@ -0,0 +1,14 @@
+#ifndef CAIRO_FEATURES_H
+#define CAIRO_FEATURES_H
+
+#define HAVE_WINDOWS_H 1
+
+#define CAIRO_HAS_SVG_SURFACE 1
+#define CAIRO_HAS_PDF_SURFACE 1
+#define CAIRO_HAS_PS_SURFACE 1
+#define CAIRO_HAS_WIN32_SURFACE 1
+#define CAIRO_HAS_WIN32_FONT 1
+#define CAIRO_HAS_PNG_FUNCTIONS 1
+
+#endif
+
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -47,21 +47,19 @@
 # define CAIRO_END_DECLS
 #endif
 
 #ifndef cairo_public
 # define cairo_public
 #endif
 
 #define CAIRO_VERSION_MAJOR 1
-#define CAIRO_VERSION_MINOR 6
+#define CAIRO_VERSION_MINOR 7
 #define CAIRO_VERSION_MICRO 4
 
-#define CAIRO_VERSION_STRING "1.6.4"
-
 @PS_SURFACE_FEATURE@
 
 @PDF_SURFACE_FEATURE@
 
 @SVG_SURFACE_FEATURE@
 
 @XLIB_SURFACE_FEATURE@
 
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -36,29 +36,88 @@
  *	Carl D. Worth <cworth@cworth.org>
  *      Graydon Hoare <graydon@redhat.com>
  *      Owen Taylor <otaylor@redhat.com>
  */
 
 #define _BSD_SOURCE /* for strdup() */
 #include "cairoint.h"
 
-/* Forward declare so we can use it as an arbitrary backend for
- * _cairo_font_face_nil.
- */
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
 
 /* #cairo_font_face_t */
 
-const cairo_font_face_t _cairo_font_face_nil = {
-    { 0 },			/* hash_entry */
-    CAIRO_STATUS_NO_MEMORY,	/* status */
+const cairo_toy_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 */
+    { 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 */
 };
 
 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;
@@ -366,37 +425,76 @@ static int
     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:
+ * 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.
  *
- * Return value: a newly created #cairo_font_face_t, destroy with
- *  cairo_font_face_destroy()
+ * 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_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,
@@ -439,16 +537,17 @@ cairo_font_face_t *
     _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 ||
@@ -488,16 +587,87 @@ static cairo_status_t
     return _cairo_font_face_set_error (&font_face->base,
 	                               backend->create_toy (font_face,
 				                            font_matrix,
 							    ctm,
 							    options,
 							    scaled_font));
 }
 
+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;
+}
+
+/**
+ * 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;
+}
+
 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_create
 };
 
 void
 _cairo_unscaled_font_init (cairo_unscaled_font_t               *unscaled_font,
--- a/gfx/cairo/cairo/src/cairo-font-options.c
+++ b/gfx/cairo/cairo/src/cairo-font-options.c
@@ -34,41 +34,44 @@
  *      Owen Taylor <otaylor@redhat.com>
  */
 
 #include "cairoint.h"
 
 static const cairo_font_options_t _cairo_font_options_nil = {
     CAIRO_ANTIALIAS_DEFAULT,
     CAIRO_SUBPIXEL_ORDER_DEFAULT,
+    CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_HINT_STYLE_DEFAULT,
     CAIRO_HINT_METRICS_DEFAULT
 };
 
 /**
  * _cairo_font_options_init_default:
  * @options: a #cairo_font_options_t
  *
  * Initializes all fields of the font options object to default values.
  **/
 void
 _cairo_font_options_init_default (cairo_font_options_t *options)
 {
     options->antialias = CAIRO_ANTIALIAS_DEFAULT;
     options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
     options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
     options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
 }
 
 void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other)
 {
     options->antialias = other->antialias;
     options->subpixel_order = other->subpixel_order;
+    options->lcd_filter = other->lcd_filter;
     options->hint_style = other->hint_style;
     options->hint_metrics = other->hint_metrics;
 }
 
 /**
  * cairo_font_options_create:
  *
  * Allocates a new font options object with all options initialized
@@ -184,16 +187,18 @@ cairo_font_options_merge (cairo_font_opt
 
     if (cairo_font_options_status ((cairo_font_options_t *) other))
 	return;
 
     if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
 	options->antialias = other->antialias;
     if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
 	options->subpixel_order = other->subpixel_order;
+    if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
+	options->lcd_filter = other->lcd_filter;
     if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
 	options->hint_style = other->hint_style;
     if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
 	options->hint_metrics = other->hint_metrics;
 }
 slim_hidden_def (cairo_font_options_merge);
 
 /**
@@ -216,16 +221,17 @@ cairo_font_options_equal (const cairo_fo
     if (cairo_font_options_status ((cairo_font_options_t *) other))
 	return FALSE;
 
     if (options == other)
 	return TRUE;
 
     return (options->antialias == other->antialias &&
 	    options->subpixel_order == other->subpixel_order &&
+	    options->lcd_filter == other->lcd_filter &&
 	    options->hint_style == other->hint_style &&
 	    options->hint_metrics == other->hint_metrics);
 }
 slim_hidden_def (cairo_font_options_equal);
 
 /**
  * cairo_font_options_hash:
  * @options: a #cairo_font_options_t
@@ -241,17 +247,18 @@ slim_hidden_def (cairo_font_options_equa
 unsigned long
 cairo_font_options_hash (const cairo_font_options_t *options)
 {
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	options = &_cairo_font_options_nil; /* force default values */
 
     return ((options->antialias) |
 	    (options->subpixel_order << 4) |
-	    (options->hint_style << 8) |
+	    (options->lcd_filter << 8) |
+	    (options->hint_style << 12) |
 	    (options->hint_metrics << 16));
 }
 slim_hidden_def (cairo_font_options_hash);
 
 /**
  * cairo_font_options_set_antialias:
  * @options: a #cairo_font_options_t
  * @antialias: the new antialiasing mode
@@ -323,16 +330,59 @@ cairo_font_options_get_subpixel_order (c
 {
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	return CAIRO_SUBPIXEL_ORDER_DEFAULT;
 
     return options->subpixel_order;
 }
 
 /**
+ * cairo_font_options_set_lcd_filter:
+ * @options: a #cairo_font_options_t
+ * @lcd_filter: the new LCD filter
+ *
+ * Sets the LCD filter for the font options object. The LCD filter
+ * specifies how pixels are filtered when rendered with an antialiasing
+ * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
+ * #cairo_lcd_filter_t for full details.
+ *
+ * Since: 1.8
+ **/
+void
+cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
+				   cairo_lcd_filter_t    lcd_filter)
+{
+    if (cairo_font_options_status (options))
+	return;
+
+    options->lcd_filter = lcd_filter;
+}
+slim_hidden_def (cairo_font_options_set_lcd_filter);
+
+/**
+ * cairo_font_options_get_lcd_filter:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the LCD filter for the font options object.
+ * See the documentation for #cairo_lcd_filter_t for full details.
+ *
+ * Return value: the LCD filter for the font options object
+ *
+ * Since: 1.8
+ **/
+cairo_lcd_filter_t
+cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
+{
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_LCD_FILTER_DEFAULT;
+
+    return options->lcd_filter;
+}
+
+/**
  * cairo_font_options_set_hint_style:
  * @options: a #cairo_font_options_t
  * @hint_style: the new hint style
  *
  * Sets the hint style for font outlines for the font options object.
  * This controls whether to fit font outlines to the pixel grid,
  * and if so, whether to optimize for fidelity or contrast.
  * See the documentation for #cairo_hint_style_t for full details.
--- a/gfx/cairo/cairo/src/cairo-freelist-private.h
+++ b/gfx/cairo/cairo/src/cairo-freelist-private.h
@@ -18,16 +18,17 @@
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  */
 #ifndef CAIRO_FREELIST_H
 #define CAIRO_FREELIST_H
 
 #include "cairo-types-private.h"
+#include "cairo-compiler-private.h"
 
 /* Opaque implementation types. */
 typedef struct _cairo_freelist cairo_freelist_t;
 typedef struct _cairo_freelist_node cairo_freelist_node_t;
 
 struct _cairo_freelist_node {
     cairo_freelist_node_t *next;
 };
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -52,16 +52,40 @@
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_IMAGE_H
 #include FT_TRUETYPE_TABLES_H
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 #include FT_SYNTHESIS_H
 #endif
 
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+#include FT_LCD_FILTER_H
+#endif
+
+/* Fontconfig version older than 2.6 didn't have these options */
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER	"lcdfilter"
+#endif
+/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE	0
+#define FC_LCD_DEFAULT	1
+#define FC_LCD_LIGHT	2
+#define FC_LCD_LEGACY	3
+#endif
+
+/* FreeType version older than 2.3.5(?) didn't have these options */
+#ifndef FT_LCD_FILTER_NONE
+#define FT_LCD_FILTER_NONE	0
+#define FT_LCD_FILTER_DEFAULT	1
+#define FT_LCD_FILTER_LIGHT	2
+#define FT_LCD_FILTER_LEGACY	16
+#endif
+
 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
 
 /* This is the max number of FT_face objects we keep open at once
  */
 #define MAX_OPEN_FACES 10
@@ -536,17 +560,17 @@ static cairo_bool_t
 }
 
 /* Ensures that an unscaled font has a face object. If we exceed
  * MAX_OPEN_FACES, try to close some.
  *
  * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
  * set the scale on the face, but just returns it at the last scale.
  */
-FT_Face
+cairo_warn FT_Face
 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
 {
     cairo_ft_unscaled_font_map_t *font_map;
     FT_Face face = NULL;
 
     CAIRO_MUTEX_LOCK (unscaled->mutex);
     unscaled->lock_count++;
 
@@ -617,17 +641,17 @@ static cairo_status_t
 
     /* The font matrix has x and y "scale" components which we extract and
      * use as character scale values. These influence the way freetype
      * chooses hints, as well as selecting different bitmaps in
      * hand-rendered fonts. We also copy the normalized matrix to
      * freetype's transformation.
      */
 
-    status = _cairo_matrix_compute_scale_factors (scale,
+    status = _cairo_matrix_compute_basis_scale_factors (scale,
 						  &x_scale, &y_scale,
 						  1);
     if (status)
 	return status;
 
     /* FreeType docs say this about x_scale and y_scale:
      * "A character width or height smaller than 1pt is set to 1pt;"
      * So, we cap them from below at 1.0 and let the FT transform
@@ -738,46 +762,309 @@ static cairo_status_t
 					unscaled->face->available_sizes[best_i].height);
 	if (error)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-/* Empirically-derived subpixel filtering values thanks to Keith
- * Packard and libXft. */
-static const int    filters[3][3] = {
-    /* red */
-#if 0
-    {    65538*4/7,65538*2/7,65538*1/7 },
-    /* green */
-    {    65536*1/4, 65536*2/4, 65537*1/4 },
-    /* blue */
-    {    65538*1/7,65538*2/7,65538*4/7 },
+/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
+ * into a different format. For example, we want to convert a
+ * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
+ * ARGB or ABGR bitmap.
+ *
+ * this function prepares a target descriptor for this operation.
+ *
+ * input :: target bitmap descriptor. The function will set its
+ *          'width', 'rows' and 'pitch' fields, and only these
+ *
+ * slot  :: the glyph slot containing the source bitmap. this
+ *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
+ *
+ * mode  :: the requested final rendering mode. supported values are
+ *          MONO, NORMAL (i.e. gray), LCD and LCD_V
+ *
+ * the function returns the size in bytes of the corresponding buffer,
+ * it's up to the caller to allocate the corresponding memory block
+ * before calling _fill_xrender_bitmap
+ *
+ * it also returns -1 in case of error (e.g. incompatible arguments,
+ * like trying to convert a gray bitmap into a monochrome one)
+ */
+static int
+_compute_xrender_bitmap_size(FT_Bitmap      *target,
+			     FT_GlyphSlot    slot,
+			     FT_Render_Mode  mode)
+{
+    FT_Bitmap *ftbit;
+    int width, height, pitch;
+
+    if (slot->format != FT_GLYPH_FORMAT_BITMAP)
+	return -1;
+
+    /* compute the size of the final bitmap */
+    ftbit = &slot->bitmap;
+
+    width = ftbit->width;
+    height = ftbit->rows;
+    pitch = (width + 3) & ~3;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (mode == FT_RENDER_MODE_MONO) {
+	    pitch = (((width + 31) & ~31) >> 3);
+	    break;
+	}
+	/* fall-through */
+
+    case FT_PIXEL_MODE_GRAY:
+	if (mode == FT_RENDER_MODE_LCD ||
+	    mode == FT_RENDER_MODE_LCD_V)
+	{
+	    /* each pixel is replicated into a 32-bit ARGB value */
+	    pitch = width * 4;
+	}
+	break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (mode != FT_RENDER_MODE_LCD)
+	    return -1;
+
+	/* horz pixel triplets are packed into 32-bit ARGB values */
+	width /= 3;
+	pitch = width * 4;
+	break;
+
+    case FT_PIXEL_MODE_LCD_V:
+	if (mode != FT_RENDER_MODE_LCD_V)
+	    return -1;
+
+	/* vert pixel triplets are packed into 32-bit ARGB values */
+	height /= 3;
+	pitch = width * 4;
+	break;
+
+    default:  /* unsupported source format */
+	return -1;
+    }
+
+    target->width = width;
+    target->rows = height;
+    target->pitch = pitch;
+    target->buffer = NULL;
+
+    return pitch * height;
+}
+
+/* this functions converts the glyph bitmap found in a FT_GlyphSlot
+ * into a different format (see _compute_xrender_bitmap_size)
+ *
+ * you should call this function after _compute_xrender_bitmap_size
+ *
+ * target :: target bitmap descriptor. Note that its 'buffer' pointer
+ *           must point to memory allocated by the caller
+ *
+ * slot   :: the glyph slot containing the source bitmap
+ *
+ * mode   :: the requested final rendering mode
+ *
+ * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
+ */
+static void
+_fill_xrender_bitmap(FT_Bitmap      *target,
+		     FT_GlyphSlot    slot,
+		     FT_Render_Mode  mode,
+		     int             bgr)
+{
+    FT_Bitmap *ftbit = &slot->bitmap;
+    unsigned char *srcLine = ftbit->buffer;
+    unsigned char *dstLine = target->buffer;
+    int src_pitch = ftbit->pitch;
+    int width = target->width;
+    int height = target->rows;
+    int pitch = target->pitch;
+    int subpixel;
+    int h;
+
+    subpixel = (mode == FT_RENDER_MODE_LCD ||
+		mode == FT_RENDER_MODE_LCD_V);
+
+    if (src_pitch < 0)
+	srcLine -= src_pitch * (ftbit->rows - 1);
+
+    target->pixel_mode = ftbit->pixel_mode;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (subpixel) {
+	    /* convert mono to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			((unsigned int *) dstLine)[x] = 0xffffffffU;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+
+	} else if (mode == FT_RENDER_MODE_NORMAL) {
+	    /* convert mono to 8-bit gray */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			dstLine[x] = 0xff;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_GRAY;
+
+	} else {
+	    /* copy mono to mono */
+
+	    int  bytes = (width + 7) >> 3;
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+		memcpy (dstLine, srcLine, bytes);
+	}
+	break;
+
+    case FT_PIXEL_MODE_GRAY:
+	if (subpixel) {
+	    /* convert gray to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++) {
+		    unsigned int pix = srcLine[x];
+
+		    pix |= (pix << 8);
+		    pix |= (pix << 16);
+
+		    dst[x] = pix;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+        } else {
+            /* copy gray into gray */
+
+            for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+                memcpy (dstLine, srcLine, width);
+        }
+        break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (!bgr) {
+	    /* convert horizontal RGB into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[0] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[2]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+	    /* convert horizontal BGR into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[2] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[0]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+	break;
+
+    default:  /* FT_PIXEL_MODE_LCD_V */
+	/* convert vertical RGB into ARGB32 */
+	if (!bgr) {
+
+	    for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char* src = srcLine;
+		unsigned int*  dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int pix;
+#if 1
+		    pix = ((unsigned int)src[0]           << 16) |
+			  ((unsigned int)src[src_pitch]   <<  8) |
+			  ((unsigned int)src[src_pitch*2]      ) |
+			  0xFF000000 ;
+#else
+		    pix = ((unsigned int)src[0]           << 16) |
+			  ((unsigned int)src[src_pitch]   <<  8) |
+			  ((unsigned int)src[src_pitch*2]      ) |
+			  ((unsigned int)src[src_pitch]   << 24) ;
 #endif
-    {    65538*9/13,65538*3/13,65538*1/13 },
-    /* green */
-    {    65538*1/6, 65538*4/6, 65538*1/6 },
-    /* blue */
-    {    65538*1/13,65538*3/13,65538*9/13 },
-};
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+
+	    for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[src_pitch * 2] << 16) |
+			  ((unsigned int)src[src_pitch]     <<  8) |
+			  ((unsigned int)src[0]                  ) |
+			  ((unsigned int)src[src_pitch]     << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+    }
+}
+
 
 /* Fills in val->image with an image surface created from @bitmap
  */
 static cairo_status_t
 _get_bitmap_surface (FT_Bitmap		     *bitmap,
 		     cairo_bool_t	      own_buffer,
 		     cairo_font_options_t    *font_options,
 		     cairo_image_surface_t  **surface)
 {
     int width, height, stride;
     unsigned char *data;
     int format = CAIRO_FORMAT_A8;
-    cairo_bool_t subpixel = FALSE;
+    cairo_image_surface_t *image;
 
     width = bitmap->width;
     height = bitmap->rows;
 
     if (width == 0 || height == 0) {
 	*surface = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	return (*surface)->base.status;
@@ -809,169 +1096,78 @@ static cairo_status_t
 		    source += bitmap->pitch;
 		    dest += stride;
 		}
 	    }
 	}
 
 #ifndef WORDS_BIGENDIAN
 	{
-	    unsigned char   *d = data;
+	    uint8_t   *d = data;
 	    int		count = stride * height;
 
 	    while (count--) {
 		*d = CAIRO_BITSWAP8 (*d);
 		d++;
 	    }
 	}
 #endif
 	format = CAIRO_FORMAT_A1;
 	break;
 
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
     case FT_PIXEL_MODE_GRAY:
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	case CAIRO_ANTIALIAS_NONE:
-	default:
+        if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
 	    stride = bitmap->pitch;
 	    if (own_buffer) {
 		data = bitmap->buffer;
 	    } else {
 		data = _cairo_malloc_ab (height, stride);
 		if (!data)
 		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 		memcpy (data, bitmap->buffer, stride * height);
 	    }
 	    format = CAIRO_FORMAT_A8;
-	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL: {
-	    int		    x, y;
-	    unsigned char   *in_line, *out_line, *in;
-	    unsigned int    *out;
-	    unsigned int    red, green, blue;
-	    int		    rf, gf, bf;
-	    int		    s;
-	    int		    o, os;
-	    unsigned char   *data_rgba;
-	    unsigned int    width_rgba, stride_rgba;
-	    int		    vmul = 1;
-	    int		    hmul = 1;
-
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    default:
-		width /= 3;
-		hmul = 3;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		vmul = 3;
-		height /= 3;
-		break;
-	    }
-	    /*
-	     * Filter the glyph to soften the color fringes
-	     */
-	    width_rgba = width;
+	} else {
+	    /* if we get there, the  data from the source bitmap
+	     * really comes from _fill_xrender_bitmap, and is
+	     * made of 32-bit ARGB or ABGR values */
+	    assert (own_buffer != 0);
+	    assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
+
+	    data = bitmap->buffer;
 	    stride = bitmap->pitch;
-	    stride_rgba = (width_rgba * 4 + 3) & ~3;
-	    data_rgba = calloc (stride_rgba, height);
-	    if (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:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    default:
-		rf = 0;
-		gf = 1;
-		bf = 2;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-		bf = 0;
-		gf = 1;
-		rf = 2;
-		break;
-	    }
-	    in_line = bitmap->buffer;
-	    out_line = data_rgba;
-	    for (y = 0; y < height; y++)
-	    {
-		in = in_line;
-		out = (unsigned int *) out_line;
-		in_line += stride * vmul;
-		out_line += stride_rgba;
-		for (x = 0; x < width * hmul; x += hmul)
-		{
-		    red = green = blue = 0;
-		    o = 0;
-		    for (s = 0; s < 3; s++)
-		    {
-			red += filters[rf][s]*in[x+o];
-			green += filters[gf][s]*in[x+o];
-			blue += filters[bf][s]*in[x+o];
-			o += os;
-		    }
-		    red = red / 65536;
-		    green = green / 65536;
-		    blue = blue / 65536;
-		    *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
-		}
-	    }
-
-	    /* Images here are stored in native format. The
-	     * backend must convert to its own format as needed
-	     */
-
-	    if (own_buffer)
-		free (bitmap->buffer);
-	    data = data_rgba;
-	    stride = stride_rgba;
 	    format = CAIRO_FORMAT_ARGB32;
-	    subpixel = TRUE;
-	    break;
-	}
 	}
 	break;
     case FT_PIXEL_MODE_GRAY2:
     case FT_PIXEL_MODE_GRAY4:
 	/* These could be triggered by very rare types of TrueType fonts */
     default:
 	if (own_buffer)
 	    free (bitmap->buffer);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    *surface = (cairo_image_surface_t *)
+    /* XXX */
+    *surface = image = (cairo_image_surface_t *)
 	cairo_image_surface_create_for_data (data,
 					     format,
 					     width, height, stride);
-    if ((*surface)->base.status) {
+    if (image->base.status) {
 	free (data);
 	return (*surface)->base.status;
     }
 
-    if (subpixel)
-	pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
-
-    _cairo_image_surface_assume_ownership_of_data ((*surface));
+    if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
+	pixman_image_set_component_alpha (image->pixman_image, TRUE);
+
+    _cairo_image_surface_assume_ownership_of_data (image);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Converts an outline FT_GlyphSlot into an image
  *
  * This could go through _render_glyph_bitmap as well, letting
  * FreeType convert the outline to a bitmap, but doing it ourselves
@@ -986,129 +1182,173 @@ static cairo_status_t
  * when we add subpixel support. If so, we may want to eliminate
  * this version of the code path entirely.
  */
 static cairo_status_t
 _render_glyph_outline (FT_Face                    face,
 		       cairo_font_options_t	 *font_options,
 		       cairo_image_surface_t	**surface)
 {
+    int rgba = FC_RGBA_UNKNOWN;
+    int lcd_filter = FT_LCD_FILTER_LEGACY;
     FT_GlyphSlot glyphslot = face->glyph;
     FT_Outline *outline = &glyphslot->outline;
     FT_Bitmap bitmap;
     FT_BBox cbox;
-    FT_Matrix matrix;
-    int hmul = 1;
-    int vmul = 1;
-    unsigned int width, height, stride;
-    cairo_bool_t subpixel = FALSE;
+    unsigned int width, height;
     cairo_status_t status;
+    FT_Error fterror;
+    FT_Library library = glyphslot->library;
+    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
+
+    switch (font_options->antialias) {
+    case CAIRO_ANTIALIAS_NONE:
+	render_mode = FT_RENDER_MODE_MONO;
+	break;
+
+    case CAIRO_ANTIALIAS_SUBPIXEL:
+	switch (font_options->subpixel_order) {
+	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
+	    case CAIRO_SUBPIXEL_ORDER_RGB:
+	    case CAIRO_SUBPIXEL_ORDER_BGR:
+		render_mode = FT_RENDER_MODE_LCD;
+		break;
+
+	    case CAIRO_SUBPIXEL_ORDER_VRGB:
+	    case CAIRO_SUBPIXEL_ORDER_VBGR:
+		render_mode = FT_RENDER_MODE_LCD_V;
+		break;
+	}
+
+	switch (font_options->lcd_filter) {
+	case CAIRO_LCD_FILTER_NONE:
+	    lcd_filter = FT_LCD_FILTER_NONE;
+	    break;
+	case CAIRO_LCD_FILTER_DEFAULT:
+	case CAIRO_LCD_FILTER_INTRA_PIXEL:
+	    lcd_filter = FT_LCD_FILTER_LEGACY;
+	    break;
+	case CAIRO_LCD_FILTER_FIR3:
+	    lcd_filter = FT_LCD_FILTER_LIGHT;
+	    break;
+	case CAIRO_LCD_FILTER_FIR5:
+	    lcd_filter = FT_LCD_FILTER_DEFAULT;
+	    break;
+	}
+
+	break;
+
+    case CAIRO_ANTIALIAS_DEFAULT:
+    case CAIRO_ANTIALIAS_GRAY:
+	render_mode = FT_RENDER_MODE_NORMAL;
+    }
 
     FT_Outline_Get_CBox (outline, &cbox);
 
     cbox.xMin &= -64;
     cbox.yMin &= -64;
     cbox.xMax = (cbox.xMax + 63) & -64;
     cbox.yMax = (cbox.yMax + 63) & -64;
 
     width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
     height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
-    stride = (width * hmul + 3) & ~3;
 
     if (width * height == 0) {
 	cairo_format_t format;
 	/* Looks like fb handles zero-sized images just fine */
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
+	switch (render_mode) {
+	case FT_RENDER_MODE_MONO:
 	    format = CAIRO_FORMAT_A1;
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
+	case FT_RENDER_MODE_LCD:
+	case FT_RENDER_MODE_LCD_V:
 	    format= CAIRO_FORMAT_ARGB32;
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
 	default:
 	    format = CAIRO_FORMAT_A8;
 	    break;
 	}
 
 	(*surface) = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	if ((*surface)->base.status)
 	    return (*surface)->base.status;
     } else  {
 
-	matrix.xx = matrix.yy = 0x10000L;
-	matrix.xy = matrix.yx = 0;
-
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
-	    bitmap.num_grays  = 1;
-	    stride = ((width + 31) & -32) >> 3;
+	int bitmap_size;
+
+	switch (render_mode) {
+	case FT_RENDER_MODE_LCD:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
+		rgba = FC_RGBA_BGR;
+	    } else {
+		rgba = FC_RGBA_RGB;
+	    }
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    bitmap.num_grays  = 256;
-	    stride = (width + 3) & -4;
+	case FT_RENDER_MODE_LCD_V:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
+		rgba = FC_RGBA_VBGR;
+	    } else {
+		rgba = FC_RGBA_VRGB;
+	    }
+	    break;
+	case FT_RENDER_MODE_MONO:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
+	default:
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    default:
-		matrix.xx *= 3;
-		hmul = 3;
-		subpixel = TRUE;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		matrix.yy *= 3;
-		vmul = 3;
-		subpixel = TRUE;
-		break;
-	    }
-	    FT_Outline_Transform (outline, &matrix);
-
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    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 HAVE_FT_LIBRARY_SETLCDFILTER
+	FT_Library_SetLcdFilter (library, lcd_filter);
+#endif
+
+	fterror = FT_Render_Glyph (face->glyph, render_mode);
+
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+	FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
+#endif
+
+	if (fterror != 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
+						    face->glyph,
+						    render_mode);
+	if (bitmap_size < 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	bitmap.buffer = calloc (1, bitmap_size);
 	if (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);
-	}
-
+	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
+			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
+
+	/* Note:
+	 * _get_bitmap_surface will free bitmap.buffer if there is an error
+	 */
 	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
 	if (status)
 	    return status;
+
+	/* Note: the font's coordinate system is upside down from ours, so the
+	 * Y coordinate of the control box needs to be negated.  Moreover, device
+	 * offsets are position of glyph origin relative to top left while xMin
+	 * and yMax are offsets of top left relative to origin.  Another negation.
+	 */
+	cairo_surface_set_device_offset (&(*surface)->base,
+					 (double)-glyphslot->bitmap_left,
+					 (double)+glyphslot->bitmap_top);
     }
 
-    /*
-     * 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.
-     */
-    cairo_surface_set_device_offset (&(*surface)->base,
-				     floor (-(double) cbox.xMin / 64.0),
-				     floor (+(double) cbox.yMax / 64.0));
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
 static cairo_status_t
 _render_glyph_bitmap (FT_Face		      face,
 		      cairo_font_options_t   *font_options,
 		      cairo_image_surface_t **surface)
@@ -1317,16 +1557,17 @@ static void
 
     /* disable antialiasing if requested */
     if (FcPatternGetBool (pattern,
 			  FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
 	antialias = FcTrue;
     
     if (antialias) {
 	cairo_subpixel_order_t subpixel_order;
+	int lcd_filter;
 
 	/* disable hinting if requested */
 	if (FcPatternGetBool (pattern,
 			      FC_HINTING, 0, &hinting) != FcResultMatch)
 	    hinting = FcTrue;
 
 	if (FcPatternGetInteger (pattern,
 				 FC_RGBA, 0, &rgba) != FcResultMatch)
@@ -1352,16 +1593,35 @@ static void
 	    break;
 	}
 
 	if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
 	    ft_options.base.subpixel_order = subpixel_order;
 	    ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 	}
 
+	if (FcPatternGetInteger (pattern,
+				 FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
+	{
+	    switch (lcd_filter) {
+	    case FC_LCD_NONE:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
+		break;
+	    case FC_LCD_DEFAULT:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
+		break;
+	    case FC_LCD_LIGHT:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
+		break;
+	    case FC_LCD_LEGACY:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+		break;
+	    }
+	}
+
 #ifdef FC_HINT_STYLE    
 	if (FcPatternGetInteger (pattern, 
 				 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
 	    hintstyle = FC_HINT_FULL;
 
 	if (!hinting)
 	    hintstyle = FC_HINT_NONE;
 
@@ -1452,16 +1712,22 @@ static void
     }
 
     if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
 	options->base.hint_style = other->base.hint_style;
 
     if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
 	options->base.hint_style = CAIRO_HINT_STYLE_NONE;
 
+    if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
+	options->base.lcd_filter = other->base.lcd_filter;
+
+    if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
+	options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
+
     if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
 	if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
 	    load_flags |= FT_LOAD_NO_HINTING;
 	else
 	    load_target = FT_LOAD_TARGET_MONO;
 	load_flags |= FT_LOAD_MONOCHROME;
     } else {
 	switch (options->base.hint_style) {
@@ -1475,21 +1741,21 @@ static void
 	    break;
 	case CAIRO_HINT_STYLE_FULL:
 	case CAIRO_HINT_STYLE_DEFAULT:
 	    if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
 		switch (options->base.subpixel_order) {
 		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 		case CAIRO_SUBPIXEL_ORDER_RGB:
 		case CAIRO_SUBPIXEL_ORDER_BGR:
-		    load_target |= FT_LOAD_TARGET_LCD;
+		    load_target = FT_LOAD_TARGET_LCD;
 		    break;
 		case CAIRO_SUBPIXEL_ORDER_VRGB:
 		case CAIRO_SUBPIXEL_ORDER_VBGR:
-		    load_target |= FT_LOAD_TARGET_LCD_V;
+		    load_target = FT_LOAD_TARGET_LCD_V;
 		break;
 		}
 	    }
 	    break;
 	}
     }
 
     options->load_flags = load_flags | load_target;
@@ -2141,17 +2407,21 @@ static unsigned long
     cairo_ft_scaled_font_t *scaled_font = abstract_font;
     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;
-    index = FT_Get_Char_Index (face, ucs4);
+
+    /* If making this compile without fontconfig, use:
+     * index = FT_Get_Char_Index (face, ucs4); */
+    index = FcFreeTypeCharIndex (face, ucs4);
+
     _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,
@@ -2418,16 +2688,44 @@ static cairo_status_t
 		rgba = FC_RGBA_NONE;
 	    }
 
 	    if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
     }
 
+    if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
+    {
+	if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
+	{
+	    int lcd_filter;
+
+	    switch (options->lcd_filter) {
+	    case CAIRO_LCD_FILTER_NONE:
+		lcd_filter = FT_LCD_FILTER_NONE;
+		break;
+	    case CAIRO_LCD_FILTER_DEFAULT:
+	    case CAIRO_LCD_FILTER_INTRA_PIXEL:
+		lcd_filter = FT_LCD_FILTER_LEGACY;
+		break;
+	    case CAIRO_LCD_FILTER_FIR3:
+		lcd_filter = FT_LCD_FILTER_LIGHT;
+		break;
+	    default:
+	    case CAIRO_LCD_FILTER_FIR5:
+		lcd_filter = FT_LCD_FILTER_DEFAULT;
+		break;
+	    }
+
+	    if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+    }
+
     if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
     {
 	if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
 	{
 	    if (! FcPatternAddBool (pattern,
 			            FC_HINTING,
 				    options->hint_style != CAIRO_HINT_STYLE_NONE))
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -94,18 +94,19 @@ cairo_status_t
     _cairo_font_options_init_default (&gstate->font_options);
 
     _cairo_clip_init (&gstate->clip, target);
 
     gstate->target = cairo_surface_reference (target);
     gstate->parent_target = NULL;
     gstate->original_target = cairo_surface_reference (target);
 
-    _cairo_gstate_identity_matrix (gstate);
-    gstate->source_ctm_inverse = gstate->ctm_inverse;
+    cairo_matrix_init_identity (&gstate->ctm);
+    gstate->ctm_inverse = gstate->ctm;
+    gstate->source_ctm_inverse = gstate->ctm;
 
     gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
 						  CAIRO_CONTENT_COLOR);
 
     /* Now that the gstate is fully initialized and ready for the eventual
      * _cairo_gstate_fini(), we can check for errors (and not worry about
      * the resource deallocation). */
 
@@ -648,16 +649,19 @@ cairo_status_t
 
 cairo_status_t
 _cairo_gstate_transform (cairo_gstate_t	      *gstate,
 			 const cairo_matrix_t *matrix)
 {
     cairo_matrix_t tmp;
     cairo_status_t status;
 
+    if (_cairo_matrix_is_identity (matrix))
+	return CAIRO_STATUS_SUCCESS;
+
     tmp = *matrix;
     status = cairo_matrix_invert (&tmp);
     if (status)
 	return status;
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
@@ -671,32 +675,38 @@ cairo_status_t
 }
 
 cairo_status_t
 _cairo_gstate_set_matrix (cairo_gstate_t       *gstate,
 			  const cairo_matrix_t *matrix)
 {
     cairo_status_t status;
 
+    if (memcmp (matrix, &gstate->ctm, sizeof (cairo_matrix_t)) == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     if (! _cairo_matrix_is_invertible (matrix))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     gstate->ctm = *matrix;
     gstate->ctm_inverse = *matrix;
     status = cairo_matrix_invert (&gstate->ctm_inverse);
     assert (status == CAIRO_STATUS_SUCCESS);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
 {
+    if (_cairo_matrix_is_identity (&gstate->ctm))
+	return;
+
     _cairo_gstate_unset_scaled_font (gstate);
 
     cairo_matrix_init_identity (&gstate->ctm);
     cairo_matrix_init_identity (&gstate->ctm_inverse);
 }
 
 void
 _cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
@@ -1210,17 +1220,17 @@ cairo_status_t
 _cairo_gstate_select_font_face (cairo_gstate_t       *gstate,
 				const char           *family,
 				cairo_font_slant_t    slant,
 				cairo_font_weight_t   weight)
 {
     cairo_font_face_t *font_face;
     cairo_status_t status;
 
-    font_face = _cairo_toy_font_face_create (family, slant, weight);
+    font_face = cairo_toy_font_face_create (family, slant, weight);
     if (font_face->status)
 	return font_face->status;
 
     status = _cairo_gstate_set_font_face (gstate, font_face);
     cairo_font_face_destroy (font_face);
 
     return status;
 }
@@ -1235,16 +1245,19 @@ cairo_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_set_font_matrix (cairo_gstate_t	    *gstate,
 			       const cairo_matrix_t *matrix)
 {
+    if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0)
+	return CAIRO_STATUS_SUCCESS;
+
     if (! _cairo_matrix_is_invertible (matrix))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     gstate->font_matrix = *matrix;
 
     return CAIRO_STATUS_SUCCESS;
@@ -1256,16 +1269,19 @@ void
 {
     *matrix = gstate->font_matrix;
 }
 
 void
 _cairo_gstate_set_font_options (cairo_gstate_t             *gstate,
 				const cairo_font_options_t *options)
 {
+    if (memcmp (options, &gstate->font_options, sizeof (cairo_font_options_t)) == 0)
+	return;
+
     _cairo_gstate_unset_scaled_font (gstate);
 
     _cairo_font_options_init_copy (&gstate->font_options, options);
 }
 
 void
 _cairo_gstate_get_font_options (cairo_gstate_t       *gstate,
 				cairo_font_options_t *options)
@@ -1384,19 +1400,19 @@ static cairo_status_t
 _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
 {
     cairo_font_face_t *font_face;
 
     if (gstate->font_face != NULL)
 	return gstate->font_face->status;
 
 
-    font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
-					     CAIRO_FONT_SLANT_DEFAULT,
-					     CAIRO_FONT_WEIGHT_DEFAULT);
+    font_face = cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
+					    CAIRO_FONT_SLANT_DEFAULT,
+					    CAIRO_FONT_WEIGHT_DEFAULT);
     if (font_face->status)
 	return font_face->status;
 
     gstate->font_face = font_face;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1440,44 +1456,52 @@ cairo_status_t
 	return status;
 
     cairo_scaled_font_extents (gstate->scaled_font, extents);
 
     return cairo_scaled_font_status (gstate->scaled_font);
 }
 
 cairo_status_t
-_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
-			      const char     *utf8,
-			      double	      x,
-			      double	      y,
-			      cairo_glyph_t **glyphs,
-			      int	     *num_glyphs)
+_cairo_gstate_text_to_glyphs (cairo_gstate_t	    *gstate,
+			      double		     x,
+			      double		     y,
+			      const char	    *utf8,
+			      int		     utf8_len,
+			      cairo_glyph_t	   **glyphs,
+			      int		    *num_glyphs,
+			      cairo_text_cluster_t **clusters,
+			      int		    *num_clusters,
+			      cairo_bool_t	    *backward)
 {
     cairo_status_t status;
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
     if (status)
 	return status;
 
-    return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
-					      utf8, glyphs, num_glyphs);
+    return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
+					     utf8, utf8_len,
+					     glyphs, num_glyphs,
+					     clusters, num_clusters,
+					     backward);
 }
 
 cairo_status_t
 _cairo_gstate_set_font_face (cairo_gstate_t    *gstate,
 			     cairo_font_face_t *font_face)
 {
     if (font_face && font_face->status)
 	return font_face->status;
 
-    if (font_face != gstate->font_face) {
-	cairo_font_face_destroy (gstate->font_face);
-	gstate->font_face = cairo_font_face_reference (font_face);
-    }
+    if (font_face == gstate->font_face)
+	return CAIRO_STATUS_SUCCESS;
+
+    cairo_font_face_destroy (gstate->font_face);
+    gstate->font_face = cairo_font_face_reference (font_face);
 
     _cairo_gstate_unset_scaled_font (gstate);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
@@ -1496,17 +1520,17 @@ cairo_status_t
 				     extents);
 
     return cairo_scaled_font_status (gstate->scaled_font);
 }
 
 cairo_bool_t
 _cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
 {
-    return _cairo_surface_has_show_text_glyphs (gstate->target);
+    return cairo_surface_has_show_text_glyphs (gstate->target);
 }
 
 cairo_status_t
 _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				const char		   *utf8,
 				int			    utf8_len,
 				const cairo_glyph_t	   *glyphs,
 				int			    num_glyphs,
@@ -1528,31 +1552,35 @@ cairo_status_t
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
     if (status)
 	return status;
 
     if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
 	transformed_glyphs = stack_transformed_glyphs;
     } else {
-	transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
+	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
 	if (transformed_glyphs == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs, &num_glyphs);
 
     if (!num_glyphs)
 	goto CLEANUP_GLYPHS;
 
     status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
     if (status)
 	goto CLEANUP_GLYPHS;
 
+    /* Just in case */
+    if (!clusters)
+	num_clusters = 0;
+
     /* For really huge font sizes, we can just do path;fill instead of
      * show_glyphs, as show_glyphs would put excess pressure on the cache,
      * and moreover, not all components below us correctly handle huge font
      * sizes.  I wanted to set the limit at 256.  But alas, seems like cairo's
      * rasterizer is something like ten times slower than freetype's for huge
      * sizes.  So, no win just yet.  For now, do it for insanely-huge sizes,
      * just to make sure we don't make anyone unhappy.  When we get a really
      * fast rasterizer in cairo, we may want to readjust this.
@@ -1590,17 +1618,17 @@ cairo_status_t
 
 	_cairo_path_fixed_fini (&path);
     }
 
     _cairo_pattern_fini (&source_pattern.base);
 
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
-      free (transformed_glyphs);
+      cairo_glyph_free (transformed_glyphs);
 
     return status;
 }
 
 cairo_status_t
 _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
 			  const cairo_glyph_t *glyphs,
 			  int		       num_glyphs,
@@ -1612,31 +1640,31 @@ cairo_status_t
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
     if (status)
 	return status;
 
     if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs))
       transformed_glyphs = stack_transformed_glyphs;
     else
-      transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
+      transformed_glyphs = cairo_glyph_allocate (num_glyphs);
     if (transformed_glyphs == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs, NULL);
 
     CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
 					    path);
     CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
     if (transformed_glyphs != stack_transformed_glyphs)
-      free (transformed_glyphs);
+      cairo_glyph_free (transformed_glyphs);
 
     return status;
 }
 
 cairo_status_t
 _cairo_gstate_set_antialias (cairo_gstate_t *gstate,
 			     cairo_antialias_t antialias)
 {
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -254,24 +254,25 @@ cairo_surface_t *
 					int			stride)
 {
     cairo_int_status_t status;
     pixman_format_code_t pixman_format;
 
     status = _pixman_format_from_masks (masks, &pixman_format);
     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 	fprintf (stderr,
-		 "Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
+		 "Error: Cairo %s does not yet support the requested image format:\n"
 		 "\tDepth: %d\n"
 		 "\tAlpha mask: 0x%08lx\n"
 		 "\tRed   mask: 0x%08lx\n"
 		 "\tGreen mask: 0x%08lx\n"
 		 "\tBlue  mask: 0x%08lx\n"
 		 "Please file an enhancement request (quoting the above) at:\n"
 		 PACKAGE_BUGREPORT "\n",
+		 cairo_version_string (),
 		 masks->bpp, masks->alpha_mask,
 		 masks->red_mask, masks->green_mask, masks->blue_mask);
 
 	ASSERT_NOT_REACHED;
     }
 
     return _cairo_image_surface_create_with_pixman_format (data,
 							   pixman_format,
@@ -787,18 +788,19 @@ static cairo_status_t
     _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
 
     if (! pixman_image_set_transform (surface->pixman_image, &pixman_transform))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter)
+static cairo_status_t
+_cairo_image_surface_set_filter (cairo_image_surface_t *surface,
+				 cairo_filter_t filter)
 {
     pixman_filter_t pixman_filter;
 
     switch (filter) {
     case CAIRO_FILTER_FAST:
 	pixman_filter = PIXMAN_FILTER_FAST;
 	break;
     case CAIRO_FILTER_GOOD:
@@ -818,17 +820,24 @@ static void
 	 * whatsoever, so it was really a mistake to have it in the
 	 * API. We could fix this by officially deprecating it, or
 	 * else inventing semantics and providing an actual
 	 * implementation for it. */
     default:
 	pixman_filter = PIXMAN_FILTER_BEST;
     }
 
-    pixman_image_set_filter (surface->pixman_image, pixman_filter, NULL, 0);
+    if (! pixman_image_set_filter (surface->pixman_image,
+				   pixman_filter,
+				   NULL, 0))
+    {
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_image_surface_set_attributes (cairo_image_surface_t      *surface,
 				     cairo_surface_attributes_t *attributes)
 {
     cairo_int_status_t status;
 
@@ -846,17 +855,19 @@ static cairo_status_t
     case CAIRO_EXTEND_REFLECT:
         pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT);
 	break;
     case CAIRO_EXTEND_PAD:
         pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD);
 	break;
     }
 
-    _cairo_image_surface_set_filter (surface, attributes->filter);
+    status = _cairo_image_surface_set_filter (surface, attributes->filter);
+    if (status)
+	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* XXX: I think we should fix pixman to match the names/order of the
  * cairo operators, but that will likely be better done at the same
  * time the X server is ported to pixman, (which will change a lot of
  * things in pixman I think).
@@ -1053,18 +1064,17 @@ static cairo_int_status_t
     cairo_image_surface_t	*src;
     cairo_int_status_t		status;
     pixman_image_t		*mask;
     pixman_format_code_t	 format;
     uint32_t			*mask_data;
     pixman_trapezoid_t		 stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
     pixman_trapezoid_t		*pixman_traps = stack_traps;
     int				 mask_stride;
-    int				 mask_bpp;
-    int				 ret, i;
+    int				 i;
 
     if (height == 0 || width == 0)
 	return CAIRO_STATUS_SUCCESS;
 
     /* Convert traps to pixman traps */
     if (num_traps > ARRAY_LENGTH (stack_traps)) {
 	pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t));
 	if (pixman_traps == NULL)
@@ -1118,28 +1128,24 @@ static cairo_int_status_t
 
     status = _cairo_image_surface_set_attributes (src, &attributes);
     if (status)
 	goto CLEANUP_SOURCE;
 
     switch (antialias) {
     case CAIRO_ANTIALIAS_NONE:
 	format = PIXMAN_a1;
-	ret = 1;
 	mask_stride = ((width + 31) / 8) & ~0x03;
-	mask_bpp = 1;
 	break;
     case CAIRO_ANTIALIAS_GRAY:
     case CAIRO_ANTIALIAS_SUBPIXEL:
     case CAIRO_ANTIALIAS_DEFAULT:
     default:
 	format = PIXMAN_a8;
-	ret = 1;
 	mask_stride = (width + 3) & ~3;
-	mask_bpp = 8;
 	break;
     }
 
     /* The image must be initially transparent */
     mask_data = calloc (mask_stride, height);
     if (mask_data == NULL) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_SOURCE;
--- a/gfx/cairo/cairo/src/cairo-matrix.c
+++ b/gfx/cairo/cairo/src/cairo-matrix.c
@@ -483,17 +483,17 @@ static void
  *  returns %CAIRO_STATUS_INVALID_MATRIX.
  **/
 cairo_status_t
 cairo_matrix_invert (cairo_matrix_t *matrix)
 {
     /* inv (A) = 1/det (A) * adj (A) */
     double det;
 
-    _cairo_matrix_compute_determinant (matrix, &det);
+    det = _cairo_matrix_compute_determinant (matrix);
 
     if (! ISFINITE (det))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     if (det == 0)
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     _cairo_matrix_compute_adjoint (matrix);
@@ -503,75 +503,87 @@ cairo_matrix_invert (cairo_matrix_t *mat
 }
 slim_hidden_def(cairo_matrix_invert);
 
 cairo_bool_t
 _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
 {
     double det;
 
-    _cairo_matrix_compute_determinant (matrix, &det);
+    det = _cairo_matrix_compute_determinant (matrix);
 
     return ISFINITE (det) && det != 0.;
 }
 
-void
-_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
-				   double		*det)
+double
+_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix)
 {
     double a, b, c, d;
 
     a = matrix->xx; b = matrix->yx;
     c = matrix->xy; d = matrix->yy;
 
-    *det = a*d - b*c;
+    return a*d - b*c;
 }
 
-/* Compute the amount that each basis vector is scaled by. */
+/**
+ * _cairo_matrix_compute_basis_scale_factors:
+ * @matrix: a matrix
+ * @basis_scale: the scale factor in the direction of basis
+ * @normal_scale: the scale factor in the direction normal to the basis
+ * @x_basis: basis to use.  X basis if true, Y basis otherwise.
+ *
+ * Computes |Mv| and det(M)/|Mv| for v=[1,0] if x_basis is true, and v=[0,1]
+ * otherwise, and M is @matrix.
+ *
+ * Return value: the scale factor of @matrix on the height of the font,
+ * or 1.0 if @matrix is %NULL.
+ **/
 cairo_status_t
-_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
-				     double *sx, double *sy, int x_major)
+_cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix,
+					   double *basis_scale, double *normal_scale,
+					   cairo_bool_t x_basis)
 {
     double det;
 
-    _cairo_matrix_compute_determinant (matrix, &det);
+    det = _cairo_matrix_compute_determinant (matrix);
 
     if (! ISFINITE (det))
 	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
 
     if (det == 0)
     {
-	*sx = *sy = 0;
+	*basis_scale = *normal_scale = 0;
     }
     else
     {
-	double x = x_major != 0;
+	double x = x_basis != 0;
 	double y = x == 0;
 	double major, minor;
 
 	cairo_matrix_transform_distance (matrix, &x, &y);
 	major = sqrt(x*x + y*y);
 	/*
 	 * ignore mirroring
 	 */
 	if (det < 0)
 	    det = -det;
 	if (major)
 	    minor = det / major;
 	else
 	    minor = 0.0;
-	if (x_major)
+	if (x_basis)
 	{
-	    *sx = major;
-	    *sy = minor;
+	    *basis_scale = major;
+	    *normal_scale = minor;
 	}
 	else
 	{
-	    *sx = minor;
-	    *sy = major;
+	    *basis_scale = minor;
+	    *normal_scale = major;
 	}
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_bool_t
 _cairo_matrix_is_identity (const cairo_matrix_t *matrix)
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c
+++ b/gfx/cairo/cairo/src/cairo-meta-surface.c
@@ -839,24 +839,22 @@ static cairo_status_t
 					  command->mask.op,
 					  &command->mask.source.base,
 					  &command->mask.mask.base);
 	    break;
 	case CAIRO_COMMAND_STROKE:
 	{
 	    cairo_matrix_t dev_ctm = command->stroke.ctm;
 	    cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;
-	    cairo_matrix_t tmp;
 
 	    if (has_device_transform) {
 		cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
-		tmp = surface->device_transform;
-		status = cairo_matrix_invert (&tmp);
-		assert (status == CAIRO_STATUS_SUCCESS);
-		cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse);
+		cairo_matrix_multiply (&dev_ctm_inverse,
+				       &surface->device_transform_inverse,
+				       &dev_ctm_inverse);
 	    }
 
 	    status = _cairo_surface_stroke (target,
 					    command->stroke.op,
 					    &command->stroke.source.base,
 					    dev_path,
 					    &command->stroke.style,
 					    &dev_ctm,
@@ -880,27 +878,25 @@ static cairo_status_t
 		if (stroke_command->header.region != region)
 		    stroke_command = NULL;
 	    }
 	    if (stroke_command != NULL &&
 		stroke_command->header.type == CAIRO_COMMAND_STROKE &&
 		_cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) {
 		cairo_matrix_t dev_ctm;
 		cairo_matrix_t dev_ctm_inverse;
-		cairo_matrix_t tmp;
 
 		dev_ctm = stroke_command->stroke.ctm;
 		dev_ctm_inverse = stroke_command->stroke.ctm_inverse;
 
 		if (has_device_transform) {
 		    cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
-		    tmp = surface->device_transform;
-		    status = cairo_matrix_invert (&tmp);
-		    assert (status == CAIRO_STATUS_SUCCESS);
-		    cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse);
+		    cairo_matrix_multiply (&dev_ctm_inverse,
+					   &surface->device_transform_inverse,
+					   &dev_ctm_inverse);
 		}
 
 		status = _cairo_surface_fill_stroke (target,
 						     command->fill.op,
 						     &command->fill.source.base,
 						     command->fill.fill_rule,
 						     command->fill.tolerance,
 						     command->fill.antialias,
@@ -968,17 +964,16 @@ static cairo_status_t
 	    if (dev_path == NULL)
 		_cairo_clip_reset (&clip);
 	    else
 		status = _cairo_clip_clip (&clip, dev_path,
 					   command->intersect_clip_path.fill_rule,
 					   command->intersect_clip_path.tolerance,
 					   command->intersect_clip_path.antialias,
 					   target);
-            assert (status == 0);
 	    break;
 	default:
 	    ASSERT_NOT_REACHED;
 	}
 
 	if (dev_path == &path_copy)
 	    _cairo_path_fixed_fini (&path_copy);
 
--- a/gfx/cairo/cairo/src/cairo-misc.c
+++ b/gfx/cairo/cairo/src/cairo-misc.c
@@ -1,13 +1,14 @@
 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
  * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2007 Adrian Johnson
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -29,23 +30,26 @@
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
+ *      Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
 
 COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
 COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
 
+/* Public stuff */
+
 /**
  * cairo_status_to_string:
  * @status: a cairo status
  *
  * Provides a human-readable description of a #cairo_status_t.
  *
  * Returns: a string representation of the status
  */
@@ -108,21 +112,201 @@ cairo_status_to_string (cairo_status_t s
     case CAIRO_STATUS_USER_FONT_IMMUTABLE:
 	return "the user-font is immutable";
     case CAIRO_STATUS_USER_FONT_ERROR:
 	return "error occurred in a user-font callback function";
     case CAIRO_STATUS_NEGATIVE_COUNT:
 	return "negative number used where it is not allowed";
     case CAIRO_STATUS_INVALID_CLUSTERS:
 	return "input clusters do not represent the accompanying text and glyph arrays";
+    case CAIRO_STATUS_INVALID_SLANT:
+	return "invalid value for an input #cairo_font_slant_t";
+    case CAIRO_STATUS_INVALID_WEIGHT:
+	return "input value for an input #cairo_font_weight_t";
     }
 
     return "<unknown error status>";
 }
 
+
+/**
+ * cairo_glyph_allocate:
+ * @num_glyphs: number of glyphs to allocate
+ *
+ * Allocates an array of #cairo_glyph_t's.
+ * This function is only useful in implementations of
+ * #cairo_user_scaled_font_text_to_glyphs_func_t where the user
+ * needs to allocate an array of glyphs that cairo will free.
+ * For all other uses, user can use their own allocation method
+ * for glyphs.
+ *
+ * This function returns %NULL if @num_glyphs is not positive,
+ * or if out of memory.  That means, the %NULL return value
+ * signals out-of-memory only if @num_glyphs was positive.
+ *
+ * Returns: the newly allocated array of glyphs that should be
+ *          freed using cairo_glyph_free()
+ *
+ * Since: 1.8
+ */
+cairo_glyph_t *
+cairo_glyph_allocate (int num_glyphs)
+{
+    if (num_glyphs <= 0)
+	return NULL;
+
+    return _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+}
+slim_hidden_def (cairo_glyph_allocate);
+
+/**
+ * cairo_glyph_free:
+ * @glyphs: array of glyphs to free, or %NULL
+ *
+ * Frees an array of #cairo_glyph_t's allocated using cairo_glyph_allocate().
+ * This function is only useful to free glyph array returned
+ * by cairo_scaled_font_text_to_glyphs() where cairo returns
+ * an array of glyphs that the user will free.
+ * For all other uses, user can use their own allocation method
+ * for glyphs.
+ *
+ * Since: 1.8
+ */
+void
+cairo_glyph_free (cairo_glyph_t *glyphs)
+{
+    if (glyphs)
+	free (glyphs);
+}
+slim_hidden_def (cairo_glyph_free);
+
+/**
+ * cairo_text_cluster_allocate:
+ * @num_clusters: number of text_clusters to allocate
+ *
+ * Allocates an array of #cairo_text_cluster_t's.
+ * This function is only useful in implementations of
+ * #cairo_user_scaled_font_text_to_glyphs_func_t where the user
+ * needs to allocate an array of text clusters that cairo will free.
+ * For all other uses, user can use their own allocation method
+ * for text clusters.
+ *
+ * This function returns %NULL if @num_clusters is not positive,
+ * or if out of memory.  That means, the %NULL return value
+ * signals out-of-memory only if @num_clusters was positive.
+ *
+ * Returns: the newly allocated array of text clusters that should be
+ *          freed using cairo_text_cluster_free()
+ *
+ * Since: 1.8
+ */
+cairo_text_cluster_t *
+cairo_text_cluster_allocate (int num_clusters)
+{
+    if (num_clusters <= 0)
+	return NULL;
+
+    return _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
+}
+slim_hidden_def (cairo_text_cluster_allocate);
+
+/**
+ * cairo_text_cluster_free:
+ * @clusters: array of text clusters to free, or %NULL
+ *
+ * Frees an array of #cairo_text_cluster's allocated using cairo_text_cluster_allocate().
+ * This function is only useful to free text cluster array returned
+ * by cairo_scaled_font_text_to_glyphs() where cairo returns
+ * an array of text clusters that the user will free.
+ * For all other uses, user can use their own allocation method
+ * for text clusters.
+ *
+ * Since: 1.8
+ */
+void
+cairo_text_cluster_free (cairo_text_cluster_t *clusters)
+{
+    if (clusters)
+	free (clusters);
+}
+slim_hidden_def (cairo_text_cluster_free);
+
+
+/* Private stuff */
+
+/**
+ * _cairo_validate_text_clusters:
+ * @utf8: UTF-8 text
+ * @utf8_len: length of @utf8 in bytes
+ * @glyphs: array of glyphs
+ * @num_glyphs: number of glyphs
+ * @clusters: array of cluster mapping information
+ * @num_clusters: number of clusters in the mapping
+ * @backward: whether the text to glyphs mapping goes backward
+ *
+ * Check that clusters cover the entire glyphs and utf8 arrays,
+ * and that cluster boundaries are UTF-8 boundaries.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS upon success, or
+ *               %CAIRO_STATUS_INVALID_CLUSTERS on error.
+ *               The error is either invalid UTF-8 input,
+ *               or bad cluster mapping.
+ */
+cairo_status_t
+_cairo_validate_text_clusters (const char		   *utf8,
+			       int			    utf8_len,
+			       const cairo_glyph_t	   *glyphs,
+			       int			    num_glyphs,
+			       const cairo_text_cluster_t  *clusters,
+			       int			    num_clusters,
+			       cairo_bool_t		    backward)
+{
+    cairo_status_t status;
+    unsigned int n_bytes  = 0;
+    unsigned int n_glyphs = 0;
+    int i;
+
+    for (i = 0; i < num_clusters; i++) {
+	int cluster_bytes  = clusters[i].num_bytes;
+	int cluster_glyphs = clusters[i].num_glyphs;
+
+	if (cluster_bytes < 0 || cluster_glyphs < 0)
+	    goto BAD;
+
+	/* A cluster should cover at least one character or glyph.
+	 * I can't see any use for a 0,0 cluster.
+	 * I can't see an immediate use for a zero-text cluster
+	 * right now either, but they don't harm.
+	 * Zero-glyph clusters on the other hand are useful for
+	 * things like U+200C ZERO WIDTH NON-JOINER */
+	if (cluster_bytes == 0 && cluster_glyphs == 0)
+	    goto BAD;
+
+	/* Since n_bytes and n_glyphs are unsigned, but the rest of
+	 * values involved are signed, we can detect overflow easily */
+	if (n_bytes+cluster_bytes > (unsigned int)utf8_len || n_glyphs+cluster_glyphs > (unsigned int)num_glyphs)
+	    goto BAD;
+
+	/* Make sure we've got valid UTF-8 for the cluster */
+	status = _cairo_utf8_to_ucs4 (utf8+n_bytes, cluster_bytes, NULL, NULL);
+	if (status)
+	    return CAIRO_STATUS_INVALID_CLUSTERS;
+
+	n_bytes  += cluster_bytes ;
+	n_glyphs += cluster_glyphs;
+    }
+
+    if (n_bytes != (unsigned int) utf8_len || n_glyphs != (unsigned int) num_glyphs) {
+      BAD:
+	return CAIRO_STATUS_INVALID_CLUSTERS;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 /**
  * _cairo_operator_bounded_by_mask:
  * @op: a #cairo_operator_t
  *
  * A bounded operator is one where mask pixel
  * of zero results in no effect on the destination image.
  *
  * Unbounded operators often require special handling; if you, for
@@ -412,8 +596,74 @@ int
      * snippet.
      */
     output = (output & top) - (output & ~top);
 
     return output;
 #undef MSW
 #undef LSW
 }
+
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+#include <io.h>
+
+/* tmpfile() replacment for Windows.
+ *
+ * On Windows tmpfile() creates the file in the root directory. This
+ * may fail due to unsufficient privileges.
+ */
+FILE *
+_cairo_win32_tmpfile (void)
+{
+    DWORD path_len;
+    WCHAR path_name[MAX_PATH + 1];
+    WCHAR file_name[MAX_PATH + 1];
+    HANDLE handle;
+    int fd;
+    FILE *fp;
+
+    path_len = GetTempPathW (MAX_PATH, path_name);
+    if (path_len <= 0 || path_len >= MAX_PATH)
+	return NULL;
+
+    if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
+	return NULL;
+
+    handle = CreateFileW (file_name,
+			 GENERIC_READ | GENERIC_WRITE,
+			 0,
+			 NULL,
+			 CREATE_ALWAYS,
+			 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
+			 NULL);
+    if (handle == INVALID_HANDLE_VALUE) {
+	DeleteFileW (file_name);
+	return NULL;
+    }
+
+    fd = _open_osfhandle((intptr_t) handle, 0);
+    if (fd < 0) {
+	CloseHandle (handle);
+	return NULL;
+    }
+
+    fp = fdopen(fd, "w+b");
+    if (fp == NULL) {
+	_close(fd);
+	return NULL;
+    }
+
+    return fp;
+}
+
+#endif /* _WIN32 */
--- a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h
@@ -40,20 +40,16 @@
 
 #ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
 #define CAIRO_MUTEX_IMPL_PRIVATE_H
 
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include "cairo-features.h"
-
-CAIRO_BEGIN_DECLS
-
 
 /* A fully qualified no-operation statement */
 #define CAIRO_MUTEX_IMPL_NOOP	do {/*no-op*/} while (0)
 /* And one that evaluates it's argument once */
 #define CAIRO_MUTEX_IMPL_NOOP1(expr)        do { if (expr) ; } while (0)
 
 
 /* Cairo mutex implementation:
@@ -216,11 +212,9 @@ CAIRO_BEGIN_DECLS
 
 #else /**********************************************************************/
 
 # error "XXX: No mutex implementation found.  Cairo will not work with multiple threads.  Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
 
 
 #endif
 
-CAIRO_END_DECLS
-
 #endif
--- a/gfx/cairo/cairo/src/cairo-mutex-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-private.h
@@ -36,16 +36,20 @@
  *	Carl D. Worth <cworth@cworth.org>
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  *	Behdad Esfahbod <behdad@behdad.org>
  */
 
 #ifndef CAIRO_MUTEX_PRIVATE_H
 #define CAIRO_MUTEX_PRIVATE_H
 
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "cairo-mutex-type-private.h"
 
 CAIRO_BEGIN_DECLS
 
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
 cairo_private void _cairo_mutex_initialize (void);
 #endif
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
--- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h
@@ -36,22 +36,16 @@
  *	Carl D. Worth <cworth@cworth.org>
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  *	Behdad Esfahbod <behdad@behdad.org>
  */
 
 #ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
 #define CAIRO_MUTEX_TYPE_PRIVATE_H
 
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cairo-features.h"
-
 #include "cairo-compiler-private.h"
 #include "cairo-mutex-impl-private.h"
 
 /* Only the following three are mandatory at this point */
 #ifndef CAIRO_MUTEX_IMPL_LOCK
 # error "CAIRO_MUTEX_IMPL_LOCK not defined.  Check cairo-mutex-impl-private.h."
 #endif
 #ifndef CAIRO_MUTEX_IMPL_UNLOCK
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-no-features.h
@@ -0,0 +1,12 @@
+/* Generated by configure.  Do not edit */
+#ifndef CAIRO_NO_FEATURES_H
+#define CAIRO_NO_FEATURES_H
+
+#include <cairo-features.h>
+
+/* This is a dummy header, to trick gtk-doc only */
+
+#define CAIRO_HAS_WIN32_FONT 1
+#define CAIRO_HAS_WIN32_SURFACE 1
+
+#endif
--- a/gfx/cairo/cairo/src/cairo-output-stream-private.h
+++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h
@@ -34,16 +34,20 @@
  */
 
 #ifndef CAIRO_OUTPUT_STREAM_PRIVATE_H
 #define CAIRO_OUTPUT_STREAM_PRIVATE_H
 
 #include "cairo-compiler-private.h"
 #include "cairo-types-private.h"
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
 typedef cairo_status_t (*cairo_output_stream_write_func_t) (cairo_output_stream_t *output_stream,
 							    const unsigned char   *data,
 							    unsigned int           length);
 
 typedef cairo_status_t (*cairo_output_stream_close_func_t) (cairo_output_stream_t *output_stream);
 
 struct _cairo_output_stream {
     cairo_output_stream_write_func_t write_func;
@@ -102,17 +106,17 @@ cairo_private cairo_status_t
 _cairo_output_stream_destroy (cairo_output_stream_t *stream);
 
 cairo_private void
 _cairo_output_stream_write (cairo_output_stream_t *stream,
 			    const void *data, size_t length);
 
 cairo_private void
 _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
-				       const char *data,
+				       const unsigned char *data,
 				       size_t length);
 
 cairo_private void
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
 			      const char *fmt,
 			      va_list ap) CAIRO_PRINTF_FORMAT ( 2, 0);
 
 cairo_private void
--- a/gfx/cairo/cairo/src/cairo-output-stream.c
+++ b/gfx/cairo/cairo/src/cairo-output-stream.c
@@ -232,17 +232,17 @@ void
 	return;
 
     stream->status = stream->write_func (stream, data, length);
     stream->position += length;
 }
 
 void
 _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
-				       const char *data,
+				       const unsigned char *data,
 				       size_t length)
 {
     const char hex_chars[] = "0123456789abcdef";
     char buffer[2];
     unsigned int i, column;
 
     if (stream->status)
 	return;
@@ -418,17 +418,16 @@ void
 	assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
 
 	/* Reuse the format string for this conversion. */
 	memcpy (single_fmt, start, single_fmt_length);
 	single_fmt[single_fmt_length] = '\0';
 
 	/* Flush contents of buffer before snprintf()'ing into it. */
 	_cairo_output_stream_write (stream, buffer, p - buffer);
-	p = buffer;
 
 	/* We group signed and unsigned together in this switch, the
 	 * only thing that matters here is the size of the arguments,
 	 * since we're just passing the data through to sprintf(). */
 	switch (*f | length_modifier) {
 	case '%':
 	    buffer[0] = *f;
 	    buffer[1] = 0;
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -604,17 +604,17 @@ static cairo_int_status_t
 				tolerance, antialias);
 }
 
 static cairo_bool_t
 _cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
 
-    return _cairo_surface_has_show_text_glyphs (surface->target);
+    return cairo_surface_has_show_text_glyphs (surface->target);
 }
 
 static cairo_int_status_t
 _cairo_paginated_surface_show_text_glyphs (void			    *abstract_surface,
 					  cairo_operator_t	     op,
 					  cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
--- a/gfx/cairo/cairo/src/cairo-path-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-path-fixed-private.h
@@ -31,16 +31,18 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@redhat.com>
  */
 
 #ifndef CAIRO_PATH_FIXED_PRIVATE_H
 #define CAIRO_PATH_FIXED_PRIVATE_H
 
+#include "cairo-types-private.h"
+
 enum cairo_path_op {
     CAIRO_PATH_OP_MOVE_TO = 0,
     CAIRO_PATH_OP_LINE_TO = 1,
     CAIRO_PATH_OP_CURVE_TO = 2,
     CAIRO_PATH_OP_CLOSE_PATH = 3
 };
 /* we want to make sure a single byte is used for thie enum */
 typedef char cairo_path_op_t;
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -164,21 +164,18 @@ static cairo_status_t
 {
     cairo_status_t status;
     stroker->style = stroke_style;
     stroker->ctm = ctm;
     stroker->ctm_inverse = ctm_inverse;
     stroker->tolerance = tolerance;
     stroker->traps = traps;
 
-    _cairo_matrix_compute_determinant (stroker->ctm, &stroker->ctm_determinant);
-    if (stroker->ctm_determinant >= 0.0)
-	stroker->ctm_det_positive = TRUE;
-    else
-	stroker->ctm_det_positive = FALSE;
+    stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm);
+    stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0;
 
     status = _cairo_pen_init (&stroker->pen,
 		              stroke_style->line_width / 2.0,
 			      tolerance, ctm);
     if (status)
 	return status;
 
     stroker->has_current_face = FALSE;
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -90,19 +90,22 @@ static cairo_status_t
 
     return _cairo_error (status);
 }
 
 static void
 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
 {
     pattern->type      = type;
-    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
     pattern->status    = CAIRO_STATUS_SUCCESS;
 
+    /* Set the reference count to zero for on-stack patterns.
+     * Callers needs to explicitly increment the count for heap allocations. */
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
+
     _cairo_user_data_array_init (&pattern->user_data);
 
     if (type == CAIRO_PATTERN_TYPE_SURFACE)
 	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
     else
 	pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
 
     pattern->filter    = CAIRO_FILTER_DEFAULT;
@@ -178,17 +181,17 @@ cairo_status_t
 	status = _cairo_gradient_pattern_init_copy (dst, src);
 	if (status)
 	    return status;
 
     } break;
     }
 
     /* The reference count and user_data array are unique to the copy. */
-    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
     _cairo_user_data_array_init (&pattern->user_data);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_pattern_fini (cairo_pattern_t *pattern)
 {
@@ -241,16 +244,18 @@ cairo_status_t
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     status = _cairo_pattern_init_copy (*pattern, other);
     if (status) {
 	free (*pattern);
 	return status;
     }
 
+    CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 
 void
 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
 			   const cairo_color_t	 *color,
 			   cairo_content_t	  content)
@@ -345,18 +350,20 @@ cairo_pattern_t *
     if (pattern == NULL) {
 	/* None cached, need to create a new pattern. */
 	pattern = malloc (sizeof (cairo_solid_pattern_t));
     }
 
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	pattern = (cairo_solid_pattern_t *) &_cairo_pattern_nil;
-    } else
+    } else {
 	_cairo_pattern_init_solid (pattern, color, content);
+	CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
+    }
 
     return &pattern->base;
 }
 
 static void
 _cairo_pattern_reset_solid_pattern_cache (void)
 {
     int i;
@@ -499,16 +506,17 @@ cairo_pattern_create_for_surface (cairo_
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *)&_cairo_pattern_nil.base;
     }
 
     CAIRO_MUTEX_INITIALIZE ();
 
     _cairo_pattern_init_for_surface (pattern, surface);
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
 
     return &pattern->base;
 }
 slim_hidden_def (cairo_pattern_create_for_surface);
 
 /**
  * cairo_pattern_create_linear:
  * @x0: x coordinate of the start point
@@ -544,16 +552,17 @@ cairo_pattern_create_linear (double x0, 
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     }
 
     CAIRO_MUTEX_INITIALIZE ();
 
     _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
 
     return &pattern->base.base;
 }
 
 /**
  * cairo_pattern_create_radial:
  * @cx0: x coordinate for the center of the start circle
  * @cy0: y coordinate for the center of the start circle
@@ -591,16 +600,17 @@ cairo_pattern_create_radial (double cx0,
     if (pattern == NULL) {
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     }
 
     CAIRO_MUTEX_INITIALIZE ();
 
     _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
+    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
 
     return &pattern->base.base;
 }
 
 /**
  * cairo_pattern_reference:
  * @pattern: a #cairo_pattern_t
  *
@@ -1303,25 +1313,30 @@ static cairo_int_status_t
 	 * computing a sample.
 	 */
 	if (is_vertical && width > 8) {
 	    width = 8;
 	    repeat = TRUE;
 	}
     }
 
+    if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
+				   NULL, 0))
+    {
+	pixman_image_unref (pixman_image);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
     image = (cairo_image_surface_t *)
 	cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
     if (image->base.status) {
 	pixman_image_unref (pixman_image);
 	return image->base.status;
     }
 
-    pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR, NULL, 0);
-
     _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
     if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
 	cairo_surface_destroy (&image->base);
 	pixman_image_unref (pixman_image);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     switch (pattern->base.extend) {
@@ -2073,20 +2088,21 @@ cairo_status_t
 	return CAIRO_STATUS_SUCCESS;
     }
 
     /* XXX: We could optimize gradients with pattern->extend of NONE
      * here in some cases, (eg. radial gradients and 1 axis of
      * horizontal/vertical linear gradients).
      */
 
+    /* unbounded patterns -> 'infinite' extents */
     extents->x = CAIRO_RECT_INT_MIN;
     extents->y = CAIRO_RECT_INT_MIN;
-    extents->width = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
-    extents->height = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
+    extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * cairo_pattern_get_rgba
  * @pattern: a #cairo_pattern_t
  * @red: return value for red component of color, or %NULL
--- a/gfx/cairo/cairo/src/cairo-pdf-operators-private.h
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h
@@ -157,10 +157,9 @@ cairo_private cairo_int_status_t
 				       int                         utf8_len,
 				       cairo_glyph_t              *glyphs,
 				       int                         num_glyphs,
 				       const cairo_text_cluster_t *clusters,
 				       int                         num_clusters,
 				       cairo_bool_t                backward,
 				       cairo_scaled_font_t	  *scaled_font);
 
-
 #endif /* CAIRO_PDF_OPERATORS_H */
--- a/gfx/cairo/cairo/src/cairo-pdf-operators.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c
@@ -35,16 +35,19 @@
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
+
+#if CAIRO_HAS_PDF_OPERATORS
+
 #include "cairo-pdf-operators-private.h"
 #include "cairo-path-fixed-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 
 #include <ctype.h>
 
 static cairo_status_t
@@ -678,25 +681,28 @@ static void
 }
 
 static cairo_int_status_t
 _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t	*pdf_operators,
 				  cairo_path_fixed_t	*path,
 				  cairo_stroke_style_t	*style,
 				  cairo_matrix_t	*ctm,
 				  cairo_matrix_t	*ctm_inverse,
-				  const char 		*pdf_operator)
+				  const char		*pdf_operator)
 {
     cairo_status_t status;
     cairo_matrix_t m, path_transform;
     cairo_bool_t has_ctm = TRUE;
     double scale = 1.0;
 
-    if (pdf_operators->in_text_object)
+    if (pdf_operators->in_text_object) {
 	status = _cairo_pdf_operators_end_text (pdf_operators);
+	if (status)
+	    return status;
+    }
 
     /* Optimize away the stroke ctm when it does not affect the
      * stroke. There are other ctm cases that could be optimized
      * however this is the most common.
      */
     if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 &&
 	fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0)
     {
@@ -783,18 +789,21 @@ cairo_int_status_t
 cairo_int_status_t
 _cairo_pdf_operators_fill (cairo_pdf_operators_t	*pdf_operators,
 			   cairo_path_fixed_t		*path,
 			   cairo_fill_rule_t		fill_rule)
 {
     const char *pdf_operator;
     cairo_status_t status;
 
-    if (pdf_operators->in_text_object)
+    if (pdf_operators->in_text_object) {
 	status = _cairo_pdf_operators_end_text (pdf_operators);
+	if (status)
+	    return status;
+    }
 
     status = _cairo_pdf_operators_emit_path (pdf_operators,
 					     path,
 					     &pdf_operators->cairo_to_pdf,
 					     CAIRO_LINE_CAP_ROUND);
     if (status)
 	return status;
 
@@ -922,22 +931,22 @@ static cairo_status_t
 
     return _cairo_output_stream_get_status (stream);
 }
 
 static cairo_status_t
 _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
 {
     cairo_output_stream_t *word_wrap_stream;
-    cairo_status_t status;
+    cairo_status_t status, status2;
     int i;
     double x;
 
     if (pdf_operators->num_glyphs == 0)
-	return 0;
+	return CAIRO_STATUS_SUCCESS;
 
     word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
     status = _cairo_output_stream_get_status (word_wrap_stream);
     if (status)
 	return _cairo_output_stream_destroy (word_wrap_stream);
 
     /* Check if glyph advance used to position every glyph */
     x = pdf_operators->cur_x;
@@ -950,19 +959,19 @@ static cairo_status_t
 	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
 							 word_wrap_stream);
     } else {
 	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
 	    pdf_operators, word_wrap_stream);
     }
 
     pdf_operators->num_glyphs = 0;
-    status = _cairo_output_stream_destroy (word_wrap_stream);
-    if (status)
-	return status;
+    status2 = _cairo_output_stream_destroy (word_wrap_stream);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators,
 				cairo_scaled_font_subsets_glyph_t *glyph,
 				double 			           x_position)
@@ -1261,39 +1270,47 @@ static cairo_int_status_t
      * Mapping a glyph to a zero length unicode string requires the
      * use of ActualText.
      */
     if (num_glyphs == 1 && utf8_len != 0) {
 	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
 						       scaled_font,
 						       glyphs->index,
 						       utf8,
-						       utf8_len < 0 ? 0 : utf8_len,
+						       utf8_len,
 						       &subset_glyph);
 	if (status)
 	    return status;
 
 	if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
 	    status = _cairo_pdf_operators_emit_glyph (pdf_operators,
 						      glyphs,
 						      &subset_glyph);
-	    return 0;
+	    if (status)
+		return status;
+
+	    return CAIRO_STATUS_SUCCESS;
 	}
     }
 
     /* Fallback to using ActualText to map zero or more glyphs to a
      * unicode string. */
     _cairo_pdf_operators_flush_glyphs (pdf_operators);
     status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
+    if (status)
+	return status;
+
     cur_glyph = glyphs;
+    /* XXX
+     * If no glyphs, we should put *something* here for the text to be selectable. */
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
 						       scaled_font,
 						       cur_glyph->index,
-						       NULL, 0,
+						       NULL, -1,
 						       &subset_glyph);
 	if (status)
 	    return status;
 
 	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
 						  cur_glyph,
 						  &subset_glyph);
 	if (status)
@@ -1406,8 +1423,10 @@ cairo_int_status_t
 							scaled_font);
 	    if (status)
 		return status;
 	}
     }
 
     return _cairo_output_stream_get_status (pdf_operators->stream);
 }
+
+#endif /* CAIRO_HAS_PDF_OPERATORS */
--- a/gfx/cairo/cairo/src/cairo-pdf-surface.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c
@@ -2863,17 +2863,17 @@ static cairo_status_t
 {
     uint16_t *utf16 = NULL;
     int utf16_len = 0;
     cairo_status_t status;
     int i;
 
     if (utf8 && *utf8) {
 	status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
-	if (status && status != CAIRO_STATUS_INVALID_STRING)
+	if (status)
 	    return status;
     }
 
     _cairo_output_stream_printf (surface->output, "<");
     if (utf16 == NULL || utf16_len == 0) {
 	/* According to the "ToUnicode Mapping File Tutorial"
 	 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
 	 *
@@ -3439,17 +3439,17 @@ static cairo_status_t
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
 			     cairo_output_stream_t *stream)
 {
-    unsigned char *byte, output_byte;
+    uint8_t *byte, output_byte;
     int row, col, num_cols;
 
     /* The only image type supported by Type 3 fonts are 1-bit image
      * masks */
     assert (image->format == CAIRO_FORMAT_A1);
 
     _cairo_output_stream_printf (stream,
 				 "BI\n"
@@ -3482,17 +3482,16 @@ static cairo_status_t
 
 static cairo_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
-    cairo_matrix_t matrix;
     double *widths;
     unsigned int i;
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
     cairo_surface_t *type3_surface;
 
     if (font_subset->num_glyphs == 0)
 	return CAIRO_STATUS_SUCCESS;
@@ -3517,29 +3516,35 @@ static cairo_status_t
 						       NULL,
 						       _cairo_pdf_emit_imagemask);
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	status = _cairo_pdf_surface_open_stream (surface,
 						 NULL,
 						 surface->compress_content,
 						 NULL);
+	if (status)
+	    break;
+
 	glyphs[i] = surface->pdf_stream.self;
 	if (i == 0) {
 	    status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
 								   surface->output,
 								   &bbox,
 								   &widths[i]);
 	} else {
 	    status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
 							    surface->output,
 							    font_subset->glyphs[i],
 							    &bbox,
 							    &widths[i]);
 	}
+	if (status)
+	    break;
+
 	status = _cairo_pdf_surface_close_stream (surface);
 	if (status)
 	    break;
 
         if (i == 0) {
             font_bbox.p1.x = bbox.p1.x;
             font_bbox.p1.y = bbox.p1.y;
             font_bbox.p2.x = bbox.p2.x;
@@ -3605,17 +3610,16 @@ static cairo_status_t
 	                                                font_subset, FALSE,
 							&to_unicode_stream);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
 	free (widths);
 	return status;
     }
 
     _cairo_pdf_surface_update_object (surface, subset_resource);
-    matrix = font_subset->scaled_font->scale_inverse;
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\n"
 				 "<< /Type /Font\n"
 				 "   /Subtype /Type3\n"
 				 "   /FontBBox [%f %f %f %f]\n"
 				 "   /FontMatrix [ 1 0 0 1 0 0 ]\n"
 				 "   /Encoding %d 0 R\n"
 				 "   /CharProcs %d 0 R\n"
@@ -4778,18 +4782,18 @@ static cairo_int_status_t
 	if (group == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_SHOW_GLYPHS;
 	group->source = cairo_pattern_reference (source);
 	group->source_res = pattern_res;
 
 	if (utf8_len) {
-	    group->utf8 = malloc(utf8_len);
-	    if (group->utf8) {
+	    group->utf8 = malloc (utf8_len);
+	    if (group->utf8 == NULL) {
 		_cairo_pdf_smask_group_destroy (group);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 	    memcpy (group->utf8, utf8, utf8_len);
 	}
 	group->utf8_len = utf8_len;
 
 	if (num_glyphs) {
@@ -4799,17 +4803,17 @@ static cairo_int_status_t
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 	    memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	}
 	group->num_glyphs = num_glyphs;
 
 	if (num_clusters) {
 	    group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
-	    if (group->clusters) {
+	    if (group->clusters == NULL) {
 		_cairo_pdf_smask_group_destroy (group);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    }
 	    memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
 	}
 	group->num_clusters = num_clusters;
 
 	group->scaled_font = cairo_scaled_font_reference (scaled_font);
--- a/gfx/cairo/cairo/src/cairo-pen.c
+++ b/gfx/cairo/cairo/src/cairo-pen.c
@@ -48,27 +48,21 @@ static void
 cairo_status_t
 _cairo_pen_init (cairo_pen_t	*pen,
 		 double		 radius,
 		 double		 tolerance,
 		 cairo_matrix_t	*ctm)
 {
     int i;
     int reflect;
-    double  det;
 
     pen->radius = radius;
     pen->tolerance = tolerance;
 
-    _cairo_matrix_compute_determinant (ctm, &det);
-    if (det >= 0) {
-	reflect = 0;
-    } else {
-	reflect = 1;
-    }
+    reflect = _cairo_matrix_compute_determinant (ctm) < 0.;
 
     pen->num_vertices = _cairo_pen_vertices_needed (tolerance,
 						    radius,
 						    ctm);
 
     if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
 	pen->vertices = _cairo_malloc_ab (pen->num_vertices,
 					  sizeof (cairo_pen_vertex_t));
--- a/gfx/cairo/cairo/src/cairo-png.c
+++ b/gfx/cairo/cairo/src/cairo-png.c
@@ -114,28 +114,34 @@ png_simple_warning_callback (png_structp
     /* default to the most likely error */
     if (*error == CAIRO_STATUS_SUCCESS)
 	*error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     /* png does not expect to abort and will try to tidy up after a warning */
 }
 
 
+/* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn.
+ * Otherwise, we will segfault if we are writing to a stream. */
+static void
+png_simple_output_flush_fn (png_structp png_ptr)
+{
+}
+
 static cairo_status_t
 write_png (cairo_surface_t	*surface,
 	   png_rw_ptr		write_func,
 	   void			*closure)
 {
     int i;
     cairo_status_t status;
     cairo_image_surface_t *image;
     void *image_extra;
     png_struct *png;
     png_info *info;
-    png_time pt;
     png_byte **volatile rows = NULL;
     png_color_16 white;
     int png_color_type;
     int depth;
 
     status = _cairo_surface_acquire_source_image (surface,
 						  &image,
 						  &image_extra);
@@ -174,17 +180,17 @@ write_png (cairo_surface_t	*surface,
 	goto BAIL3;
     }
 
 #ifdef PNG_SETJMP_SUPPORTED
     if (setjmp (png_jmpbuf (png)))
 	goto BAIL3;
 #endif
 
-    png_set_write_fn (png, closure, write_func, NULL);
+    png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
 
     switch (image->format) {
     case CAIRO_FORMAT_ARGB32:
 	depth = 8;
 	png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
 	break;
     case CAIRO_FORMAT_RGB24:
 	depth = 8;
@@ -213,18 +219,22 @@ write_png (cairo_surface_t	*surface,
 		  PNG_INTERLACE_NONE,
 		  PNG_COMPRESSION_TYPE_DEFAULT,
 		  PNG_FILTER_TYPE_DEFAULT);
 
     white.gray = (1 << depth) - 1;
     white.red = white.blue = white.green = white.gray;
     png_set_bKGD (png, info, &white);
 
-    png_convert_from_time_t (&pt, time (NULL));
-    png_set_tIME (png, info, &pt);
+    if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
+	png_time pt;
+
+	png_convert_from_time_t (&pt, time (NULL));
+	png_set_tIME (png, info, &pt);
+    }
 
     /* We have to call png_write_info() before setting up the write
      * transformation, since it stores data internally in 'png'
      * that is needed for the write transformation functions to work.
      */
     png_write_info (png, info);
 
     if (image->format == CAIRO_FORMAT_ARGB32)
--- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h
@@ -41,16 +41,18 @@
 #ifndef CAIRO_PS_SURFACE_PRIVATE_H
 #define CAIRO_PS_SURFACE_PRIVATE_H
 
 #include "cairo-ps.h"
 
 #include "cairo-surface-private.h"
 #include "cairo-pdf-operators-private.h"
 
+#include <time.h>
+
 typedef struct cairo_ps_surface {
     cairo_surface_t base;
 
     /* Here final_stream corresponds to the stream/file passed to
      * cairo_ps_surface_create surface is built. Meanwhile stream is a
      * temporary stream in which the file output is built, (so that
      * the header can be built and inserted into the target stream
      * before the contents of the temporary stream are copied). */
@@ -75,16 +77,18 @@ typedef struct cairo_ps_surface {
     double current_color_blue;
     double current_color_alpha;
 
     int num_pages;
 
     cairo_paginated_mode_t paginated_mode;
 
     cairo_bool_t force_fallbacks;
+    cairo_bool_t has_creation_date;
+    time_t creation_date;
 
     cairo_scaled_font_subsets_t *font_subsets;
 
     cairo_array_t dsc_header_comments;
     cairo_array_t dsc_setup_comments;
     cairo_array_t dsc_page_setup_comments;
 
     cairo_array_t *dsc_comment_target;
--- a/gfx/cairo/cairo/src/cairo-ps-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ps-surface.c
@@ -85,17 +85,20 @@ static void
 {
     char ctime_buf[26];
     time_t now;
     char **comments;
     int i, num_comments;
     int level;
     const char *eps_header = "";
 
-    now = time (NULL);
+    if (surface->has_creation_date)
+	now = surface->creation_date;
+    else
+	now = time (NULL);
 
     if (surface->ps_level_used == CAIRO_PS_LEVEL_2)
 	level = 2;
     else
 	level = 3;
 
     if (surface->eps)
 	eps_header = " EPSF-3.0";
@@ -359,17 +362,17 @@ static cairo_status_t
     end = 0;
     for (i = 0; i < subset.num_string_offsets; i++) {
         end = subset.string_offsets[i];
         _cairo_output_stream_printf (surface->final_stream,"<");
         _cairo_output_stream_write_hex_string (surface->final_stream,
                                                subset.data + begin, end - begin);
         _cairo_output_stream_printf (surface->final_stream,"00>\n");
         begin = end;
-    } 
+    }
     if (subset.data_length > end) {
         _cairo_output_stream_printf (surface->final_stream,"<");
         _cairo_output_stream_write_hex_string (surface->final_stream,
                                                subset.data + end, subset.data_length - end);
         _cairo_output_stream_printf (surface->final_stream,"00>\n");
     }
 
     _cairo_output_stream_printf (surface->final_stream,
@@ -380,17 +383,17 @@ static cairo_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
 			  cairo_output_stream_t *stream)
 {
-    unsigned char *row, *byte;
+    uint8_t *row, *byte;
     int rows, cols;
 
     /* The only image type supported by Type 3 fonts are 1-bit image
      * masks */
     assert (image->format == CAIRO_FORMAT_A1);
 
     _cairo_output_stream_printf (stream,
 				 "<<\n"
@@ -402,55 +405,50 @@ static cairo_status_t
 				 "   /BitsPerComponent 1\n",
 				 image->width,
 				 image->height,
 				 image->width,
 				 -image->height,
 				 image->height);
 
     _cairo_output_stream_printf (stream,
-				 "   /DataSource   {<");
+				 "   /DataSource {<\n   ");
     for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
 	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
-	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
 	    _cairo_output_stream_printf (stream, "%02x ", output_byte);
 	}
 	_cairo_output_stream_printf (stream, "\n   ");
     }
-    _cairo_output_stream_printf (stream,
-				 "   >}\n");
-    _cairo_output_stream_printf (stream,
-				 ">>\n");
+    _cairo_output_stream_printf (stream, ">}\n>>\n");
 
     _cairo_output_stream_printf (stream,
 				 "imagemask\n");
 
     return _cairo_output_stream_get_status (stream);
 }
 
 static cairo_status_t
 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
 
 
 {
     cairo_status_t status;
-    cairo_matrix_t matrix;
     unsigned int i;
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
     cairo_surface_t *type3_surface;
     double width;
 
 #if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_type3_font_subset\n");
 #endif
 
-    matrix = font_subset->scaled_font->scale_inverse;
     _cairo_output_stream_printf (surface->final_stream,
 				 "8 dict begin\n"
 				 "/FontType 3 def\n"
 				 "/FontMatrix [1 0 0 1 0 0] def\n"
 				 "/Encoding 256 array def\n"
 				 "0 1 255 { Encoding exch /.notdef put } for\n");
 
     type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
@@ -613,16 +611,19 @@ static cairo_status_t
 
     if (ferror (surface->tmpfile) != 0)
 	return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
 
     rewind (surface->tmpfile);
     while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
 	_cairo_output_stream_write (surface->final_stream, buf, n);
 
+    if (ferror (surface->tmpfile) != 0)
+	return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface)
 {
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%Trailer\n");
@@ -676,16 +677,17 @@ static cairo_surface_t *
 	goto CLEANUP_OUTPUT_STREAM;
 
     surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
     if (surface->font_subsets == NULL) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_OUTPUT_STREAM;
     }
 
+    surface->has_creation_date = FALSE;
     surface->eps = FALSE;
     surface->ps_level = CAIRO_PS_LEVEL_3;
     surface->ps_level_used = CAIRO_PS_LEVEL_2;
     surface->width  = width;
     surface->height = height;
     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, height);
     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
     surface->force_fallbacks = FALSE;
@@ -1580,17 +1582,20 @@ static cairo_status_t
 		break;
 	    }
 	}
 	/* Have to be careful to never split the final ~> sequence. */
         if (c == '~') {
 	    _cairo_output_stream_write (stream->output, &c, 1);
 	    stream->column++;
 	    stream->string_size++;
-	    length--;
+
+	    if (length-- == 0)
+		break;
+
 	    c = *data++;
 	}
 	_cairo_output_stream_write (stream->output, &c, 1);
 	stream->column++;
 	stream->string_size++;
 
 	if (stream->use_strings &&
 	    stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE)
@@ -2226,21 +2231,23 @@ static cairo_status_t
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     ps_p2d = surface->cairo_to_ps;
     cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
     cairo_matrix_translate (&ps_p2d, 0.0, height);
     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
 
-    _cairo_output_stream_printf (surface->stream,
-				 "[ %f %f %f %f %f %f ] concat\n",
-				 ps_p2d.xx, ps_p2d.yx,
-				 ps_p2d.xy, ps_p2d.yy,
-				 ps_p2d.x0, ps_p2d.y0);
+    if (! _cairo_matrix_is_identity (&ps_p2d)) {
+	_cairo_output_stream_printf (surface->stream,
+				     "[ %f %f %f %f %f %f ] concat\n",
+				     ps_p2d.xx, ps_p2d.yx,
+				     ps_p2d.xy, ps_p2d.yy,
+				     ps_p2d.x0, ps_p2d.y0);
+    }
 
     status = _cairo_ps_surface_emit_surface (surface, pattern, op);
     _cairo_ps_surface_release_surface (surface, pattern);
 
     return status;
 }
 
 static cairo_status_t
@@ -2700,27 +2707,27 @@ static cairo_status_t
     }
 
     _cairo_output_stream_printf (surface->stream,
 				 "<< /PatternType 2\n"
 				 "   /Shading\n"
 				 "   << /ShadingType 2\n"
 				 "      /ColorSpace /DeviceRGB\n"
 				 "      /Coords [ %f %f %f %f ]\n"
-                                 "      /Domain [ %f %f ]\r\n"
+                                 "      /Domain [ %f %f ]\n"
 				 "      /Function CairoFunction\n",
 				 x1, y1, x2, y2,
 				 first_stop, last_stop);
 
     if (extend == CAIRO_EXTEND_PAD) {
 	_cairo_output_stream_printf (surface->stream,
-                                     "      /Extend [ true true ]\r\n");
+                                     "      /Extend [ true true ]\n");
     } else {
 	_cairo_output_stream_printf (surface->stream,
-                                     "      /Extend [ false false ]\r\n");
+                                     "      /Extend [ false false ]\n");
     }
 
     _cairo_output_stream_printf (surface->stream,
 				 "   >>\n"
 				 ">>\n");
     _cairo_output_stream_printf (surface->stream,
 				 "[ %f %f %f %f %f %f ]\n",
                                  pat_to_ps.xx, pat_to_ps.yx,
@@ -2782,20 +2789,20 @@ static cairo_status_t
 				 "   << /ShadingType 3\n"
 				 "      /ColorSpace /DeviceRGB\n"
 				 "      /Coords [ %f %f %f %f %f %f ]\n"
 				 "      /Function CairoFunction\n",
 				 x1, y1, r1, x2, y2, r2);
 
     if (extend == CAIRO_EXTEND_PAD) {
 	_cairo_output_stream_printf (surface->stream,
-                                     "      /Extend [ true true ]\r\n");
+                                     "      /Extend [ true true ]\n");
     } else {
 	_cairo_output_stream_printf (surface->stream,
-                                     "      /Extend [ false false ]\r\n");
+                                     "      /Extend [ false false ]\n");
     }
 
     _cairo_output_stream_printf (surface->stream,
 				 "   >>\n"
 				 ">>\n");
 
     _cairo_output_stream_printf (surface->stream,
 				 "[ %f %f %f %f %f %f ]\n",
--- a/gfx/cairo/cairo/src/cairo-quartz-font.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-font.c
@@ -385,17 +385,17 @@ static inline CGGlyph
 static inline cairo_status_t
 _cairo_matrix_to_unit_quartz_matrix (const cairo_matrix_t *m, CGAffineTransform *txout,
 				     double *xout, double *yout)
 {
     CGAffineTransform transform;
     double xscale, yscale;
     cairo_status_t status;
 
-    status = _cairo_matrix_compute_scale_factors (m, &xscale, &yscale, 1);
+    status = _cairo_matrix_compute_basis_scale_factors (m, &xscale, &yscale, 1);
     if (status)
 	return status;
 
     transform = CGAffineTransformMake (m->xx, - m->yx,
 				       - m->xy, m->yy,
 				       0.0f, 0.0f);
     if (xout)
 	*xout = xscale;
@@ -430,17 +430,17 @@ static cairo_int_status_t
 
     if (glyph == INVALID_GLYPH)
 	goto FAIL;
 
     if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
 	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
 	goto FAIL;
 
-    status = _cairo_matrix_compute_scale_factors (&font->base.scale,
+    status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale,
 						  &xscale, &yscale, 1);
     if (status)
 	goto FAIL;
 
     bbox = CGRectMake (bbox.origin.x / emscale,
 		       bbox.origin.y / emscale,
 		       bbox.size.width / emscale,
 		       bbox.size.height / emscale);
@@ -627,17 +627,17 @@ static cairo_int_status_t
     }
 
     if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
 	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
     {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    status = _cairo_matrix_compute_scale_factors (&font->base.scale,
+    status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale,
 						  &xscale, &yscale, 1);
     if (status)
 	return status;
 
     textMatrix = CGAffineTransformMake (font->base.scale.xx,
 					-font->base.scale.yx,
 					-font->base.scale.xy,
 					font->base.scale.yy,
--- a/gfx/cairo/cairo/src/cairo-reference-count-private.h
+++ b/gfx/cairo/cairo/src/cairo-reference-count-private.h
@@ -32,16 +32,20 @@
  *
  * Contributor(s):
  *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 #ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H
 #define CAIRO_REFRENCE_COUNT_PRIVATE_H
 
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "cairo-atomic-private.h"
 
 CAIRO_BEGIN_DECLS
 
 /* Encapsulate operations on the object's reference count */
 typedef struct {
     cairo_atomic_int_t ref_count;
 } cairo_reference_count_t;
--- a/gfx/cairo/cairo/src/cairo-region-private.h
+++ b/gfx/cairo/cairo/src/cairo-region-private.h
@@ -35,16 +35,17 @@
  */
 
 #ifndef CAIRO_REGION_PRIVATE_H
 #define CAIRO_REGION_PRIVATE_H
 
 #include <pixman.h>
 
 #include "cairo-compiler-private.h"
+#include "cairo-types-private.h"
 
 /* #cairo_region_t is defined in cairoint.h */
 
 struct _cairo_region {
     pixman_region32_t rgn;
 };
 
 cairo_private void
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -9,21 +9,16 @@
 #define cairo_clip_preserve _moz_cairo_clip_preserve
 #define cairo_close_path _moz_cairo_close_path
 #define cairo_copy_clip_rectangle_list _moz_cairo_copy_clip_rectangle_list
 #define cairo_copy_page _moz_cairo_copy_page
 #define cairo_copy_path _moz_cairo_copy_path
 #define cairo_copy_path_flat _moz_cairo_copy_path_flat
 #define cairo_create _moz_cairo_create
 #define cairo_curve_to _moz_cairo_curve_to
-#define cairo_debug_dump_clip _moz_cairo_debug_dump_clip
-#define cairo_debug_dump_path _moz_cairo_debug_dump_path
-#define cairo_debug_dump_trapezoid_array _moz_cairo_debug_dump_trapezoid_array
-#define cairo_debug_dump_traps _moz_cairo_debug_dump_traps
-#define cairo_debug_reset_static_data _moz_cairo_debug_reset_static_data
 #define cairo_debug_reset_static_data _moz_cairo_debug_reset_static_data
 #define cairo_destroy _moz_cairo_destroy
 #define cairo_device_to_user _moz_cairo_device_to_user
 #define cairo_device_to_user_distance _moz_cairo_device_to_user_distance
 #define cairo_directfb_surface_create _moz_cairo_directfb_surface_create
 #define cairo_fill _moz_cairo_fill
 #define cairo_fill_extents _moz_cairo_fill_extents
 #define cairo_fill_preserve _moz_cairo_fill_preserve
@@ -37,22 +32,24 @@
 #define cairo_font_face_status _moz_cairo_font_face_status
 #define cairo_font_options_copy _moz_cairo_font_options_copy
 #define cairo_font_options_create _moz_cairo_font_options_create
 #define cairo_font_options_destroy _moz_cairo_font_options_destroy
 #define cairo_font_options_equal _moz_cairo_font_options_equal
 #define cairo_font_options_get_antialias _moz_cairo_font_options_get_antialias
 #define cairo_font_options_get_hint_metrics _moz_cairo_font_options_get_hint_metrics
 #define cairo_font_options_get_hint_style _moz_cairo_font_options_get_hint_style
+#define cairo_font_options_get_lcd_filter _moz_cairo_font_options_get_lcd_filter
 #define cairo_font_options_get_subpixel_order _moz_cairo_font_options_get_subpixel_order
 #define cairo_font_options_hash _moz_cairo_font_options_hash
 #define cairo_font_options_merge _moz_cairo_font_options_merge
 #define cairo_font_options_set_antialias _moz_cairo_font_options_set_antialias
 #define cairo_font_options_set_hint_metrics _moz_cairo_font_options_set_hint_metrics
 #define cairo_font_options_set_hint_style _moz_cairo_font_options_set_hint_style
+#define cairo_font_options_set_lcd_filter _moz_cairo_font_options_set_lcd_filter
 #define cairo_font_options_set_subpixel_order _moz_cairo_font_options_set_subpixel_order
 #define cairo_font_options_status _moz_cairo_font_options_status
 #define cairo_format_stride_for_width _moz_cairo_format_stride_for_width
 #define cairo_ft_font_face_create_for_ft_face _moz_cairo_ft_font_face_create_for_ft_face
 #define cairo_ft_font_face_create_for_pattern _moz_cairo_ft_font_face_create_for_pattern
 #define cairo_ft_font_options_substitute _moz_cairo_ft_font_options_substitute
 #define cairo_ft_scaled_font_lock_face _moz_cairo_ft_scaled_font_lock_face
 #define cairo_ft_scaled_font_unlock_face _moz_cairo_ft_scaled_font_unlock_face
@@ -73,17 +70,19 @@
 #define cairo_get_operator _moz_cairo_get_operator
 #define cairo_get_reference_count _moz_cairo_get_reference_count
 #define cairo_get_scaled_font _moz_cairo_get_scaled_font
 #define cairo_get_source _moz_cairo_get_source
 #define cairo_get_target _moz_cairo_get_target
 #define cairo_get_tolerance _moz_cairo_get_tolerance
 #define cairo_get_user_data _moz_cairo_get_user_data
 #define cairo_glitz_surface_create _moz_cairo_glitz_surface_create
+#define cairo_glyph_allocate _moz_cairo_glyph_allocate
 #define cairo_glyph_extents _moz_cairo_glyph_extents
+#define cairo_glyph_free _moz_cairo_glyph_free
 #define cairo_glyph_path _moz_cairo_glyph_path
 #define cairo_has_current_point _moz_cairo_has_current_point
 #define cairo_has_show_text_glyphs _moz_cairo_has_show_text_glyphs
 #define cairo_identity_matrix _moz_cairo_identity_matrix
 #define cairo_image_surface_create _moz_cairo_image_surface_create
 #define cairo_image_surface_create_for_data _moz_cairo_image_surface_create_for_data
 #define cairo_image_surface_create_from_png _moz_cairo_image_surface_create_from_png
 #define cairo_image_surface_create_from_png_stream _moz_cairo_image_surface_create_from_png_stream
@@ -163,16 +162,22 @@
 #define cairo_ps_surface_dsc_begin_setup _moz_cairo_ps_surface_dsc_begin_setup
 #define cairo_ps_surface_dsc_comment _moz_cairo_ps_surface_dsc_comment
 #define cairo_ps_surface_get_eps _moz_cairo_ps_surface_get_eps
 #define cairo_ps_surface_restrict_to_level _moz_cairo_ps_surface_restrict_to_level
 #define cairo_ps_surface_set_eps _moz_cairo_ps_surface_set_eps
 #define cairo_ps_surface_set_size _moz_cairo_ps_surface_set_size
 #define cairo_push_group _moz_cairo_push_group
 #define cairo_push_group_with_content _moz_cairo_push_group_with_content
+#define cairo_qpainter_surface_create _moz_cairo_qpainter_surface_create
+#define cairo_qpainter_surface_create_with_qimage _moz_cairo_qpainter_surface_create_with_qimage
+#define cairo_qpainter_surface_create_with_qpixmap _moz_cairo_qpainter_surface_create_with_qpixmap
+#define cairo_qpainter_surface_get_image _moz_cairo_qpainter_surface_get_image
+#define cairo_qpainter_surface_get_qimage _moz_cairo_qpainter_surface_get_qimage
+#define cairo_qpainter_surface_get_qpainter _moz_cairo_qpainter_surface_get_qpainter
 #define cairo_quartz_font_face_create_for_atsu_font_id _moz_cairo_quartz_font_face_create_for_atsu_font_id
 #define cairo_quartz_font_face_create_for_cgfont _moz_cairo_quartz_font_face_create_for_cgfont
 #define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create
 #define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image
 #define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
 #define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
 #define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
 #define cairo_rectangle _moz_cairo_rectangle
@@ -197,16 +202,17 @@
 #define cairo_scaled_font_get_scale_matrix _moz_cairo_scaled_font_get_scale_matrix
 #define cairo_scaled_font_get_type _moz_cairo_scaled_font_get_type
 #define cairo_scaled_font_get_user_data _moz_cairo_scaled_font_get_user_data
 #define cairo_scaled_font_glyph_extents _moz_cairo_scaled_font_glyph_extents
 #define cairo_scaled_font_reference _moz_cairo_scaled_font_reference
 #define cairo_scaled_font_set_user_data _moz_cairo_scaled_font_set_user_data
 #define cairo_scaled_font_status _moz_cairo_scaled_font_status
 #define cairo_scaled_font_text_extents _moz_cairo_scaled_font_text_extents
+#define cairo_scaled_font_text_to_glyphs _moz_cairo_scaled_font_text_to_glyphs
 #define cairo_select_font_face _moz_cairo_select_font_face
 #define cairo_set_antialias _moz_cairo_set_antialias
 #define cairo_set_dash _moz_cairo_set_dash
 #define cairo_set_fill_rule _moz_cairo_set_fill_rule
 #define cairo_set_font_face _moz_cairo_set_font_face
 #define cairo_set_font_matrix _moz_cairo_set_font_matrix
 #define cairo_set_font_options _moz_cairo_set_font_options
 #define cairo_set_font_size _moz_cairo_set_font_size
@@ -240,33 +246,40 @@
 #define cairo_surface_flush _moz_cairo_surface_flush
 #define cairo_surface_get_content _moz_cairo_surface_get_content
 #define cairo_surface_get_device_offset _moz_cairo_surface_get_device_offset
 #define cairo_surface_get_fallback_resolution _moz_cairo_surface_get_fallback_resolution
 #define cairo_surface_get_font_options _moz_cairo_surface_get_font_options
 #define cairo_surface_get_reference_count _moz_cairo_surface_get_reference_count
 #define cairo_surface_get_type _moz_cairo_surface_get_type
 #define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
+#define cairo_surface_has_show_text_glyphs _moz_cairo_surface_has_show_text_glyphs
 #define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
 #define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle
 #define cairo_surface_reference _moz_cairo_surface_reference
 #define cairo_surface_set_device_offset _moz_cairo_surface_set_device_offset
 #define cairo_surface_set_fallback_resolution _moz_cairo_surface_set_fallback_resolution
 #define cairo_surface_set_user_data _moz_cairo_surface_set_user_data
 #define cairo_surface_show_page _moz_cairo_surface_show_page
 #define cairo_surface_status _moz_cairo_surface_status
 #define cairo_surface_write_to_png _moz_cairo_surface_write_to_png
 #define cairo_surface_write_to_png_stream _moz_cairo_surface_write_to_png_stream
 #define cairo_svg_get_versions _moz_cairo_svg_get_versions
 #define cairo_svg_surface_create _moz_cairo_svg_surface_create
 #define cairo_svg_surface_create_for_stream _moz_cairo_svg_surface_create_for_stream
 #define cairo_svg_surface_restrict_to_version _moz_cairo_svg_surface_restrict_to_version
 #define cairo_svg_version_to_string _moz_cairo_svg_version_to_string
+#define cairo_text_cluster_allocate _moz_cairo_text_cluster_allocate
+#define cairo_text_cluster_free _moz_cairo_text_cluster_free
 #define cairo_text_extents _moz_cairo_text_extents
 #define cairo_text_path _moz_cairo_text_path
+#define cairo_toy_font_face_create _moz_cairo_toy_font_face_create
+#define cairo_toy_font_face_get_family _moz_cairo_toy_font_face_get_family
+#define cairo_toy_font_face_get_slant _moz_cairo_toy_font_face_get_slant
+#define cairo_toy_font_face_get_weight _moz_cairo_toy_font_face_get_weight
 #define cairo_transform _moz_cairo_transform
 #define cairo_translate _moz_cairo_translate
 #define cairo_user_font_face_create _moz_cairo_user_font_face_create
 #define cairo_user_font_face_get_init_func _moz_cairo_user_font_face_get_init_func
 #define cairo_user_font_face_get_render_glyph_func _moz_cairo_user_font_face_get_render_glyph_func
 #define cairo_user_font_face_get_text_to_glyphs_func _moz_cairo_user_font_face_get_text_to_glyphs_func
 #define cairo_user_font_face_get_unicode_to_glyph_func _moz_cairo_user_font_face_get_unicode_to_glyph_func
 #define cairo_user_font_face_set_init_func _moz_cairo_user_font_face_set_init_func
@@ -369,24 +382,24 @@
 #define pixman_image_set_clip_region32 _moz_pixman_image_set_clip_region32
 #define pixman_image_set_has_client_clip _moz_pixman_image_set_has_client_clip
 #define pixman_image_set_transform _moz_pixman_image_set_transform
 #define pixman_image_set_repeat _moz_pixman_image_set_repeat
 #define pixman_image_set_filter _moz_pixman_image_set_filter
 #define pixman_image_set_source_clipping _moz_pixman_image_set_source_clipping
 #define pixman_image_set_alpha_map _moz_pixman_image_set_alpha_map
 #define pixman_image_set_component_alpha _moz_pixman_image_set_component_alpha
-#define pixman_image_set_accessors _moz_pixman_image_set_accessors
-#define pixman_image_set_indexed _moz_pixman_image_set_indexed
+#define pixman_image_set_accessors	 _moz_pixman_image_set_accessors	
+#define pixman_image_set_indexed	 _moz_pixman_image_set_indexed	
 #define pixman_image_get_data _moz_pixman_image_get_data
 #define pixman_image_get_width _moz_pixman_image_get_width
 #define pixman_image_get_height _moz_pixman_image_get_height
 #define pixman_image_get_stride _moz_pixman_image_get_stride
 #define pixman_image_get_depth _moz_pixman_image_get_depth
-#define pixman_image_fill_rectangles _moz_pixman_image_fill_rectangles
+#define pixman_image_fill_rectangles	 _moz_pixman_image_fill_rectangles	
 #define pixman_compute_composite_region _moz_pixman_compute_composite_region
 #define pixman_image_composite _moz_pixman_image_composite
 #define pixman_sample_ceil_y _moz_pixman_sample_ceil_y
 #define pixman_sample_floor_y _moz_pixman_sample_floor_y
 #define pixman_edge_step _moz_pixman_edge_step
 #define pixman_edge_init _moz_pixman_edge_init
 #define pixman_line_fixed_edge_init _moz_pixman_line_fixed_edge_init
 #define pixman_rasterize_edges _moz_pixman_rasterize_edges
--- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
+++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
@@ -34,16 +34,18 @@
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
 #define CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
 
 #include "cairoint.h"
 
+#if CAIRO_HAS_FONT_SUBSET
+
 typedef struct _cairo_scaled_font_subsets_glyph {
     unsigned int font_id;
     unsigned int subset_id;
     unsigned int subset_glyph_index;
     cairo_bool_t is_scaled;
     cairo_bool_t is_composite;
     double       x_advance;
     double       y_advance;
@@ -122,22 +124,20 @@ cairo_private cairo_scaled_font_subsets_
 cairo_private void
 _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
 
 /**
  * _cairo_scaled_font_subsets_map_glyph:
  * @font_subsets: a #cairo_scaled_font_subsets_t
  * @scaled_font: the font of the glyph to be mapped
  * @scaled_font_glyph_index: the index of the glyph to be mapped
+ * @utf8: a string of text encoded in UTF-8
+ * @utf8_len: length of @utf8 in bytes
  * @subset_glyph_ret: return structure containing subset font and glyph id
  *
- * @font_id_ret: return value giving the font ID of the mapped glyph
- * @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
- * @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
- *
  * Map a glyph from a #cairo_scaled_font to a new index within a
  * subset of that font. The mapping performed is from the tuple:
  *
  *	(scaled_font, scaled_font_glyph_index)
  *
  * to the tuple:
  *
  *	(font_id, subset_id, subset_glyph_index)
@@ -165,16 +165,24 @@ cairo_private void
  * by one or more font subsets. Each subset is effectively a tuple of
  * (scaled_font, font_id, subset_id) and within each subset there
  * exists a mapping of scaled_glyph_font_index to subset_glyph_index.
  *
  * This final description of a font subset is the same representation
  * used by #cairo_scaled_font_subset_t as provided by
  * _cairo_scaled_font_subsets_foreach.
  *
+ * @utf8 and @utf8_len specify a string of unicode characters that the
+ * glyph @scaled_font_glyph_index maps to. If @utf8_is_mapped in
+ * @subset_glyph_ret is %TRUE, the font subsetting will (where index to
+ * unicode mapping is supported) ensure that @scaled_font_glyph_index
+ * maps to @utf8. If @utf8_is_mapped is %FALSE,
+ * @scaled_font_glyph_index has already been mapped to a different
+ * unicode string.
+ *
  * The returned values in the #cairo_scaled_font_subsets_glyph_t struct are:
  *
  * @font_id: The font ID of the mapped glyph
  * @subset_id : The subset ID of the mapped glyph within the @font_id
  * @subset_glyph_index: The index of the mapped glyph within the @subset_id subset
  * @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
  * subset is created for each font scale used. If false, the outline of the mapped glyph
  * is available. One font subset for each font face is created.
@@ -360,17 +368,17 @@ cairo_private cairo_status_t
 cairo_private void
 _cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
 
 typedef struct _cairo_truetype_subset {
     char *base_font;
     double *widths;
     double x_min, y_min, x_max, y_max;
     double ascent, descent;
-    char *data;
+    unsigned char *data;
     unsigned long data_length;
     unsigned long *string_offsets;
     unsigned long num_string_offsets;
 } cairo_truetype_subset_t;
 
 /**
  * _cairo_truetype_subset_init:
  * @truetype_subset: a #cairo_truetype_subset_t to initialize
@@ -410,16 +418,19 @@ typedef struct _cairo_type1_subset {
     long x_min, y_min, x_max, y_max;
     long ascent, descent;
     char *data;
     unsigned long header_length;
     unsigned long data_length;
     unsigned long trailer_length;
 } cairo_type1_subset_t;
 
+
+#if CAIRO_HAS_FT_FONT
+
 /**
  * _cairo_type1_subset_init:
  * @type1_subset: a #cairo_type1_subset_t to initialize
  * @font_subset: the #cairo_scaled_font_subset_t to initialize from
  * @hex_encode: if true the encrypted portion of the font is hex encoded
  *
  * If possible (depending on the format of the underlying
  * #cairo_scaled_font_t and the font backend in use) generate a type1
@@ -443,16 +454,19 @@ cairo_private cairo_status_t
  *
  * Free all resources associated with @type1_subset.  After this call,
  * @type1_subset should not be used again without a subsequent call to
  * _cairo_truetype_type1_init() again first.
  **/
 cairo_private void
 _cairo_type1_subset_fini (cairo_type1_subset_t *subset);
 
+#endif /* CAIRO_HAS_FT_FONT */
+
+
 /**
  * _cairo_type1_scaled_font_is_type1:
  * @scaled_font: a #cairo_scaled_font_t
  *
  * Return %TRUE if @scaled_font is a Type 1 font, otherwise return %FALSE.
  **/
 cairo_private cairo_bool_t
 _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t	*scaled_font);
@@ -581,9 +595,11 @@ cairo_private cairo_int_status_t
  * %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode
  * is not supported.  Possible errors include %CAIRO_STATUS_NO_MEMORY.
  **/
 cairo_private cairo_int_status_t
 _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
                                unsigned long        index,
                                uint32_t            *ucs4);
 
+#endif /* CAIRO_HAS_FONT_SUBSET */
+
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
+++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
@@ -37,16 +37,19 @@
  *	Carl D. Worth <cworth@cworth.org>
  *	Kristian Høgsberg <krh@redhat.com>
  *	Keith Packard <keithp@keithp.com>
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-user-font-private.h"
 
 #define MAX_GLYPHS_PER_SIMPLE_FONT 256
 #define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
 
 typedef enum {
     CAIRO_SUBSETS_SCALED,
@@ -275,17 +278,17 @@ static cairo_status_t
     sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal);
     if (sub_font->sub_font_glyphs == NULL) {
 	free (sub_font);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
     sub_font->next = NULL;
 
     /* Reserve first glyph in subset for the .notdef glyph */
-    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &subset_glyph);
+    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
     if (status) {
 	_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
 	free (sub_font);
 	return status;
     }
 
     *sub_font_out = sub_font;
     return CAIRO_STATUS_SUCCESS;
@@ -319,83 +322,92 @@ static cairo_status_t
 {
     uint32_t unicode;
     char buf[8];
     int len;
     cairo_status_t status;
 
     /* Do a reverse lookup on the glyph index. unicode is -1 if the
      * index could not be mapped to a unicode character. */
-    status = _cairo_truetype_index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+    unicode = -1;
+    status = _cairo_truetype_index_to_ucs4 (scaled_font,
+					    scaled_font_glyph_index,
+					    &unicode);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	unicode = -1;
-
-    if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4)
-	status = scaled_font->backend->index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+    if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4) {
+	status = scaled_font->backend->index_to_ucs4 (scaled_font,
+						      scaled_font_glyph_index,
+						      &unicode);
+	if (status)
+	    return status;
+    }
 
     sub_font_glyph->unicode = unicode;
     sub_font_glyph->utf8 = NULL;
     sub_font_glyph->utf8_len = 0;
-    if (unicode != (uint32_t)-1) {
+    if (unicode != (uint32_t) -1) {
 	len = _cairo_ucs4_to_utf8 (unicode, buf);
 	if (len > 0) {
-	    sub_font_glyph->utf8 = malloc(len + 1);
+	    sub_font_glyph->utf8 = malloc (len + 1);
+	    if (sub_font_glyph->utf8 == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
 	    memcpy (sub_font_glyph->utf8, buf, len);
 	    sub_font_glyph->utf8[len] = 0;
 	    sub_font_glyph->utf8_len = len;
 	}
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
 _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
-				      const char 	     *utf8,
-				      int 		      utf8_len)
+				      const char	     *utf8,
+				      int		      utf8_len)
 {
-    int add_zero_byte = 0;
+    if (utf8_len < 0)
+	return FALSE;
+
+    if (utf8 != NULL && utf8_len != 0 && utf8[utf8_len - 1] == '\0')
+	utf8_len--;
 
     if (utf8 != NULL && utf8_len != 0) {
 	if (sub_font_glyph->utf8 != NULL) {
 	    if (utf8_len == sub_font_glyph->utf8_len &&
 		memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
 	    {
 		/* Requested utf8 mapping matches the existing mapping */
 		return TRUE;
 	    }
 	    else
 	    {
 		/* Requested utf8 mapping does not match the existing mapping */
 		return FALSE;
 	    }
 	} else {
 	    /* No existing mapping. Use the requested mapping */
-	    if (sub_font_glyph->utf8[utf8_len - 1] != 0)
-		add_zero_byte = 1;
-	    sub_font_glyph->utf8 = malloc (utf8_len + add_zero_byte);
+	    sub_font_glyph->utf8 = malloc (utf8_len + 1);
 	    memcpy (sub_font_glyph->utf8, utf8, utf8_len);
-	    if (add_zero_byte)
-		sub_font_glyph->utf8[utf8_len] = 0;
+	    sub_font_glyph->utf8[utf8_len] = 0;
 	    sub_font_glyph->utf8_len = utf8_len;
 	    return TRUE;
 	}
     }
 
     /* No mapping was requested. */
     return FALSE;
 }
 
 static cairo_bool_t
 _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
                               unsigned long	                 scaled_font_glyph_index,
-			      const char * 			 utf8,
+			      const char			*utf8,
 			      int				 utf8_len,
                               cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
 
     _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
     if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
 				    (cairo_hash_entry_t **) &sub_font_glyph))
@@ -414,36 +426,37 @@ static cairo_bool_t
     }
 
     return FALSE;
 }
 
 static cairo_status_t
 _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 			   unsigned long	 scaled_font_glyph_index,
-			   const char * 	 utf8,
+			   const char		*utf8,
 			   int			 utf8_len,
                            cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
     cairo_status_t status;
     cairo_scaled_glyph_t *scaled_glyph;
-    cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
 
     _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
     if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
 				    (cairo_hash_entry_t **) &sub_font_glyph))
     {
 	if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
 	{
+	    cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
+
 	    sub_font->current_subset++;
 	    sub_font->num_glyphs_in_current_subset = 0;
 
 	    /* Reserve first glyph in subset for the .notdef glyph */
-	    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &tmp_subset_glyph);
+	    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
 	    if (status)
 		return status;
 	}
 
         status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
                                              scaled_font_glyph_index,
                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
                                              &scaled_glyph);
@@ -454,48 +467,50 @@ static cairo_status_t
         sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
 						       sub_font->current_subset,
 						       sub_font->num_glyphs_in_current_subset,
                                                        scaled_glyph->metrics.x_advance,
                                                        scaled_glyph->metrics.y_advance);
 	if (sub_font_glyph == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	_cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
-					      sub_font->scaled_font,
-					      scaled_font_glyph_index);
+	status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
+						       sub_font->scaled_font,
+						       scaled_font_glyph_index);
+	if (status) {
+	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
+	    return status;
+	}
 
 	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
 	if (status) {
 	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
 	    return status;
 	}
 
 	sub_font->num_glyphs_in_current_subset++;
 
-        if (sub_font->is_scaled)
-        {
+        if (sub_font->is_scaled) {
             if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used)
                 sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset;
-        }
-        else
-        {
+        } else {
             if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used)
                 sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset;
         }
     }
 
     subset_glyph->font_id = sub_font->font_id;
     subset_glyph->subset_id = sub_font_glyph->subset_id;
     subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
     subset_glyph->is_scaled = sub_font->is_scaled;
     subset_glyph->is_composite = sub_font->is_composite;
     subset_glyph->x_advance = sub_font_glyph->x_advance;
     subset_glyph->y_advance = sub_font_glyph->y_advance;
-    subset_glyph->utf8_is_mapped = FALSE;
+    subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+    subset_glyph->unicode = sub_font_glyph->unicode;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_sub_font_collect (void *entry, void *closure)
 {
     cairo_sub_font_t *sub_font = entry;
@@ -939,18 +954,18 @@ cairo_int_status_t
     }
 
     for (i = 1; i < subset->num_glyphs; i++) {
 	utf8 = subset->utf8[i];
 	utf16 = NULL;
 	utf16_len = 0;
 	if (utf8 && *utf8) {
 	    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
-	    if (status && status != CAIRO_STATUS_INVALID_STRING)
-		return status; // FIXME
+	    if (status)
+		return status; /* FIXME */
 	}
 
 	if (utf16_len == 1) {
 	    snprintf (buf, sizeof(buf), "uni%04X", (int)(utf16[0]));
 	    _cairo_string_init_key (&key, buf);
 	    if (_cairo_hash_table_lookup (names, &key.base,
 					  (cairo_hash_entry_t **) &entry)) {
 		snprintf (buf, sizeof(buf), "g%d", i);
@@ -999,8 +1014,10 @@ CLEANUP_HASH:
 	}
 
 	free (subset->glyph_names);
 	subset->glyph_names = NULL;
     }
 
     return status;
 }
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-scaled-font.c
+++ b/gfx/cairo/cairo/src/cairo-scaled-font.c
@@ -294,16 +294,17 @@ slim_hidden_def (cairo_scaled_font_statu
  */
 
 /* This defines the size of the holdover array ... that is, the number
  * of scaled fonts we keep around even when not otherwise referenced
  */
 #define CAIRO_SCALED_FONT_MAX_HOLDOVERS 256
 
 typedef struct _cairo_scaled_font_map {
+    cairo_scaled_font_t *mru_scaled_font;
     cairo_hash_table_t *hash_table;
     cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS];
     int num_holdovers;
 } cairo_scaled_font_map_t;
 
 static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
 
 static int
@@ -314,16 +315,17 @@ static cairo_scaled_font_map_t *
 {
     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
 
     if (cairo_scaled_font_map == NULL) {
 	cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t));
 	if (cairo_scaled_font_map == NULL)
 	    goto CLEANUP_MUTEX_LOCK;
 
+	cairo_scaled_font_map->mru_scaled_font = NULL;
 	cairo_scaled_font_map->hash_table =
 	    _cairo_hash_table_create (_cairo_scaled_font_keys_equal);
 
 	if (cairo_scaled_font_map->hash_table == NULL)
 	    goto CLEANUP_SCALED_FONT_MAP;
 
 	cairo_scaled_font_map->num_holdovers = 0;
     }
@@ -353,21 +355,27 @@ void
 
     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
 
     font_map = cairo_scaled_font_map;
     if (font_map == NULL) {
         goto CLEANUP_MUTEX_LOCK;
     }
 
+    scaled_font = font_map->mru_scaled_font;
+    if (scaled_font != NULL) {
+	CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
+	cairo_scaled_font_destroy (scaled_font);
+	CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
+    }
+
     /* remove scaled_fonts starting from the end so that font_map->holdovers
      * is always in a consistent state when we release the mutex. */
     while (font_map->num_holdovers) {
 	scaled_font = font_map->holdovers[font_map->num_holdovers-1];
-
 	assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
 	_cairo_hash_table_remove (font_map->hash_table,
 				  &scaled_font->hash_entry);
 
 	font_map->num_holdovers--;
 
 	/* release the lock to avoid the possibility of a recursive
 	 * deadlock when the scaled font destroy closure gets called */
@@ -668,17 +676,17 @@ void
 
 cairo_status_t
 _cairo_scaled_font_set_metrics (cairo_scaled_font_t	    *scaled_font,
 				cairo_font_extents_t	    *fs_metrics)
 {
     cairo_status_t status;
     double  font_scale_x, font_scale_y;
 
-    status = _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
+    status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->font_matrix,
 						  &font_scale_x, &font_scale_y,
 						  1);
     if (status)
 	return status;
 
     /*
      * The font responded in unscaled units, scale by the font
      * matrix scale factors to get to user space
@@ -740,17 +748,17 @@ void
 cairo_scaled_font_t *
 cairo_scaled_font_create (cairo_font_face_t          *font_face,
 			  const cairo_matrix_t       *font_matrix,
 			  const cairo_matrix_t       *ctm,
 			  const cairo_font_options_t *options)
 {
     cairo_status_t status;
     cairo_scaled_font_map_t *font_map;
-    cairo_scaled_font_t key, *scaled_font = NULL;
+    cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
 
     if (font_face->status)
 	return _cairo_scaled_font_create_in_error (font_face->status);
 
     status = cairo_font_options_status ((cairo_font_options_t *) options);
     if (status)
 	return _cairo_scaled_font_create_in_error (status);
 
@@ -758,90 +766,128 @@ cairo_scaled_font_create (cairo_font_fac
      * We want to support a font size of 0. */
 
     font_map = _cairo_scaled_font_map_lock ();
     if (font_map == NULL)
 	return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_scaled_font_init_key (&key, font_face,
 				 font_matrix, ctm, options);
-
-
-    while (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
-				     (cairo_hash_entry_t**) &scaled_font))
-    {
-	if (!scaled_font->placeholder)
-	    break;
-
-	/* If the scaled font is being created (happens for user-font),
-	 * just wait until it's done, then retry */
-	_cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
-    }
-
-    /* Return existing scaled_font if it exists in the hash table. */
-    if (scaled_font)
+    scaled_font = font_map->mru_scaled_font;
+    if (scaled_font != NULL &&
+	scaled_font->hash_entry.hash == key.hash_entry.hash &&
+	_cairo_scaled_font_keys_equal (scaled_font, &key))
     {
-	/* If the original reference count is 0, then this font must have
-	 * been found in font_map->holdovers, (which means this caching is
-	 * actually working). So now we remove it from the holdovers
-	 * array. */
-	if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
-	    int i;
-
-	    for (i = 0; i < font_map->num_holdovers; i++)
-		if (font_map->holdovers[i] == scaled_font)
-		    break;
-	    assert (i < font_map->num_holdovers);
-
-	    font_map->num_holdovers--;
-	    memmove (&font_map->holdovers[i],
-		     &font_map->holdovers[i+1],
-		     (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
-
-	    /* reset any error status */
-	    scaled_font->status = CAIRO_STATUS_SUCCESS;
-	}
+	assert (! scaled_font->placeholder);
 
 	if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
 	    /* We increment the reference count manually here, (rather
 	     * than calling into cairo_scaled_font_reference), since we
 	     * must modify the reference count while our lock is still
 	     * held. */
 	    _cairo_reference_count_inc (&scaled_font->ref_count);
 	    _cairo_scaled_font_map_unlock ();
 	    return scaled_font;
 	}
 
 	/* the font has been put into an error status - abandon the cache */
 	_cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
 	scaled_font->hash_entry.hash = ZOMBIE;
     }
+    else
+    {
+	while (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
+					 (cairo_hash_entry_t**) &scaled_font))
+	{
+	    if (! scaled_font->placeholder)
+		break;
+
+	    /* If the scaled font is being created (happens for user-font),
+	     * just wait until it's done, then retry */
+	    _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
+	}
+
+	/* Return existing scaled_font if it exists in the hash table. */
+	if (scaled_font != NULL) {
+	    /* If the original reference count is 0, then this font must have
+	     * been found in font_map->holdovers, (which means this caching is
+	     * actually working). So now we remove it from the holdovers
+	     * array. */
+	    if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
+		int i;
+
+		for (i = 0; i < font_map->num_holdovers; i++)
+		    if (font_map->holdovers[i] == scaled_font)
+			break;
+		assert (i < font_map->num_holdovers);
+
+		font_map->num_holdovers--;
+		memmove (&font_map->holdovers[i],
+			 &font_map->holdovers[i+1],
+			 (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
+
+		/* reset any error status */
+		scaled_font->status = CAIRO_STATUS_SUCCESS;
+	    }
+
+	    if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
+		/* We increment the reference count manually here, (rather
+		 * than calling into cairo_scaled_font_reference), since we
+		 * must modify the reference count while our lock is still
+		 * held. */
+
+		old = font_map->mru_scaled_font;
+		font_map->mru_scaled_font = scaled_font;
+		/* increment reference count for the mru cache */
+		_cairo_reference_count_inc (&scaled_font->ref_count);
+		/* and increment for the returned reference */
+		_cairo_reference_count_inc (&scaled_font->ref_count);
+		_cairo_scaled_font_map_unlock ();
+
+		cairo_scaled_font_destroy (old);
+
+		return scaled_font;
+	    }
+
+	    /* the font has been put into an error status - abandon the cache */
+	    _cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
+	    scaled_font->hash_entry.hash = ZOMBIE;
+	}
+    }
 
     /* Otherwise create it and insert it into the hash table. */
     status = font_face->backend->scaled_font_create (font_face, font_matrix,
 						     ctm, options, &scaled_font);
     if (status) {
 	_cairo_scaled_font_map_unlock ();
 	status = _cairo_font_face_set_error (font_face, status);
 	return _cairo_scaled_font_create_in_error (status);
     }
 
     status = _cairo_hash_table_insert (font_map->hash_table,
 				       &scaled_font->hash_entry);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	old = font_map->mru_scaled_font;
+	font_map->mru_scaled_font = scaled_font;
+	_cairo_reference_count_inc (&scaled_font->ref_count);
+    }
+
     _cairo_scaled_font_map_unlock ();
 
     if (status) {
 	/* We can't call _cairo_scaled_font_destroy here since it expects
 	 * that the font has already been successfully inserted into the
 	 * hash table. */
 	_cairo_scaled_font_fini (scaled_font);
 	free (scaled_font);
 	return _cairo_scaled_font_create_in_error (status);
     }
 
+    cairo_scaled_font_destroy (old);
+
     return scaled_font;
 }
 slim_hidden_def (cairo_scaled_font_create);
 
 static cairo_scaled_font_t *_cairo_scaled_font_nil_objects[CAIRO_STATUS_LAST_STATUS + 1];
 
 /* XXX This should disappear in favour of a common pool of error objects. */
 cairo_scaled_font_t *
@@ -1078,17 +1124,17 @@ cairo_scaled_font_extents (cairo_scaled_
 {
     *extents = scaled_font->extents;
 }
 slim_hidden_def (cairo_scaled_font_extents);
 
 /**
  * cairo_scaled_font_text_extents:
  * @scaled_font: a #cairo_scaled_font_t
- * @utf8: a string of text, encoded in UTF-8
+ * @utf8: a NUL-terminated string of text, encoded in UTF-8
  * @extents: a #cairo_text_extents_t which to store the retrieved extents.
  *
  * Gets the extents for a string of text. The extents describe a
  * user-space rectangle that encloses the "inked" portion of the text
  * drawn at the origin (0,0) (as it would be drawn by cairo_show_text()
  * if the cairo graphics state were set to the same font_face,
  * font_matrix, ctm, and font_options as @scaled_font).  Additionally,
  * the x_advance and y_advance values indicate the amount by which the
@@ -1104,26 +1150,30 @@ slim_hidden_def (cairo_scaled_font_exten
  * Since: 1.2
  **/
 void
 cairo_scaled_font_text_extents (cairo_scaled_font_t   *scaled_font,
 				const char            *utf8,
 				cairo_text_extents_t  *extents)
 {
     cairo_status_t status;
-    cairo_glyph_t *glyphs;
+    cairo_glyph_t *glyphs = NULL;
     int num_glyphs;
 
     if (scaled_font->status)
 	goto ZERO_EXTENTS;
 
     if (utf8 == NULL)
 	goto ZERO_EXTENTS;
 
-    status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs);
+    status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
+					       utf8, -1,
+					       &glyphs, &num_glyphs,
+					       NULL, NULL,
+					       NULL);
     if (status)
 	goto ZERO_EXTENTS;
 
     cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
     free (glyphs);
 
     return;
 
@@ -1161,25 +1211,25 @@ cairo_scaled_font_glyph_extents (cairo_s
 				 cairo_text_extents_t  *extents)
 {
     cairo_status_t status;
     int i;
     double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
     cairo_bool_t visible = FALSE;
     cairo_scaled_glyph_t *scaled_glyph = NULL;
 
-    if (scaled_font->status) {
-	extents->x_bearing = 0.0;
-	extents->y_bearing = 0.0;
-	extents->width  = 0.0;
-	extents->height = 0.0;
-	extents->x_advance = 0.0;
-	extents->y_advance = 0.0;
+    extents->x_bearing = 0.0;
+    extents->y_bearing = 0.0;
+    extents->width  = 0.0;
+    extents->height = 0.0;
+    extents->x_advance = 0.0;
+    extents->y_advance = 0.0;
+
+    if (scaled_font->status)
 	return;
-    }
 
     if (num_glyphs == 0)
 	return;
 
     if (num_glyphs < 0) {
 	_cairo_error_throw (CAIRO_STATUS_NEGATIVE_COUNT);
 	/* XXX Can't propagate error */
 	return;
@@ -1259,97 +1309,376 @@ cairo_scaled_font_glyph_extents (cairo_s
     }
 
  UNLOCK:
     _cairo_scaled_font_thaw_cache (scaled_font);
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 }
 slim_hidden_def (cairo_scaled_font_glyph_extents);
 
+/**
+ * cairo_scaled_font_text_to_glyphs:
+ * @x: X position to place first glyph
+ * @y: Y position to place first glyph
+ * @scaled_font: a #cairo_scaled_font_t
+ * @utf8: a string of text encoded in UTF-8
+ * @utf8_len: length of @utf8 in bytes, or -1 if it is NUL-terminated
+ * @glyphs: pointer to array of glyphs to fill
+ * @num_glyphs: pointer to number of glyphs
+ * @clusters: pointer to array of cluster mapping information to fill, or %NULL
+ * @num_clusters: pointer to number of clusters, or %NULL
+ * @backward: pointer to whether the text to glyphs mapping goes backward, or
+ *            %NULL
+ *
+ * Converts UTF-8 text to an array of glyphs, optionally with cluster
+ * mapping, that can be used to render later using @scaled_font.
+ *
+ * If @glyphs initially points to a non-%NULL value, that array is used
+ * as a glyph buffer, and @num_glyphs should point to the number of glyph
+ * entries available there.  If the provided glyph array is too short for
+ * the conversion, a new glyph array is allocated using cairo_glyph_allocate()
+ * and placed in @glyphs.  Upon return, @num_glyphs always contains the
+ * number of generated glyphs.  If the value @glyphs points at has changed
+ * after the call, the user is responsible for freeing the allocated glyph
+ * array using cairo_glyph_free().
+ *
+ * If @clusters is not %NULL, @num_clusters and @backward should not be %NULL,
+ * and cluster mapping will be computed.
+ * The semantics of how cluster array allocation works is similar to the glyph
+ * array.  That is,
+ * if @clusters initially points to a non-%NULL value, that array is used
+ * as a cluster buffer, and @num_clusters should point to the number of cluster
+ * entries available there.  If the provided cluster array is too short for
+ * the conversion, a new cluster array is allocated using cairo_text_cluster_allocate()
+ * and placed in @clusters.  Upon return, @num_clusters always contains the
+ * number of generated clusters.  If the value @clusters points at has changed
+ * after the call, the user is responsible for freeing the allocated cluster
+ * array using cairo_text_cluster_free().
+ *
+ * In the simplest case, @glyphs and @clusters can point to %NULL initially
+ * and a suitable array will be allocated.  In code:
+ * <informalexample><programlisting>
+ * cairo_status_t status;
+ *
+ * cairo_glyph_t *glyphs = NULL;
+ * int num_glyphs;
+ * cairo_text_cluster_t *clusters = NULL;
+ * int num_clusters;
+ * cairo_bool_t backward;
+ *
+ * status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ *                                            x, y,
+ *                                            utf8, utf8_len,
+ *                                            &amp;glyphs, &amp;num_glyphs,
+ *                                            &amp;clusters, &amp;num_clusters,
+ *                                            &amp;backward);
+ *
+ * if (status == CAIRO_STATUS_SUCCESS) {
+ *     cairo_show_text_glyphs (cr,
+ *                             utf8, utf8_len,
+ *                             *glyphs, *num_glyphs,
+ *                             *clusters, *num_clusters,
+ *                             *backward);
+ *
+ *     cairo_glyph_free (*glyphs);
+ *     cairo_text_cluster_free (*clusters);
+ * }
+ * </programlisting></informalexample>
+ *
+ * If no cluster mapping is needed:
+ * <informalexample><programlisting>
+ * cairo_status_t status;
+ *
+ * cairo_glyph_t *glyphs = NULL;
+ * int num_glyphs;
+ *
+ * status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ *                                            x, y,
+ *                                            utf8, utf8_len,
+ *                                            &amp;glyphs, &amp;num_glyphs,
+ *                                            NULL, NULL,
+ *                                            NULL);
+ *
+ * if (status == CAIRO_STATUS_SUCCESS) {
+ *     cairo_show_glyphs (cr, *glyphs, *num_glyphs);
+ *     cairo_glyph_free (*glyphs);
+ * }
+ * </programlisting></informalexample>
+ *
+ * If stack-based glyph and cluster arrays are to be used for small
+ * arrays:
+ * <informalexample><programlisting>
+ * cairo_status_t status;
+ *
+ * cairo_glyph_t stack_glyphs[40];
+ * cairo_glyph_t *glyphs = stack_glyphs;
+ * int num_glyphs = sizeof (stack_glyphs) / sizeof (stack_glyphs[0]);
+ * cairo_text_cluster_t stack_clusters[40];
+ * cairo_text_cluster_t *clusters = stack_clusters;
+ * int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]);
+ * cairo_bool_t backward;
+ *
+ * status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ *                                            x, y,
+ *                                            utf8, utf8_len,
+ *                                            &amp;glyphs, &amp;num_glyphs,
+ *                                            &amp;clusters, &amp;num_clusters,
+ *                                            &amp;backward);
+ *
+ * if (status == CAIRO_STATUS_SUCCESS) {
+ *     cairo_show_text_glyphs (cr,
+ *                             utf8, utf8_len,
+ *                             *glyphs, *num_glyphs,
+ *                             *clusters, *num_clusters,
+ *                             *backward);
+ *
+ *     if (glyphs != stack_glyphs)
+ *         cairo_glyph_free (*glyphs);
+ *     if (clusters != stack_clusters)
+ *         cairo_text_cluster_free (*clusters);
+ * }
+ * </programlisting></informalexample>
+ *
+ * For details of how @clusters, @num_clusters, and @backward map input
+ * UTF-8 text to the output glyphs see cairo_show_text_glyphs().
+ *
+ * The output values can be readily passed to cairo_show_text_glyphs()
+ * cairo_show_glyphs(), or related functions, assuming that the exact
+ * same @scaled_font is used for the operation.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS upon success, or an error status
+ * if the input values are wrong or if conversion failed.  If the input
+ * values are correct but the conversion failed, the error status is also
+ * set on @scaled_font.
+ *
+ * Since: 1.8
+ **/
 cairo_status_t
-_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
-				   double		x,
-				   double		y,
-				   const char          *utf8,
-				   cairo_glyph_t      **glyphs,
-				   int 		       *num_glyphs)
+cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t   *scaled_font,
+				  double		 x,
+				  double		 y,
+				  const char	        *utf8,
+				  int		         utf8_len,
+				  cairo_glyph_t	       **glyphs,
+				  int		        *num_glyphs,
+				  cairo_text_cluster_t **clusters,
+				  int		        *num_clusters,
+				  cairo_bool_t	        *backward)
 {
     int i;
-    uint32_t *ucs4 = NULL;
+    int num_chars = 0;
+    const char *p;
     cairo_status_t status;
-    cairo_scaled_glyph_t *scaled_glyph;
-
-    *num_glyphs = 0;
-    *glyphs = NULL;
+    cairo_glyph_t *orig_glyphs;
+    cairo_text_cluster_t *orig_clusters;
 
     status = scaled_font->status;
     if (status)
 	return status;
 
-    if (utf8[0] == '\0')
-	return CAIRO_STATUS_SUCCESS;
+    /* A slew of sanity checks */
+
+    /* glyphs and num_glyphs can't be NULL */
+    if (glyphs     == NULL ||
+	num_glyphs == NULL) {
+	status = CAIRO_STATUS_NULL_POINTER;
+	goto BAIL;
+    }
+
+    /* Special case for NULL and -1 */
+    if (utf8 == NULL && utf8_len == -1)
+	utf8_len = 0;
+
+    /* No NULLs for non-NULLs! */
+    if ((utf8_len && utf8         == NULL) ||
+	(clusters && num_clusters == NULL) ||
+	(clusters && backward     == NULL)) {
+	status = CAIRO_STATUS_NULL_POINTER;
+	goto BAIL;
+    }
+
+    /* A -1 for utf8_len means NUL-terminated */
+    if (utf8_len == -1)
+	utf8_len = strlen (utf8);
+
+    /* A NULL *glyphs means no prealloced glyphs array */
+    if (glyphs && *glyphs == NULL)
+	*num_glyphs = 0;
+
+    /* A NULL *clusters means no prealloced clusters array */
+    if (clusters && *clusters == NULL)
+	*num_clusters = 0;
+
+    if (!clusters && num_clusters) {
+	num_clusters = NULL;
+    }
+
+    if (backward) {
+	*backward = FALSE;
+    }
+
+    if (!clusters && backward) {
+	backward = NULL;
+    }
+
+    /* Apart from that, no negatives */
+    if (utf8_len < 0 ||
+	*num_glyphs < 0 ||
+	(num_clusters && *num_clusters < 0)) {
+	status = CAIRO_STATUS_NEGATIVE_COUNT;
+	goto BAIL;
+    }
+
+    if (utf8_len == 0) {
+	status = CAIRO_STATUS_SUCCESS;
+	goto BAIL;
+    }
+
+    /* validate input so backend does not have to */
+    status = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, &num_chars);
+    if (status)
+	goto BAIL;
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
     _cairo_scaled_font_freeze_cache (scaled_font);
 
+    orig_glyphs = *glyphs;
+    orig_clusters = clusters ? *clusters : NULL;
+
     if (scaled_font->backend->text_to_glyphs) {
 
-	/* validate input so backend does not have to */
-	status = _cairo_utf8_to_ucs4 (utf8, -1, NULL, NULL);
-	if (status)
-	    goto DONE;
+	status = scaled_font->backend->text_to_glyphs (scaled_font, x, y,
+						       utf8, utf8_len,
+						       glyphs, num_glyphs,
+						       clusters, num_clusters,
+						       backward);
+
+        if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
+
+	    if (status == CAIRO_STATUS_SUCCESS) {
+
+	        /* The checks here are crude; we only should do them in
+		 * user-font backend, but they don't hurt here.  This stuff
+		 * can be hard to get right. */
 
-	status = scaled_font->backend->text_to_glyphs (scaled_font,
-						       x, y, utf8,
-						       glyphs, num_glyphs);
+	        if (*num_glyphs < 0) {
+		    status = CAIRO_STATUS_NEGATIVE_COUNT;
+		    goto DONE;
+		}
+		if (num_glyphs && *glyphs == NULL) {
+		    status = CAIRO_STATUS_NULL_POINTER;
+		    goto DONE;
+		}
+
+		if (clusters) {
 
-        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+		    if (*num_clusters < 0) {
+			status = CAIRO_STATUS_NEGATIVE_COUNT;
+			goto DONE;
+		    }
+		    if (num_clusters && *clusters == NULL) {
+			status = CAIRO_STATUS_NULL_POINTER;
+			goto DONE;
+		    }
+
+		    /* Dont trust the backend, validate clusters! */
+		    status = _cairo_validate_text_clusters (utf8, utf8_len,
+							    *glyphs, *num_glyphs,
+							    *clusters, *num_clusters,
+							    *backward);
+		}
+	    }
+
             goto DONE;
+	}
     }
 
-    status = _cairo_utf8_to_ucs4 (utf8, -1, &ucs4, num_glyphs);
-    if (status)
-	goto DONE;
+    if (*num_glyphs < num_chars) {
+	*glyphs = cairo_glyph_allocate (num_chars);
+	if (*glyphs == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto DONE;
+	}
+    }
+    *num_glyphs = num_chars;
 
-    *glyphs = (cairo_glyph_t *) _cairo_malloc_ab ((*num_glyphs), sizeof (cairo_glyph_t));
-
-    if (*glyphs == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto DONE;
+    if (clusters) {
+	if (*num_clusters < num_chars) {
+	    *clusters = cairo_text_cluster_allocate (num_chars);
+	    if (*clusters == NULL) {
+		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		goto DONE;
+	    }
+	}
+	*num_clusters = num_chars;
     }
 
-    for (i = 0; i < *num_glyphs; i++) {
-        (*glyphs)[i].index = (*scaled_font->backend->
-			      ucs4_to_index) (scaled_font, ucs4[i]);
+    p = utf8;
+    for (i = 0; i < num_chars; i++) {
+	int num_bytes;
+	uint32_t unicode;
+	cairo_scaled_glyph_t *scaled_glyph;
+
+	num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
+	p += num_bytes;
+
+        (*glyphs)[i].index = (*scaled_font->backend->ucs4_to_index) (scaled_font, unicode);
 	(*glyphs)[i].x = x;
 	(*glyphs)[i].y = y;
 
+	if (clusters) {
+	    (*clusters)[i].num_bytes  = num_bytes;
+	    (*clusters)[i].num_glyphs = 1;
+	}
+
 	status = _cairo_scaled_glyph_lookup (scaled_font,
 					     (*glyphs)[i].index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
 					     &scaled_glyph);
 	if (status) {
-	    free (*glyphs);
-	    *glyphs = NULL;
 	    goto DONE;
 	}
 
         x += scaled_glyph->metrics.x_advance;
         y += scaled_glyph->metrics.y_advance;
     }
 
- DONE:
+ DONE: /* error that should be logged on scaled_font happened */
     _cairo_scaled_font_thaw_cache (scaled_font);
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
-    if (ucs4)
-	free (ucs4);
+    if (status) {
+	*num_glyphs = 0;
+	if (*glyphs != orig_glyphs) {
+	    cairo_glyph_free (*glyphs);
+	    *glyphs = orig_glyphs;
+	}
+
+	if (clusters) {
+	    *num_clusters = 0;
+	    if (*clusters != orig_clusters) {
+		cairo_text_cluster_free (*clusters);
+		*clusters = orig_clusters;
+	    }
+	}
+    }
 
     return _cairo_scaled_font_set_error (scaled_font, status);
+
+ BAIL: /* error with input arguments */
+
+    if (num_glyphs)
+	*num_glyphs = 0;
+
+    if (num_clusters)
+	*num_clusters = 0;
+
+    return status;
 }
+slim_hidden_def (cairo_scaled_font_text_to_glyphs);
 
 /*
  * Compute a device-space bounding box for the glyphs.
  */
 cairo_status_t
 _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
 					 const cairo_glyph_t	 *glyphs,
 					 int                      num_glyphs,
@@ -1448,18 +1777,16 @@ cairo_status_t
 	if (remaining_glyphs == 0)
 	    status = CAIRO_STATUS_SUCCESS;
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	    return _cairo_scaled_font_set_error (scaled_font, status);
     }
 
     /* Font display routine either does not exist or failed. */
 
-    status = CAIRO_STATUS_SUCCESS;
-
     _cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
 
     _cairo_cache_freeze (scaled_font->glyphs);
 
     for (i = 0; i < num_glyphs; i++) {
 	int x, y;
 	cairo_surface_pattern_t glyph_pattern;
 	cairo_image_surface_t *glyph_surface;
@@ -1691,17 +2018,17 @@ static cairo_status_t
  * something more sophisticated.
  **/
 static cairo_status_t
 _trace_mask_to_path (cairo_image_surface_t *mask,
 		     cairo_path_fixed_t *path)
 {
     cairo_status_t status;
     cairo_image_surface_t *a1_mask;
-    unsigned char *row, *byte_ptr, byte;
+    uint8_t *row, *byte_ptr, byte;
     int rows, cols, bytes_per_row;
     int x, y, bit;
     double xoff, yoff;
 
     if (mask->format == CAIRO_FORMAT_A1)
 	a1_mask = (cairo_image_surface_t *) cairo_surface_reference (&mask->base);
     else
 	a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1);
@@ -1711,17 +2038,17 @@ static cairo_status_t
 	cairo_surface_destroy (&a1_mask->base);
 	return status;
     }
 
     cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
 
     bytes_per_row = (a1_mask->width + 7) / 8;
     for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) {
-	for (x = 0, byte_ptr = row, cols = (a1_mask->width + 7) / 8; cols; byte_ptr++, cols--) {
+	for (x = 0, byte_ptr = row, cols = bytes_per_row; cols; byte_ptr++, cols--) {
 	    byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
 	    for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
 		if (byte & (1 << bit)) {
 		    status = _add_unit_rectangle_to_path (path,
 							  x - xoff, y - yoff);
 		    if (status)
 			goto BAIL;
 		}
--- a/gfx/cairo/cairo/src/cairo-surface.c
+++ b/gfx/cairo/cairo/src/cairo-surface.c
@@ -66,20 +66,21 @@ const cairo_surface_t name = {					\
     0.0,				/* y_resolution */	\
     0.0,				/* x_fallback_resolution */	\
     0.0,				/* y_fallback_resolution */	\
     NULL,				/* clip */		\
     0,					/* next_clip_serial */	\
     0,					/* current_clip_serial */	\
     FALSE,				/* is_snapshot */	\
     FALSE,				/* has_font_options */	\
-    { CAIRO_ANTIALIAS_DEFAULT,					\
-      CAIRO_SUBPIXEL_ORDER_DEFAULT,				\
-      CAIRO_HINT_STYLE_DEFAULT,					\
-      CAIRO_HINT_METRICS_DEFAULT				\
+    { CAIRO_ANTIALIAS_DEFAULT,		/* antialias */		\
+      CAIRO_SUBPIXEL_ORDER_DEFAULT,	/* subpixel_order */	\
+      CAIRO_LCD_FILTER_DEFAULT,		/* lcd_filter */	\
+      CAIRO_HINT_STYLE_DEFAULT,		/* hint_style */	\
+      CAIRO_HINT_METRICS_DEFAULT	/* hint_metrics */	\
     }					/* font_options */	\
 }
 
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual);
 static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
@@ -643,17 +644,22 @@ void
  **/
 void
 cairo_surface_get_font_options (cairo_surface_t       *surface,
 				cairo_font_options_t  *options)
 {
     if (cairo_font_options_status (options))
 	return;
 
-    if (!surface->has_font_options) {
+    if (surface->status) {
+	_cairo_font_options_init_default (options);
+	return;
+    }
+
+    if (! surface->has_font_options) {
 	surface->has_font_options = TRUE;
 
 	_cairo_font_options_init_default (&surface->font_options);
 
 	if (!surface->finished && surface->backend->get_font_options) {
 	    surface->backend->get_font_options (surface, &surface->font_options);
 	}
     }
@@ -1727,16 +1733,19 @@ cairo_status_t
  * cairo_surface_copy_page:
  * @surface: a #cairo_surface_t
  *
  * Emits the current page for backends that support multiple pages,
  * but doesn't clear it, so that the contents of the current page will
  * be retained for the next page.  Use cairo_surface_show_page() if you
  * want to get an empty page after the emission.
  *
+ * There is a convenience function for this that takes a #cairo_t,
+ * namely cairo_copy_page().
+ *
  * Since: 1.6
  */
 void
 cairo_surface_copy_page (cairo_surface_t *surface)
 {
     cairo_status_t status_ignored;
 
     assert (! surface->is_snapshot);
@@ -1761,16 +1770,19 @@ slim_hidden_def (cairo_surface_copy_page
 
 /**
  * cairo_surface_show_page:
  * @surface: a #cairo_Surface_t
  *
  * Emits and clears the current page for backends that support multiple
  * pages.  Use cairo_surface_copy_page() if you don't want to clear the page.
  *
+ * There is a convenience function for this that takes a #cairo_t,
+ * namely cairo_show_page().
+ *
  * Since: 1.6
  **/
 void
 cairo_surface_show_page (cairo_surface_t *surface)
 {
     cairo_status_t status_ignored;
 
     assert (! surface->is_snapshot);
@@ -2130,24 +2142,60 @@ cairo_int_status_t
 	extents->y      = CAIRO_RECT_INT_MIN;
 	extents->width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
 	extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
     }
 
     return status;
 }
 
+/**
+ * cairo_surface_has_show_text_glyphs:
+ * @surface: a #cairo_surface_t
+ *
+ * Returns whether the surface supports
+ * sophisticated cairo_show_text_glyphs() operations.  That is,
+ * whether it actually uses the provided text and cluster data
+ * to a cairo_show_text_glyphs() call.
+ *
+ * Note: Even if this function returns %FALSE, a
+ * cairo_show_text_glyphs() operation targeted at @surface will
+ * still succeed.  It just will
+ * act like a cairo_show_glyphs() operation.  Users can use this
+ * function to avoid computing UTF-8 text and cluster mapping if the
+ * target surface does not use it.
+ *
+ * There is a convenience function for this that takes a #cairo_t,
+ * namely cairo_has_show_text_glyphs().
+ *
+ * Return value: %TRUE if @surface supports
+ *               cairo_show_text_glyphs(), %FALSE otherwise
+ *
+ * Since: 1.8
+ **/
 cairo_bool_t
-_cairo_surface_has_show_text_glyphs (cairo_surface_t	    *surface)
+cairo_surface_has_show_text_glyphs (cairo_surface_t	    *surface)
 {
+    cairo_status_t status_ignored;
+
+    if (surface->status)
+	return FALSE;
+
+    if (surface->finished) {
+	status_ignored = _cairo_surface_set_error (surface,
+						   CAIRO_STATUS_SURFACE_FINISHED);
+	return FALSE;
+    }
+
     if (surface->backend->has_show_text_glyphs)
 	return surface->backend->has_show_text_glyphs (surface);
     else
 	return surface->backend->show_text_glyphs != NULL;
 }
+slim_hidden_def (cairo_surface_has_show_text_glyphs);
 
 /* Note: the backends may modify the contents of the glyph array as long as
  * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to
  * avoid copying the array again and again, and edit it in-place.
  * Backends are in fact free to use the array as a generic buffer as they
  * see fit.
  *
  * For show_glyphs backend method, and NOT for show_text_glyphs method,
@@ -2553,25 +2601,18 @@ static cairo_status_t
 {
     cairo_status_t status;
 
     status = _cairo_pattern_create_copy (pattern_out, pattern);
     if (status)
 	return status;
 
     if (_cairo_surface_has_device_transform (destination)) {
-	cairo_matrix_t device_to_surface = destination->device_transform;
-
-	status = cairo_matrix_invert (&device_to_surface);
-	/* We only ever allow for scaling (under the implementation's
-	 * control) or translation (under the user's control). So the
-	 * matrix should always be invertible. */
-	assert (status == CAIRO_STATUS_SUCCESS);
-
-	_cairo_pattern_transform (*pattern_out, &device_to_surface);
+	_cairo_pattern_transform (*pattern_out,
+		                  &destination->device_transform_inverse);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_surface_set_resolution
  * @surface: the surface
@@ -2634,16 +2675,18 @@ cairo_surface_t *
     case CAIRO_STATUS_INVALID_DSC_COMMENT:
     case CAIRO_STATUS_INVALID_INDEX:
     case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
     case CAIRO_STATUS_FONT_TYPE_MISMATCH:
     case CAIRO_STATUS_USER_FONT_IMMUTABLE:
     case CAIRO_STATUS_USER_FONT_ERROR:
     case CAIRO_STATUS_NEGATIVE_COUNT:
     case CAIRO_STATUS_INVALID_CLUSTERS:
+    case CAIRO_STATUS_INVALID_SLANT:
+    case CAIRO_STATUS_INVALID_WEIGHT:
     default:
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t *) &_cairo_surface_nil;
     }
 }
 
 /*  LocalWords:  rasterized
  */
--- a/gfx/cairo/cairo/src/cairo-svg-surface.c
+++ b/gfx/cairo/cairo/src/cairo-svg-surface.c
@@ -646,17 +646,17 @@ static cairo_int_status_t
 static cairo_int_status_t
 _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t	*document,
 					    cairo_scaled_font_t		*scaled_font,
 					    unsigned long		 glyph_index)
 {
     cairo_image_surface_t *image;
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_status_t status;
-    unsigned char *row, *byte;
+    uint8_t *row, *byte;
     int rows, cols;
     int x, y, bit;
 
     status = _cairo_scaled_glyph_lookup (scaled_font,
 					 glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					 &scaled_glyph);
@@ -672,17 +672,17 @@ static cairo_int_status_t
 
     _cairo_output_stream_printf (document->xml_node_glyphs, "<g");
     _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform",
 				       &image->base.device_transform_inverse, NULL);
     _cairo_output_stream_printf (document->xml_node_glyphs, ">/n");
 
     for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
 	for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
-	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
 	    for (bit = 7; bit >= 0 && x < image->width; bit--, x++) {
 		if (output_byte & (1 << bit)) {
 		    _cairo_output_stream_printf (document->xml_node_glyphs,
 						 "<rect x=\"%d\" y=\"%d\" width=\"1\" height=\"1\"/>\n",
 						 x, y);
 		}
 	    }
 	}
@@ -865,89 +865,86 @@ static void
 				 "</filter>\n");
 
     document->alpha_filter = TRUE;
 }
 
 typedef struct {
     cairo_output_stream_t *output;
     unsigned int in_mem;
+    unsigned int trailing;
     unsigned char src[3];
-    unsigned char dst[5];
-    unsigned int trailing;
 } base64_write_closure_t;
 
-static char const *base64_table =
+static char const base64_table[64] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 static cairo_status_t
 base64_write_func (void *closure,
 		   const unsigned char *data,
 		   unsigned int length)
 {
     base64_write_closure_t *info = (base64_write_closure_t *) closure;
     unsigned int i;
-    unsigned char *src, *dst;
-
-    dst = info->dst;
+    unsigned char *src;
+
     src = info->src;
 
     if (info->in_mem + length < 3) {
 	for (i = 0; i < length; i++) {
-	    src[i + info->in_mem] = *data;
-	    data++;
+	    src[i + info->in_mem] = *data++;
 	}
 	info->in_mem += length;
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    while (info->in_mem + length >= 3) {
-	for (i = 0; i < 3 - info->in_mem; i++) {
-	    src[i + info->in_mem] = *data;
-	    data++;
+    do {
+	unsigned char dst[4];
+
+	for (i = info->in_mem; i < 3; i++) {
+	    src[i] = *data++;
 	    length--;
 	}
+	info->in_mem = 0;
+
 	dst[0] = base64_table[src[0] >> 2];
 	dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
 	dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6];
 	dst[3] = base64_table[src[2] & 0xfc >> 2];
 	/* Special case for the last missing bits */
 	switch (info->trailing) {
 	    case 2:
 		dst[2] = '=';
 	    case 1:
 		dst[3] = '=';
 	    default:
 		break;
 	}
 	_cairo_output_stream_write (info->output, dst, 4);
-	info->in_mem = 0;
-    }
+    } while (length >= 3);
 
     for (i = 0; i < length; i++) {
-	src[i] = *data;
-	data++;
+	src[i] = *data++;
     }
     info->in_mem = length;
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (info->output);
 }
 
 static cairo_int_status_t
 _cairo_surface_base64_encode (cairo_surface_t       *surface,
 			      cairo_output_stream_t *output)
 {
     cairo_status_t status;
     base64_write_closure_t info;
     unsigned int i;
 
     info.output = output;
     info.in_mem = 0;
     info.trailing = 0;
-    memset (info.dst, '\x0', 5);
 
     _cairo_output_stream_printf (info.output, "data:image/png;base64,");
 
     status = cairo_surface_write_to_png_stream (surface, base64_write_func,
 						(void *) &info);
 
     if (status)
 	return status;
--- a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
+++ b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
@@ -34,16 +34,18 @@
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H
 #define CAIRO_TRUETYPE_SUBSET_PRIVATE_H
 
 #include "cairoint.h"
 
+#if CAIRO_HAS_FONT_SUBSET
+
 /* The structs defined here should strictly follow the TrueType
  * specification and not be padded.  We use only 16-bit integer
  * in their definition to guarantee that.  The fields of type
  * "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit
  * parts, and 64-bit members are broken into four.
  *
  * The test truetype-tables in the test suite makes sure that
  * these tables have the right size.  Please update that test
@@ -187,9 +189,11 @@ typedef struct _tt_composite_glyph {
 } tt_composite_glyph_t;
 
 typedef struct _tt_glyph_data {
     int16_t           num_contours;
     int8_t            data[8];
     tt_composite_glyph_t glyph;
 } tt_glyph_data_t;
 
+#endif /* CAIRO_HAS_FONT_SUBSET */
+
 #endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-truetype-subset.c
+++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c
@@ -38,16 +38,18 @@
  * Useful links:
  * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html
  * http://www.microsoft.com/typography/specs/default.htm
  */
 
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
 
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 
 
 typedef struct subset_glyph subset_glyph_t;
 struct subset_glyph {
     int parent_index;
     unsigned long location;
@@ -1219,18 +1221,17 @@ static cairo_int_status_t
 
     num_segments = be16_to_cpu (map->segCountX2)/2;
     end_code = map->endCount;
     start_code = &(end_code[num_segments + 1]);
     delta = &(start_code[num_segments]);
     range_offset = &(delta[num_segments]);
     glyph_array = &(range_offset[num_segments]);
 
-    /* search for glyph in segments
-     * with rangeOffset=0 */
+    /* search for glyph in segments with rangeOffset=0 */
     for (i = 0; i < num_segments; i++) {
 	c = index - be16_to_cpu (delta[i]);
 	if (range_offset[i] == 0 &&
 	    c >= be16_to_cpu (start_code[i]) &&
 	    c <= be16_to_cpu (end_code[i]))
 	{
 	    *ucs4 = c;
 	    goto found;
@@ -1240,22 +1241,23 @@ static cairo_int_status_t
     /* search for glyph in segments with rangeOffset=1 */
     for (i = 0; i < num_segments; i++) {
 	if (range_offset[i] != 0) {
 	    uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
 	    int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
 	    uint16_t g_id_be = cpu_to_be16 (index);
 	    int j;
 
-	    for (j = 0; j < range_size; j++) {
-		if (glyph_ids[j] == g_id_be) {
-		    *ucs4 = be16_to_cpu (start_code[i]) + j;
-		    goto found;
+	    if (range_size > 0)
+		for (j = 0; j < range_size; j++) {
+		    if (glyph_ids[j] == g_id_be) {
+			*ucs4 = be16_to_cpu (start_code[i]) + j;
+			goto found;
+		    }
 		}
-	    }
 	}
     }
 
     /* glyph not found */
     *ucs4 = -1;
 
 found:
     status = CAIRO_STATUS_SUCCESS;
@@ -1288,17 +1290,17 @@ cairo_int_status_t
 					   (unsigned char *) &buf,
 					   &size);
     if (status)
 	return status;
 
     cmap = (tt_cmap_t *) buf;
     num_tables = be16_to_cpu (cmap->num_tables);
     size = 4 + num_tables*sizeof(tt_cmap_index_t);
-    cmap = malloc (size);
+    cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4);
     if (cmap == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     status = backend->load_truetype_table (scaled_font,
 	                                   TT_TAG_cmap, 0,
 					   (unsigned char *) cmap,
 					   &size);
     if (status)
@@ -1317,8 +1319,10 @@ cairo_int_status_t
         }
     }
 
 cleanup:
     free (cmap);
 
     return status;
 }
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-type1-fallback.c
+++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c
@@ -30,16 +30,19 @@
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-type1-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-path-fixed-private.h"
 #include "cairo-output-stream-private.h"
 
 typedef enum {
     CAIRO_CHARSTRING_TYPE1,
     CAIRO_CHARSTRING_TYPE2
@@ -868,8 +871,10 @@ void
     for (i = 0; i < num_charstrings; i++) {
         charstring = _cairo_array_index (&type2_subset->charstrings, i);
         _cairo_array_fini (charstring);
     }
     _cairo_array_fini (&type2_subset->charstrings);
 
     free (type2_subset->widths);
 }
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-type1-private.h
+++ b/gfx/cairo/cairo/src/cairo-type1-private.h
@@ -31,15 +31,21 @@
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_TYPE1_PRIVATE_H
 #define CAIRO_TYPE1_PRIVATE_H
 
+#include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 /* Magic constants for the type1 eexec encryption */
 #define CAIRO_TYPE1_ENCRYPT_C1		((unsigned short) 52845)
 #define CAIRO_TYPE1_ENCRYPT_C2		((unsigned short) 22719)
 #define CAIRO_TYPE1_PRIVATE_DICT_KEY	((unsigned short) 55665)
 #define CAIRO_TYPE1_CHARSTRING_KEY	((unsigned short) 4330)
 
+#endif /* CAIRO_HAS_FONT_SUBSET */
+
 #endif /* CAIRO_TYPE1_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-type1-subset.c
+++ b/gfx/cairo/cairo/src/cairo-type1-subset.c
@@ -33,23 +33,29 @@
  *	Kristian Høgsberg <krh@redhat.com>
  */
 
 /*
  * Useful links:
  * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
  */
 
+
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-type1-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-output-stream-private.h"
 
 /* XXX: Eventually, we need to handle other font backends */
+#if CAIRO_HAS_FT_FONT
+
 #include "cairo-ft-private.h"
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_TYPE1_TABLES_H
 
 #include <ctype.h>
@@ -1400,8 +1406,12 @@ cairo_bool_t
     if (FT_IS_SFNT (face))
         is_type1 = FALSE;
 #endif
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return is_type1;
 }
+
+#endif /* CAIRO_HAS_FT_FONT */
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h
@@ -32,16 +32,20 @@
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
 #define CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
 
+#include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-surface-private.h"
 #include "cairo-pdf-operators-private.h"
 
 typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
 								  cairo_output_stream_t	*stream);
 
 typedef struct cairo_type3_glyph_surface {
     cairo_surface_t base;
@@ -66,9 +70,11 @@ cairo_private cairo_status_t
 
 cairo_private cairo_status_t
 _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
 				       cairo_output_stream_t *stream,
 				       unsigned long	      glyph_index,
 				       cairo_box_t           *bbox,
 				       double                *width);
 
+#endif /* CAIRO_HAS_FONT_SUBSET */
+
 #endif /* CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
+++ b/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
@@ -30,16 +30,19 @@
  *
  * The Initial Developer of the Original Code is Adrian Johnson.
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
+
+#if CAIRO_HAS_FONT_SUBSET
+
 #include "cairo-type3-glyph-surface-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-meta-surface-private.h"
 
 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
 
 cairo_surface_t *
 _cairo_type3_glyph_surface_create (cairo_scaled_font_t	 		 *scaled_font,
@@ -107,17 +110,17 @@ static cairo_status_t
     status = surface->emit_image (image_mask, surface->stream);
 
     _cairo_output_stream_printf (surface->stream,
 				 "Q\n");
 
     if (image_mask != image)
 	cairo_surface_destroy (&image_mask->base);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 static cairo_status_t
 _cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface,
 					       cairo_image_surface_t       *image,
 					       cairo_matrix_t              *pattern_matrix)
 {
     cairo_matrix_t mat, upside_down;
@@ -438,8 +441,10 @@ cairo_status_t
 	    return status2;
     }
 
     if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
 	status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
 
     return status;
 }
+
+#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-types-private.h
+++ b/gfx/cairo/cairo/src/cairo-types-private.h
@@ -40,27 +40,37 @@
 #define CAIRO_TYPES_PRIVATE_H
 
 /* This is the only header file not including cairoint.h.  It only contains
  * typedefs.*/
 #include "cairo.h"
 #include "cairo-fixed-type-private.h"
 
 typedef struct _cairo_array cairo_array_t;
-typedef struct _cairo_hash_table cairo_hash_table_t;
 typedef struct _cairo_cache cairo_cache_t;
+typedef struct _cairo_clip cairo_clip_t;
+typedef struct _cairo_clip_path cairo_clip_path_t;
+typedef struct _cairo_color cairo_color_t;
+typedef struct _cairo_font_face_backend     cairo_font_face_backend_t;
+typedef struct _cairo_gstate cairo_gstate_t;
 typedef struct _cairo_hash_entry cairo_hash_entry_t;
-typedef struct _cairo_surface_backend cairo_surface_backend_t;
-typedef struct _cairo_clip cairo_clip_t;
+typedef struct _cairo_hash_table cairo_hash_table_t;
+typedef struct _cairo_image_surface cairo_image_surface_t;
 typedef struct _cairo_output_stream cairo_output_stream_t;
-typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
 typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
+typedef struct _cairo_path_fixed cairo_path_fixed_t;
+typedef struct _cairo_rectangle_int16 cairo_glyph_size_t;
+typedef struct _cairo_region cairo_region_t;
 typedef struct _cairo_scaled_font_backend   cairo_scaled_font_backend_t;
-typedef struct _cairo_font_face_backend     cairo_font_face_backend_t;
+typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
+typedef struct _cairo_solid_pattern cairo_solid_pattern_t;
+typedef struct _cairo_surface_backend cairo_surface_backend_t;
+typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
 typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
+
 typedef cairo_array_t cairo_user_data_array_t;
 
 /**
  * cairo_hash_entry_t:
  *
  * A #cairo_hash_entry_t contains both a key and a value for
  * #cairo_hash_table_t. User-derived types for #cairo_hash_entry_t must
  * be type-compatible with this structure (eg. they must have an
@@ -103,16 +113,17 @@ struct _cairo_array {
     char **elements;
 
     cairo_bool_t is_snapshot;
 };
 
 struct _cairo_font_options {
     cairo_antialias_t antialias;
     cairo_subpixel_order_t subpixel_order;
+    cairo_lcd_filter_t lcd_filter;
     cairo_hint_style_t hint_style;
     cairo_hint_metrics_t hint_metrics;
 };
 
 struct _cairo_cache {
     cairo_hash_table_t *hash_table;
 
     cairo_destroy_func_t entry_destroy;
@@ -132,17 +143,16 @@ typedef enum _cairo_paginated_mode {
 /* Sure wish C had a real enum type so that this would be distinct
  * from #cairo_status_t. Oh well, without that, I'll use this bogus 100
  * offset.  We want to keep it fit in int8_t as the compiler may choose
  * that for #cairo_status_t */
 typedef enum _cairo_int_status {
     CAIRO_INT_STATUS_UNSUPPORTED = 100,
     CAIRO_INT_STATUS_DEGENERATE,
     CAIRO_INT_STATUS_NOTHING_TO_DO,
-    CAIRO_INT_STATUS_CACHE_EMPTY,
     CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
     CAIRO_INT_STATUS_IMAGE_FALLBACK,
     CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN,
 
     CAIRO_INT_STATUS_LAST_STATUS
 } cairo_int_status_t;
 
 typedef enum _cairo_internal_surface_type {
@@ -151,18 +161,16 @@ typedef enum _cairo_internal_surface_typ
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
     CAIRO_INTERNAL_SURFACE_TYPE_NULL,
     CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
 } cairo_internal_surface_type_t;
 
-typedef struct _cairo_region cairo_region_t;
-
 typedef struct _cairo_point {
     cairo_fixed_t x;
     cairo_fixed_t y;
 } cairo_point_t;
 
 typedef struct _cairo_slope
 {
     cairo_fixed_t dx;
@@ -194,18 +202,16 @@ struct _cairo_rectangle_int16 {
     uint16_t width, height;
 };
 
 struct _cairo_rectangle_int32 {
     int32_t x, y;
     uint32_t width, height;
 };
 
-typedef struct _cairo_rectangle_int16 cairo_glyph_size_t;
-
 struct _cairo_point_int16 {
     int16_t x, y;
 };
 
 struct _cairo_point_int32 {
     int32_t x, y;
 };
 
@@ -228,23 +234,21 @@ typedef struct _cairo_box_int {
     cairo_point_int_t p2;
 } cairo_box_int_t;
 
 typedef enum _cairo_direction {
     CAIRO_DIRECTION_FORWARD,
     CAIRO_DIRECTION_REVERSE
 } cairo_direction_t;
 
-typedef struct _cairo_path_fixed cairo_path_fixed_t;
 typedef enum _cairo_clip_mode {
     CAIRO_CLIP_MODE_PATH,
     CAIRO_CLIP_MODE_REGION,
     CAIRO_CLIP_MODE_MASK
 } cairo_clip_mode_t;
-typedef struct _cairo_clip_path cairo_clip_path_t;
 
 typedef struct _cairo_edge {
     cairo_line_t edge;
     int clockWise;
 
     cairo_fixed_t current_x;
 } cairo_edge_t;
 
@@ -287,19 +291,16 @@ typedef struct _cairo_pen {
     double radius;
     double tolerance;
 
     int num_vertices;
     cairo_pen_vertex_t *vertices;
     cairo_pen_vertex_t  vertices_embedded[32];
 } cairo_pen_t;
 
-typedef struct _cairo_color cairo_color_t;
-typedef struct _cairo_image_surface cairo_image_surface_t;
-
 typedef struct _cairo_stroke_style {
     double		 line_width;
     cairo_line_cap_t	 line_cap;
     cairo_line_join_t	 line_join;
     double		 miter_limit;
     double		*dash;
     unsigned int	 num_dashes;
     double		 dash_offset;
--- a/gfx/cairo/cairo/src/cairo-unicode.c
+++ b/gfx/cairo/cairo/src/cairo-unicode.c
@@ -191,16 +191,50 @@ static uint32_t
 
     if (UTF8_LENGTH(wc) != len)
 	return (uint32_t)-1;
 
     return wc;
 }
 
 /**
+ * _cairo_utf8_get_char_validated:
+ * @p: a UTF-8 string
+ * @unicode: location to store one Unicode character
+ *
+ * Decodes the first character of a valid UTF-8 string, and returns
+ * the number of bytes consumed.
+ *
+ * Note that the string should be valid.  Do not use this without
+ * validating the string first.
+ *
+ * Returns: the number of bytes forming the character returned.
+ **/
+int
+_cairo_utf8_get_char_validated (const char *p,
+				uint32_t   *unicode)
+{
+    int i, mask = 0, len;
+    uint32_t result;
+    unsigned char c = (unsigned char) *p;
+
+    UTF8_COMPUTE (c, mask, len);
+    if (len == -1) {
+	if (unicode)
+	    *unicode = (uint32_t)-1;
+	return 1;
+    }
+    UTF8_GET (result, p, i, mask, len);
+
+    if (unicode)
+	*unicode = result;
+    return len;
+}
+
+/**
  * _cairo_utf8_to_utf32:
  * @str: an UTF-8 string
  * @len: length of @str in bytes, or -1 if it is nul-terminated.
  *   If @len is supplied and the string has an embedded nul
  *   byte, only the portion before the nul byte is converted.
  * @result: location to store a pointer to a newly allocated UTF-32
  *   string (always native endian), or %NULL. Free with free(). A 0
  *   word will be written after the last character.
@@ -261,41 +295,45 @@ cairo_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_ucs4_to_utf8:
  * @unicode: a UCS-4 character
  * @utf8: buffer to write utf8 string into. Must have at least 4 bytes
- * space available.
+ * space available. Or %NULL.
  *
  * Return value: Number of bytes in the utf8 string or 0 if an invalid
  * unicode character
  **/
 int
 _cairo_ucs4_to_utf8 (uint32_t  unicode,
 		     char     *utf8)
 {
     int bytes;
     char *p;
 
     if (unicode < 0x80) {
-	*utf8 = unicode;
+	if (utf8)
+	    *utf8 = unicode;
 	return 1;
     } else if (unicode < 0x800) {
 	bytes = 2;
     } else if (unicode < 0x10000) {
 	bytes = 3;
     } else if (unicode < 0x200000) {
 	bytes = 4;
     } else {
 	return 0;
     }
 
+    if (!utf8)
+	return bytes;
+
     p = utf8 + bytes;
     while (p > utf8) {
 	*--p = 0x80 | (unicode & 0x3f);
 	unicode >>= 6;
     }
     *p |= 0xf0 << (4 - bytes);
 
     return bytes;
--- a/gfx/cairo/cairo/src/cairo-user-font-private.h
+++ b/gfx/cairo/cairo/src/cairo-user-font-private.h
@@ -33,13 +33,14 @@
  *      Kristian Høgsberg <krh@redhat.com>
  *      Behdad Esfahbod <behdad@behdad.org>
  */
 
 #ifndef CAIRO_USER_FONT_PRIVATE_H
 #define CAIRO_USER_FONT_PRIVATE_H
 
 #include "cairo.h"
+#include "cairo-compiler-private.h"
 
 cairo_private cairo_bool_t
 _cairo_font_face_is_user (cairo_font_face_t *font_face);
 
 #endif /* CAIRO_USER_FONT_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-user-font.c
+++ b/gfx/cairo/cairo/src/cairo-user-font.c
@@ -69,53 +69,69 @@ typedef struct _cairo_user_scaled_font {
     /* multiplier for metrics hinting */
     double snap_x_scale;
     double snap_y_scale;
 
 } cairo_user_scaled_font_t;
 
 /* #cairo_user_scaled_font_t */
 
+static cairo_t *
+_cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_font)
+{
+    cairo_content_t content;
+    cairo_surface_t *meta_surface;
+    cairo_t *cr;
+
+    content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
+						     CAIRO_CONTENT_COLOR_ALPHA :
+						     CAIRO_CONTENT_ALPHA;
+
+    meta_surface = _cairo_meta_surface_create (content, -1, -1);
+    cr = cairo_create (meta_surface);
+    cairo_surface_destroy (meta_surface);
+
+    cairo_set_matrix (cr, &scaled_font->base.scale);
+    cairo_set_font_size (cr, 1.0);
+    cairo_set_font_options (cr, &scaled_font->base.options);
+
+    return cr;
+}
+
 static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend;
 
 static cairo_int_status_t
 _cairo_user_scaled_glyph_init (void			 *abstract_font,
 			       cairo_scaled_glyph_t	 *scaled_glyph,
 			       cairo_scaled_glyph_info_t  info)
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_user_scaled_font_t *scaled_font = abstract_font;
     cairo_surface_t *meta_surface = scaled_glyph->meta_surface;
 
     if (!scaled_glyph->meta_surface) {
 	cairo_user_font_face_t *face =
 	    (cairo_user_font_face_t *) scaled_font->base.font_face;
 	cairo_text_extents_t extents = scaled_font->default_glyph_extents;
-	cairo_content_t content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
-									 CAIRO_CONTENT_COLOR_ALPHA :
-									 CAIRO_CONTENT_ALPHA;
 	cairo_t *cr;
 
-	meta_surface = _cairo_meta_surface_create (content, -1, -1);
-	cr = cairo_create (meta_surface);
-
-	cairo_set_matrix (cr, &scaled_font->base.scale);
-	cairo_set_font_size (cr, 1.0);
-	cairo_set_font_options (cr, &scaled_font->base.options);
+	cr = _cairo_user_scaled_font_create_meta_context (scaled_font);
 
 	if (face->scaled_font_methods.render_glyph)
 	    status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
 							     _cairo_scaled_glyph_index(scaled_glyph),
 							     cr, &extents);
 	else
 	    status = CAIRO_STATUS_USER_FONT_ERROR;
 
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = cairo_status (cr);
 
+	meta_surface = cairo_surface_reference (cairo_get_target (cr));
+
 	cairo_destroy (cr);
 
 	if (status) {
 	    cairo_surface_destroy (meta_surface);
 	    return status;
 	}
 
 	_cairo_scaled_glyph_set_meta_surface (scaled_glyph,
@@ -126,25 +142,31 @@ static cairo_int_status_t
 	/* set metrics */
 
 	if (extents.width == 0.) {
 	    /* Compute extents.x/y/width/height from meta_surface, in font space */
 
 	    cairo_box_t bbox;
 	    double x1, y1, x2, y2;
 	    double x_scale, y_scale;
-	    cairo_surface_t *null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
-	    cairo_surface_t *analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
+	    cairo_surface_t *null_surface;
+	    cairo_surface_t *analysis_surface;
+
+	    null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
+	    analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
 	    cairo_surface_destroy (null_surface);
 
 	    _cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
 	    status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
 	    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
 	    cairo_surface_destroy (analysis_surface);
 
+	    if (status)
+		return status;
+
 	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
 
 	    x_scale = scaled_font->extent_x_scale;
 	    y_scale = scaled_font->extent_y_scale;
 	    extents.x_bearing = x1 * x_scale;
 	    extents.y_bearing = y1 * y_scale;
 	    extents.width     = (x2 - x1) * x_scale;
 	    extents.height    = (y2 - y1) * y_scale;
@@ -244,51 +266,51 @@ static unsigned long
     } else {
 	glyph = ucs4;
     }
 
     return glyph;
 }
 
 static cairo_int_status_t
-_cairo_user_text_to_glyphs (void           *abstract_font,
-			    double          x,
-			    double          y,
-			    const char     *utf8,
-			    cairo_glyph_t **glyphs,
-			    int	           *num_glyphs)
+_cairo_user_text_to_glyphs (void		 *abstract_font,
+			    double		  x,
+			    double		  y,
+			    const char		 *utf8,
+			    int			  utf8_len,
+			    cairo_glyph_t	**glyphs,
+			    int			  *num_glyphs,
+			    cairo_text_cluster_t **clusters,
+			    int			  *num_clusters,
+			    cairo_bool_t	  *backward)
 {
     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     cairo_user_scaled_font_t *scaled_font = abstract_font;
     cairo_user_font_face_t *face =
 	(cairo_user_font_face_t *) scaled_font->base.font_face;
 
     if (face->scaled_font_methods.text_to_glyphs) {
 	int i;
-
-	*glyphs = NULL;
-	*num_glyphs = -1;
+	int orig_num_glyphs = *num_glyphs;
 
-	/* XXX currently user allocs glyphs array but cairo frees it */
 	status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
-							   utf8, glyphs, num_glyphs);
+							   utf8, utf8_len,
+							   glyphs, num_glyphs,
+							   clusters, num_clusters,
+							   backward);
 
-	if (status != CAIRO_STATUS_SUCCESS) {
-	    status = _cairo_scaled_font_set_error (&scaled_font->base, status);
-	    if (*glyphs) {
-		free (*glyphs);
-		*glyphs = NULL;
-	    }
+	if (status != CAIRO_STATUS_SUCCESS)
 	    return status;
+
+	if (*num_glyphs < 0) {
+	    *num_glyphs = orig_num_glyphs;
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
 
-	if (*num_glyphs < 0)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 	/* Convert from font space to user space and add x,y */
 	for (i = 0; i < *num_glyphs; i++) {
 	    double gx = (*glyphs)[i].x;
 	    double gy = (*glyphs)[i].y;
 
 	    cairo_matrix_transform_point (&scaled_font->base.font_matrix,
 					  &gx, &gy);
 
@@ -346,17 +368,17 @@ static cairo_status_t
 
     /* compute a normalized version of font scale matrix to compute
      * extents in.  This is to minimize error caused by the cairo_fixed_t
      * representation. */
     {
 	double fixed_scale, x_scale, y_scale;
 
 	user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
-	status = _cairo_matrix_compute_scale_factors (&user_scaled_font->extent_scale,
+	status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
 						      &x_scale, &y_scale,
 						      1);
 	if (status == CAIRO_STATUS_SUCCESS) {
 
 	    if (x_scale == 0) x_scale = 1.;
 	    if (y_scale == 0) y_scale = 1.;
 
 	    user_scaled_font->snap_x_scale = x_scale;
@@ -372,26 +394,36 @@ static cairo_status_t
 
 	    user_scaled_font->extent_x_scale = x_scale;
 	    user_scaled_font->extent_y_scale = y_scale;
 	}
     }
 
     if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) {
 
+	cairo_t *cr;
+
 	/* Lock the scaled_font mutex such that user doesn't accidentally try
          * to use it just yet. */
 	CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
 
 	/* Give away fontmap lock such that user-font can use other fonts */
 	_cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
 
+	cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
+
 	status = font_face->scaled_font_methods.init (&user_scaled_font->base,
+						      cr,
 						      &font_extents);
 
+	if (status == CAIRO_STATUS_SUCCESS)
+	    status = cairo_status (cr);
+
+	cairo_destroy (cr);
+
 	_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
 
 	CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
     }
 
     if (status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-version.c
@@ -0,0 +1,88 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth@cworth.org>
+ */
+
+#define CAIRO_VERSION_H 1
+
+#include "cairoint.h"
+
+/* get the "real" version info instead of dummy cairo-version.h */
+#undef CAIRO_VERSION_H
+#include "cairo-features.h"
+
+/**
+ * cairo_version:
+ *
+ * Returns the version of the cairo library encoded in a single
+ * integer as per %CAIRO_VERSION_ENCODE. The encoding ensures that
+ * later versions compare greater than earlier versions.
+ *
+ * A run-time comparison to check that cairo's version is greater than
+ * or equal to version X.Y.Z could be performed as follows:
+ *
+ * <informalexample><programlisting>
+ * if (cairo_version() >= CAIRO_VERSION_ENCODE(X,Y,Z)) {...}
+ * </programlisting></informalexample>
+ *
+ * See also cairo_version_string() as well as the compile-time
+ * equivalents %CAIRO_VERSION and %CAIRO_VERSION_STRING.
+ *
+ * Return value: the encoded version.
+ **/
+int
+cairo_version (void)
+{
+    return CAIRO_VERSION;
+}
+
+/**
+ * cairo_version_string:
+ *
+ * Returns the version of the cairo library as a human-readable string
+ * of the form "X.Y.Z".
+ *
+ * See also cairo_version() as well as the compile-time equivalents
+ * %CAIRO_VERSION_STRING and %CAIRO_VERSION.
+ *
+ * Return value: a string containing the version.
+ **/
+const char*
+cairo_version_string (void)
+{
+    return CAIRO_VERSION_STRING;
+}
+slim_hidden_def (cairo_version_string);
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-version.h
@@ -0,0 +1,16 @@
+/* This is a dummy file.
+ * The actual version info is in toplevel cairo-version.h.
+ * The purpose of this file is to make most of the source files NOT depend
+ * on the real cairo-version.h, and as a result, changing library version
+ * would not cause a complete rebuild of all object files (just a relink).
+ * This is useful when bisecting. */
+#ifndef CAIRO_VERSION_H
+#define CAIRO_VERSION_H
+
+#if 0
+#define CAIRO_VERSION_MAJOR USE_cairo_version_OR_cairo_version_string_INSTEAD
+#define CAIRO_VERSION_MINOR USE_cairo_version_OR_cairo_version_string_INSTEAD
+#define CAIRO_VERSION_MICRO USE_cairo_version_OR_cairo_version_string_INSTEAD
+#endif
+
+#endif
--- a/gfx/cairo/cairo/src/cairo-wideint-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-wideint-type-private.h
@@ -54,35 +54,36 @@
   typedef unsigned __int16 uint16_t;
   typedef __int32 int32_t;
   typedef unsigned __int32 uint32_t;
   typedef __int64 int64_t;
   typedef unsigned __int64 uint64_t;
 # ifndef HAVE_UINT64_T
 #  define HAVE_UINT64_T 1
 # endif
-# ifndef INT16_MIN
-#  define INT16_MIN	(-32767-1)
-# endif
-# ifndef INT16_MAX
-#  define INT16_MAX	(32767)
-# endif
-# ifndef UINT16_MAX
-#  define UINT16_MAX	(65535)
-# endif
-# ifndef INT32_MIN
-#  define INT32_MIN	(-2147483647-1)
-# endif
-# ifndef INT32_MAX
-#  define INT32_MAX	(2147483647)
-# endif
 #else
 #error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
 #endif
 
+#ifndef INT16_MIN
+# define INT16_MIN	(-32767-1)
+#endif
+#ifndef INT16_MAX
+# define INT16_MAX	(32767)
+#endif
+#ifndef UINT16_MAX
+# define UINT16_MAX	(65535)
+#endif
+#ifndef INT32_MIN
+# define INT32_MIN	(-2147483647-1)
+#endif
+#ifndef INT32_MAX
+# define INT32_MAX	(2147483647)
+#endif
+
 #if HAVE_BYTESWAP_H
 # include <byteswap.h>
 #endif
 #ifndef bswap_16
 # define bswap_16(p) \
 	(((((uint16_t)(p)) & 0x00ff) << 8) | \
 	  (((uint16_t)(p))           >> 8));
 #endif
--- a/gfx/cairo/cairo/src/cairo-win32-font.c
+++ b/gfx/cairo/cairo/src/cairo-win32-font.c
@@ -125,16 +125,38 @@ static cairo_status_t
                                              cairo_scaled_glyph_t      *scaled_glyph);
 
 static cairo_status_t
 _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
 					  cairo_scaled_glyph_t      *scaled_glyph);
 
 #define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
 
+static HDC
+_get_global_font_dc (void)
+{
+    static HDC hdc;
+
+    if (!hdc) {
+	hdc = CreateCompatibleDC (NULL);
+	if (!hdc) {
+	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
+	    return NULL;
+	}
+
+	if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
+	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
+	    DeleteDC (hdc);
+	    return NULL;
+	}
+    }
+
+    return hdc;
+}
+
 static cairo_status_t
 _compute_transform (cairo_win32_scaled_font_t *scaled_font,
 		    cairo_matrix_t            *sc)
 {
     cairo_status_t status;
 
     if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy)) {
 	scaled_font->preserve_axes = TRUE;
@@ -170,17 +192,17 @@ static cairo_status_t
 
     /* The font matrix has x and y "scale" components which we extract and
      * use as character scale values.
      */
     cairo_matrix_init (&scaled_font->logical_to_device,
 		       sc->xx, sc->yx, sc->xy, sc->yy, 0, 0);
 
     if (!scaled_font->preserve_axes) {
-	status = _cairo_matrix_compute_scale_factors (&scaled_font->logical_to_device,
+	status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device,
 						      &scaled_font->x_scale, &scaled_font->y_scale,
 						      TRUE);	/* XXX: Handle vertical text */
 	if (status)
 	    return status;
 
 	scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
                                                    scaled_font->y_scale);
 	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
@@ -254,20 +276,25 @@ static cairo_status_t
 _win32_scaled_font_create (LOGFONTW                   *logfont,
 			   HFONT                      face_hfont,
 			   cairo_font_face_t	      *font_face,
 			   const cairo_matrix_t       *font_matrix,
 			   const cairo_matrix_t       *ctm,
 			   const cairo_font_options_t *options,
 			   cairo_scaled_font_t       **font_out)
 {
+    HDC hdc;
     cairo_win32_scaled_font_t *f;
     cairo_matrix_t scale;
     cairo_status_t status;
 
+    hdc = _get_global_font_dc ();
+    if (hdc == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
     f = malloc (sizeof(cairo_win32_scaled_font_t));
     if (f == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     f->logfont = *logfont;
 
     /* We don't have any control over the hinting style or subpixel
      * order in the Win32 font API, so we ignore those parts of
@@ -358,127 +385,101 @@ static cairo_status_t
 _win32_scaled_font_set_identity_transform (HDC hdc)
 {
     if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY))
 	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform");
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static HDC
-_get_global_font_dc (void)
-{
-    static HDC hdc;
-
-    if (!hdc) {
-	hdc = CreateCompatibleDC (NULL);
-	if (!hdc) {
-	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
-	    return NULL;
-	}
-
-	if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
-	    _cairo_win32_print_gdi_error ("_get_global_font_dc");
-	    DeleteDC (hdc);
-	    return NULL;
-	}
-    }
-
-    return hdc;
-}
-
-static HFONT
-_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font)
+static cairo_status_t
+_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font,
+				     HFONT *hfont_out)
 {
     if (!scaled_font->scaled_hfont) {
 	LOGFONTW logfont = scaled_font->logfont;
 	logfont.lfHeight = -scaled_font->logical_size;
 	logfont.lfWidth = 0;
 	logfont.lfEscapement = 0;
 	logfont.lfOrientation = 0;
 	logfont.lfQuality = scaled_font->quality;
 
 	scaled_font->scaled_hfont = CreateFontIndirectW (&logfont);
-	if (!scaled_font->scaled_hfont) {
-	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont");
-	    return NULL;
-	}
+	if (!scaled_font->scaled_hfont)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont");
     }
 
-    return scaled_font->scaled_hfont;
+    *hfont_out = scaled_font->scaled_hfont;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static HFONT
+static cairo_status_t
 _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
-				       HDC                        hdc)
+				       HDC                        hdc,
+				       HFONT			 *hfont_out)
 {
-    if (!scaled_font->unscaled_hfont) {
+    if (scaled_font->unscaled_hfont == NULL) {
 	OUTLINETEXTMETRIC *otm;
 	unsigned int otm_size;
 	HFONT scaled_hfont;
 	LOGFONTW logfont;
-
-	scaled_hfont = _win32_scaled_font_get_scaled_hfont (scaled_font);
-	if (!scaled_hfont)
-	    return NULL;
+	cairo_status_t status;
 
-	if (!SelectObject (hdc, scaled_hfont)) {
-	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
-	    return NULL;
-	}
+	status = _win32_scaled_font_get_scaled_hfont (scaled_font,
+						      &scaled_hfont);
+	if (status)
+	    return status;
+
+	if (! SelectObject (hdc, scaled_hfont))
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
 
 	otm_size = GetOutlineTextMetrics (hdc, 0, NULL);
-	if (!otm_size) {
-	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
-	    return NULL;
-	}
+	if (! otm_size)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
 
 	otm = malloc (otm_size);
-	if (!otm) {
-	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	    return NULL;
-	}
+	if (otm == NULL)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	if (!GetOutlineTextMetrics (hdc, otm_size, otm)) {
-	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
+	if (! GetOutlineTextMetrics (hdc, otm_size, otm)) {
+	    status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
 	    free (otm);
-	    return NULL;
+	    return status;
 	}
 
 	scaled_font->em_square = otm->otmEMSquare;
 	free (otm);
 
 	logfont = scaled_font->logfont;
 	logfont.lfHeight = -scaled_font->em_square;
 	logfont.lfWidth = 0;
 	logfont.lfEscapement = 0;
 	logfont.lfOrientation = 0;
 	logfont.lfQuality = scaled_font->quality;
 
 	scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont);
-	if (!scaled_font->unscaled_hfont) {
-	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");
-	    return NULL;
-	}
+	if (! scaled_font->unscaled_hfont)
+	    return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");
     }
 
-    return scaled_font->unscaled_hfont;
+    *hfont_out = scaled_font->unscaled_hfont;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
 					       HDC                  hdc)
 {
     cairo_status_t status;
     HFONT hfont;
     HFONT old_hfont = NULL;
 
-    hfont = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc);
-    if (!hfont)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont);
+    if (status)
+	return status;
 
     old_hfont = SelectObject (hdc, hfont);
     if (!old_hfont)
 	return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
 
     status = _win32_scaled_font_set_identity_transform (hdc);
     if (status) {
 	SelectObject (hdc, old_hfont);
@@ -610,36 +611,33 @@ static cairo_int_status_t
 					       const char	         *utf8,
 					       cairo_glyph_t            **glyphs,
 					       int		         *num_glyphs)
 {
     uint16_t *utf16;
     int n16;
     int i;
     WORD *glyph_indices = NULL;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     double x_pos, y_pos;
     HDC hdc = NULL;
     cairo_matrix_t mat;
 
     status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
     if (status)
 	return status;
 
     glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
     if (!glyph_indices) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL1;
     }
 
     hdc = _get_global_font_dc ();
-    if (!hdc) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL2;
-    }
+    assert (hdc != NULL);
 
     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
     if (status)
 	goto FAIL2;
 
     if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
 	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
 	goto FAIL2;
@@ -650,17 +648,18 @@ static cairo_int_status_t
     if (!*glyphs) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL2;
     }
 
     x_pos = x;
     y_pos = y;
     mat = scaled_font->base.ctm;
-    cairo_matrix_invert (&mat);
+    status = cairo_matrix_invert (&mat);
+    assert (status == CAIRO_STATUS_SUCCESS);
     for (i = 0; i < n16; i++) {
 	cairo_scaled_glyph_t *scaled_glyph;
 
 	(*glyphs)[i].index = glyph_indices[i];
 	(*glyphs)[i].x = x_pos;
 	(*glyphs)[i].y = y_pos;
 
 	status = _cairo_scaled_glyph_lookup (&scaled_font->base,
@@ -699,17 +698,17 @@ static cairo_int_status_t
 {
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     uint16_t *utf16;
     int n16;
     GCP_RESULTSW gcp_results;
     unsigned int buffer_size, i;
     WCHAR *glyph_indices = NULL;
     int *dx = NULL;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     double x_pos, y_pos;
     double x_incr, y_incr;
     HDC hdc = NULL;
 
     /* GetCharacterPlacement() returns utf16 instead of glyph indices
      * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
     if (scaled_font->is_type1)
 	 return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
@@ -738,20 +737,17 @@ static cairo_int_status_t
 
     buffer_size = MAX (n16 * 1.2, 16);		/* Initially guess number of chars plus a few */
     if (buffer_size > INT_MAX) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto FAIL1;
     }
 
     hdc = _get_global_font_dc ();
-    if (!hdc) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL1;
-    }
+    assert (hdc != NULL);
 
     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
     if (status)
 	goto FAIL1;
 
     while (TRUE) {
 	if (glyph_indices) {
 	    free (glyph_indices);
@@ -781,17 +777,17 @@ static cairo_int_status_t
 	    goto FAIL2;
 	}
 
 	if (gcp_results.lpDx && gcp_results.lpGlyphs)
 	    break;
 
 	/* Too small a buffer, try again */
 
-	buffer_size *= 1.5;
+	buffer_size += buffer_size / 2;
 	if (buffer_size > INT_MAX) {
 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    goto FAIL2;
 	}
     }
 
     *num_glyphs = gcp_results.nGlyphs;
     *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
@@ -821,28 +817,56 @@ static cairo_int_status_t
     cairo_win32_scaled_font_done_font (&scaled_font->base);
 
  FAIL1:
     free (utf16);
 
     return status;
 }
 
+static unsigned long
+_cairo_win32_scaled_font_ucs4_to_index (void		*abstract_font,
+					uint32_t	 ucs4)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    wchar_t unicode[2];
+    WORD glyph_index;
+    HDC hdc = NULL;
+    cairo_status_t status;
+
+    hdc = _get_global_font_dc ();
+    assert (hdc != NULL);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return 0;
+
+    unicode[0] = ucs4;
+    unicode[1] = 0;
+    if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
+	_cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW");
+	glyph_index = 0;
+    }
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return glyph_index;
+}
+
 static cairo_status_t
 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
 {
     cairo_status_t status;
     cairo_font_extents_t extents;
 
     TEXTMETRIC metrics;
     HDC hdc;
 
     hdc = _get_global_font_dc ();
-    if (!hdc)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    assert (hdc != NULL);
 
     if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) {
 	/* For 90-degree rotations (including 0), we get the metrics
 	 * from the GDI in logical space, then convert back to font space
 	 */
 	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
 	if (status)
 	    return status;
@@ -907,56 +931,61 @@ static cairo_status_t
 {
     static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
     GLYPHMETRICS metrics;
     cairo_status_t status;
     cairo_text_extents_t extents;
     HDC hdc;
 
     hdc = _get_global_font_dc ();
-    if (!hdc)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    assert (hdc != NULL);
 
     if (scaled_font->is_bitmap) {
 	/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
 	cairo_font_extents_t font_extents;
 	INT width = 0;
 	UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
 
 	cairo_scaled_font_extents (&scaled_font->base, &font_extents);
 
 	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-	if (!status) {
-	    if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
-		status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
-		width = 0;
-	    }
+	if (status)
+	    return status;
+
+	if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
+	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
+	    width = 0;
 	}
 	cairo_win32_scaled_font_done_font (&scaled_font->base);
+	if (status)
+	    return status;
 
 	extents.x_bearing = 0;
 	extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale);
 	extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale);
 	extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
 	extents.x_advance = extents.width;
 	extents.y_advance = 0;
     } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) {
 	/* If we aren't rotating / skewing the axes, then we get the metrics
 	 * from the GDI in device space and convert to font space.
 	 */
 	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
 	if (status)
 	    return status;
+
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
 			      GGO_METRICS | GGO_GLYPH_INDEX,
 			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
 	  status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
 	  memset (&metrics, 0, sizeof (GLYPHMETRICS));
 	}
 	cairo_win32_scaled_font_done_font (&scaled_font->base);
+	if (status)
+	    return status;
 
 	if (scaled_font->swap_axes) {
 	    extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
 	    extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
 	    extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;
 	    extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;
 	    extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;
 	    extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;
@@ -979,23 +1008,28 @@ static cairo_status_t
 	    extents.y_advance = - extents.y_advance;
 	}
 
     } else {
 	/* For all other transformations, we use the design metrics
 	 * of the font.
 	 */
 	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
+	if (status)
+	    return status;
+
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
 	                      GGO_METRICS | GGO_GLYPH_INDEX,
 			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
 	  status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
 	  memset (&metrics, 0, sizeof (GLYPHMETRICS));
 	}
 	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
+	if (status)
+	    return status;
 
 	extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
 	extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
 	extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
 	extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
 	extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
 	extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
     }
@@ -1019,23 +1053,23 @@ static cairo_status_t
 				     int                  num_glyphs,
 				     cairo_box_t         *bbox)
 {
     static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
 
     if (num_glyphs > 0) {
-	HDC hdc = _get_global_font_dc ();
+	HDC hdc;
 	GLYPHMETRICS metrics;
 	cairo_status_t status;
 	int i;
 
-	if (!hdc)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	hdc = _get_global_font_dc ();
+	assert (hdc != NULL);
 
 	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
 	if (status)
 	    return status;
 
 	for (i = 0; i < num_glyphs; i++) {
 	    int x = _cairo_lround (glyphs[i].x);
 	    int y = _cairo_lround (glyphs[i].y);
@@ -1159,37 +1193,40 @@ static cairo_status_t
 
     status = _cairo_array_append (&state->glyphs, &glyph_index);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 _finish_glyphs (cairo_glyph_state_t *state)
 {
-    /* ignore errors as we only call _finish_glyphs on the error path */
-    _flush_glyphs (state);
+    cairo_status_t status;
+
+    status = _flush_glyphs (state);
 
     _cairo_array_fini (&state->glyphs);
     _cairo_array_fini (&state->dx);
+
+    return status;
 }
 
 static cairo_status_t
 _draw_glyphs_on_surface (cairo_win32_surface_t     *surface,
 			 cairo_win32_scaled_font_t *scaled_font,
 			 COLORREF                   color,
 			 int                        x_offset,
 			 int                        y_offset,
 			 const cairo_glyph_t       *glyphs,
-			 int                 	    num_glyphs)
+			 int			    num_glyphs)
 {
     cairo_glyph_state_t state;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status, status2;
     int i;
 
     if (!SaveDC (surface->dc))
 	return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
 
     status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
     if (status)
 	goto FAIL1;
@@ -1203,17 +1240,20 @@ static cairo_status_t
     for (i = 0; i < num_glyphs; i++) {
 	status = _add_glyph (&state, glyphs[i].index,
 			     glyphs[i].x - x_offset, glyphs[i].y - y_offset);
 	if (status)
 	    goto FAIL2;
     }
 
  FAIL2:
-    _finish_glyphs (&state);
+    status2 = _finish_glyphs (&state);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
+
     cairo_win32_scaled_font_done_font (&scaled_font->base);
  FAIL1:
     RestoreDC (surface->dc, -1);
 
     return status;
 }
 
 /* Duplicate the green channel of a 4-channel mask in the alpha channel, then
@@ -1255,20 +1295,23 @@ static void
  */
 static cairo_surface_t *
 _compute_a8_mask (cairo_win32_surface_t *mask_surface)
 {
     cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
     cairo_image_surface_t *image8;
     int i, j;
 
+    if (image24->base.status)
+	return cairo_surface_reference (&image24->base);
+
     image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
 								  image24->width, image24->height);
     if (image8->base.status)
-	return NULL;
+	return &image8->base;
 
     for (i = 0; i < image24->height; i++) {
 	uint32_t *p = (uint32_t *) (image24->data + i * image24->stride);
 	unsigned char *q = (unsigned char *) (image8->data + i * image8->stride);
 
 	for (j = 0; j < image24->width; j++) {
 	    *q = 255 - ((*p & 0x0000ff00) >> 8);
 	    p++;
@@ -1397,18 +1440,19 @@ static cairo_int_status_t
 	    mask_surface = &tmp_surface->base;
 
 	    /* XXX: Hacky, should expose this in cairo_image_surface */
 	    pixman_image_set_component_alpha (((cairo_image_surface_t *)tmp_surface->image)->pixman_image, TRUE);
 
 	} else {
 	    mask_surface = _compute_a8_mask (tmp_surface);
 	    cairo_surface_destroy (&tmp_surface->base);
-	    if (!mask_surface)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    status = mask_surface->status;
+	    if (status)
+		return status;
 	}
 
 	/* For op == OVER, no-cleartype, a possible optimization here is to
 	 * draw onto an intermediate ARGB32 surface and alpha-blend that with the
 	 * destination
 	 */
 	_cairo_pattern_init_for_surface (&mask, mask_surface);
 
@@ -1430,55 +1474,53 @@ static cairo_int_status_t
 
 static cairo_int_status_t
 _cairo_win32_scaled_font_load_truetype_table (void	       *abstract_font,
                                              unsigned long      tag,
                                              long               offset,
                                              unsigned char     *buffer,
                                              unsigned long     *length)
 {
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
     HDC hdc;
     cairo_status_t status;
 
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
     hdc = _get_global_font_dc ();
-    if (!hdc)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    assert (hdc != NULL);
 
     tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
     if (status)
 	return status;
 
     *length = GetFontData (hdc, tag, offset, buffer, *length);
     if (*length == GDI_ERROR)
         status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     cairo_win32_scaled_font_done_font (&scaled_font->base);
 
     return status;
 }
 
-static cairo_status_t
-_cairo_win32_scaled_font_index_to_ucs4 (void 		*abstract_font,
+static cairo_int_status_t
+_cairo_win32_scaled_font_index_to_ucs4 (void		*abstract_font,
 					unsigned long    index,
 					uint32_t	*ucs4)
 {
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     GLYPHSET *glyph_set;
     uint16_t *utf16 = NULL;
     WORD *glyph_indices = NULL;
     HDC hdc = NULL;
     int res;
     unsigned int i, j, num_glyphs;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
 
     hdc = _get_global_font_dc ();
-    if (!hdc)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    assert (hdc != NULL);
 
     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
     if (status)
 	return status;
 
     res = GetFontUnicodeRanges(hdc, NULL);
     if (res == 0) {
 	status = _cairo_win32_print_gdi_error (
@@ -1548,17 +1590,17 @@ exit1:
 
     return status;
 }
 
 static cairo_status_t
 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
                                              cairo_scaled_glyph_t      *scaled_glyph)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     cairo_glyph_t glyph;
     cairo_win32_surface_t *surface;
     cairo_t *cr;
     cairo_surface_t *image;
     int width, height;
     int x1, y1, x2, y2;
 
     x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
@@ -1566,33 +1608,45 @@ static cairo_status_t
     x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
     y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
     width = x2 - x1;
     height = y2 - y1;
 
     surface = (cairo_win32_surface_t *)
 	cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
 
-    cr = cairo_create((cairo_surface_t *)surface);
+    cr = cairo_create (&surface->base);
     cairo_set_source_rgb (cr, 1, 1, 1);
     cairo_paint (cr);
+    status = cairo_status (cr);
     cairo_destroy(cr);
+    if (status)
+	goto FAIL;
 
     glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
     glyph.x = -x1;
     glyph.y = -y1;
     status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
                                       0, 0, &glyph, 1);
+    if (status)
+	goto FAIL;
+
     GdiFlush();
 
     image = _compute_a8_mask (surface);
-    cairo_surface_set_device_offset ((cairo_surface_t *)image, -x1, -y1);
+    status = image->status;
+    if (status)
+	goto FAIL;
+
+    cairo_surface_set_device_offset (image, -x1, -y1);
     _cairo_scaled_glyph_set_surface (scaled_glyph,
                                      &scaled_font->base,
-                                     (cairo_image_surface_t*)image);
+                                     (cairo_image_surface_t *) image);
+
+  FAIL:
     cairo_surface_destroy (&surface->base);
 
     return status;
 }
 
 static void
 _cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
                                        FIXED Fx, FIXED Fy,
@@ -1618,18 +1672,17 @@ static cairo_status_t
     cairo_path_fixed_t *path;
     cairo_matrix_t transform;
     cairo_fixed_t x, y;
 
     if (scaled_font->is_bitmap)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     hdc = _get_global_font_dc ();
-    if (!hdc)
-        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    assert (hdc != NULL);
 
     path = _cairo_path_fixed_create ();
     if (!path)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) {
         status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
         transform = scaled_font->base.scale;
@@ -1646,17 +1699,16 @@ static cairo_status_t
 				   &metrics, 0, NULL, &matrix);
 
     if (bytesGlyph == GDI_ERROR) {
 	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
 	goto CLEANUP_FONT;
     }
 
     ptr = buffer = malloc (bytesGlyph);
-
     if (!buffer) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto CLEANUP_FONT;
     }
 
     if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
 			  GGO_NATIVE | GGO_GLYPH_INDEX,
 			  &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
@@ -1775,18 +1827,18 @@ static cairo_status_t
     return status;
 }
 
 const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     CAIRO_FONT_TYPE_WIN32,
     _cairo_win32_scaled_font_create_toy,
     _cairo_win32_scaled_font_fini,
     _cairo_win32_scaled_font_glyph_init,
-    _cairo_win32_scaled_font_text_to_glyphs,
-    NULL,			/* ucs4_to_index */
+    NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
+    _cairo_win32_scaled_font_ucs4_to_index,
     _cairo_win32_scaled_font_show_glyphs,
     _cairo_win32_scaled_font_load_truetype_table,
     _cairo_win32_scaled_font_index_to_ucs4,
 };
 
 /* #cairo_win32_font_face_t */
 
 typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
@@ -1980,19 +2032,19 @@ cairo_win32_scaled_font_select_font (cai
 
     if (! _cairo_scaled_font_is_win32 (scaled_font)) {
 	return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
     }
 
     if (scaled_font->status)
 	return scaled_font->status;
 
-    hfont = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font);
-    if (!hfont)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont);
+    if (status)
+	return status;
 
     old_hfont = SelectObject (hdc, hfont);
     if (!old_hfont)
 	return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
 
     old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
     if (!old_mode) {
 	status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
--- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
@@ -46,16 +46,17 @@
 
 #include "cairoint.h"
 
 #include "cairo-paginated-private.h"
 
 #include "cairo-clip-private.h"
 #include "cairo-win32-private.h"
 #include "cairo-meta-surface-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <windows.h>
 
 #if !defined(POSTSCRIPT_IDENTIFY)
 # define POSTSCRIPT_IDENTIFY 0x1015
 #endif
 
 #if !defined(PSIDENT_GDICENTRIC)
@@ -1308,26 +1309,24 @@ static cairo_int_status_t
 
     if (op == CAIRO_OPERATOR_CLEAR) {
 	_cairo_win32_printing_surface_init_clear_color (surface, &clear);
 	source = (cairo_pattern_t*) &clear;
 	op = CAIRO_OPERATOR_SOURCE;
     }
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
-	/* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1 or
-	 * bitmap font on a printer DC prints garbled text. The text
-	 * displays correctly on a display DC. It appears that when
-	 * using a printer DC. ExtTextOutW() only works with
-	 * characters and not glyph indices.
+	/* When printing bitmap fonts to a printer DC, Windows may
+	 * substitute an outline font for bitmap font. As the win32
+	 * font backend always uses a screen DC when obtaining the
+	 * font metrics the metrics of the substituted font will not
+	 * match the metrics that the win32 font backend returns.
 	 *
-	 * For now we don't use ExtTextOutW for Type 1 or bitmap
-	 * fonts. These fonts will go through the fallback path for
-	 * non Windows fonts. ie filled outlines for Type 1 fonts and
-	 * fallback images for bitmap fonts.
+	 * If we are printing a bitmap font, use fallback images to
+	 * ensure the font is not substituted.
 	 */
 	if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
 	    if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 	    else
 		return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
 	}
 
@@ -1359,20 +1358,56 @@ static cairo_int_status_t
 					   GetGValue (color) / 255.0,
 					   GetBValue (color) / 255.0);
 	if (opaque->status)
 	    return opaque->status;
 	source = opaque;
     }
 
     if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
-	! _cairo_win32_scaled_font_is_type1 (scaled_font) &&
 	source->type == CAIRO_PATTERN_TYPE_SOLID)
     {
 	cairo_matrix_t ctm;
+	cairo_glyph_t  *type1_glyphs = NULL;
+	cairo_scaled_font_subsets_glyph_t subset_glyph;
+
+	/* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1
+	 * font on a printer DC prints garbled text. The text displays
+	 * correctly on a display DC. When using a printer
+	 * DC, ExtTextOutW() only works with characters and not glyph
+	 * indices.
+	 *
+	 * For Type 1 fonts the glyph indices are converted back to
+	 * unicode characters before calling _cairo_win32_surface_show_glyphs().
+	 *
+	 * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
+	 * operation, the font subsetting function
+	 * _cairo_scaled_font_subsets_map_glyph() is used to obtain
+	 * the unicode value because it caches the reverse mapping in
+	 * the subsets.
+	 */
+	if (_cairo_win32_scaled_font_is_type1 (scaled_font)) {
+	    type1_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	    if (type1_glyphs == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	    memcpy (type1_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+	    for (i = 0; i < num_glyphs; i++) {
+		status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+							       scaled_font,
+							       type1_glyphs[i].index,
+							       NULL, 0,
+							       &subset_glyph);
+		if (status)
+		    return status;
+
+		type1_glyphs[i].index = subset_glyph.unicode;
+	    }
+	    glyphs = type1_glyphs;
+	}
 
 	if (surface->has_ctm) {
 	    for (i = 0; i < num_glyphs; i++)
 		cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y);
 	    cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm);
 	    scaled_font = cairo_scaled_font_create (scaled_font->font_face,
 						    &scaled_font->font_matrix,
 						    &ctm,
@@ -1380,16 +1415,19 @@ static cairo_int_status_t
 	}
 	status = _cairo_win32_surface_show_glyphs (surface, op,
 						   source, glyphs,
 						   num_glyphs, scaled_font,
 						   remaining_glyphs);
 	if (surface->has_ctm)
 	    cairo_scaled_font_destroy (scaled_font);
 
+	if (type1_glyphs != NULL)
+	    free (type1_glyphs);
+
 	return status;
     }
 
     SaveDC (surface->dc);
     old_ctm = surface->ctm;
     old_has_ctm = surface->has_ctm;
     surface->has_ctm = TRUE;
     surface->path_empty = TRUE;
@@ -1526,16 +1564,21 @@ cairo_win32_printing_surface_create (HDC
     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
 
     surface->dc = hdc;
     surface->bitmap = NULL;
     surface->is_dib = FALSE;
     surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
+    surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
+    if (surface->font_subsets == NULL) {
+	free (surface);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
 
     GetClipBox(hdc, &rect);
     surface->extents.x = rect.left;
     surface->extents.y = rect.top;
     surface->extents.width = rect.right - rect.left;
     surface->extents.height = rect.bottom - rect.top;
 
     surface->flags = _cairo_win32_flags_for_dc (surface->dc);
--- a/gfx/cairo/cairo/src/cairo-win32-private.h
+++ b/gfx/cairo/cairo/src/cairo-win32-private.h
@@ -87,16 +87,17 @@ typedef struct _cairo_win32_surface {
 
     /* printing surface bits */
     cairo_paginated_mode_t paginated_mode;
     cairo_content_t content;
     cairo_bool_t path_empty;
     cairo_bool_t has_ctm;
     cairo_matrix_t ctm;
     HBRUSH brush, old_brush;
+    cairo_scaled_font_subsets_t *font_subsets;
 } cairo_win32_surface_t;
 
 /* Surface DC flag values */
 enum {
     /* If this is a surface created for printing or not */
     CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
 
     /* Whether the DC is a display DC or not */
--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
@@ -45,16 +45,17 @@
 # define _WIN32_WINNT 0x0500
 #endif
 
 #include "cairoint.h"
 
 #include "cairo-clip-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-win32-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <windows.h>
 
 #if defined(__MINGW32__) && !defined(ETO_PDY)
 # define ETO_PDY 0x2000
 #endif
 
 #undef DEBUG_COMPOSITE
@@ -354,16 +355,17 @@ static cairo_surface_t *
     surface->clip_rect.y = 0;
     surface->clip_rect.width = width;
     surface->clip_rect.height = height;
 
     surface->initial_clip_rgn = NULL;
     surface->had_simple_clip = FALSE;
 
     surface->extents = surface->clip_rect;
+    surface->font_subsets = NULL;
 
     _cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
 			 _cairo_content_from_format (format));
 
     return &surface->base;
 
  FAIL:
     if (surface->bitmap) {
@@ -492,16 +494,19 @@ cairo_status_t
 	DeleteDC (surface->dc);
     } else {
 	_cairo_win32_restore_initial_clip (surface);
     }
 
     if (surface->initial_clip_rgn)
 	DeleteObject (surface->initial_clip_rgn);
 
+    if (surface->font_subsets != NULL)
+	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
 				   int                     x,
 				   int                     y,
 				   int                     width,
@@ -1573,16 +1578,17 @@ cairo_int_status_t
     cairo_solid_pattern_t *solid_pattern;
     COLORREF color;
 
     cairo_matrix_t device_to_logical;
 
     int start_x, start_y;
     double user_x, user_y;
     int logical_x, logical_y;
+    unsigned int glyph_index_option;
 
     /* We can only handle win32 fonts */
     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* We can only handle opaque solid color sources */
     if (!_cairo_pattern_is_opaque_solid(source))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1658,20 +1664,34 @@ cairo_int_status_t
             dxy_buf[j] = _cairo_lround (next_logical_x - logical_x);
             dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y);
 
             logical_x = next_logical_x;
             logical_y = next_logical_y;
         }
     }
 
+    /* Using glyph indices for a Type 1 font does not work on a
+     * printer DC. The win32 printing surface will convert the the
+     * glyph indices of Type 1 fonts to the unicode values.
+     */
+    if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) &&
+	_cairo_win32_scaled_font_is_type1 (scaled_font))
+    {
+	glyph_index_option = 0;
+    }
+    else
+    {
+	glyph_index_option = ETO_GLYPH_INDEX;
+    }
+
     win_result = ExtTextOutW(dst->dc,
                              start_x,
                              start_y,
-                             ETO_GLYPH_INDEX | ETO_PDY,
+                             glyph_index_option | ETO_PDY,
                              NULL,
                              glyph_buf,
                              num_glyphs,
                              dxy_buf);
     if (!win_result) {
         _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
     }
 
@@ -1726,16 +1746,17 @@ cairo_win32_surface_create (HDC hdc)
     surface->format = format;
 
     surface->dc = hdc;
     surface->bitmap = NULL;
     surface->is_dib = FALSE;
     surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
+    surface->font_subsets = NULL;
 
     GetClipBox(hdc, &rect);
     surface->extents.x = rect.left;
     surface->extents.y = rect.top;
     surface->extents.width = rect.right - rect.left;
     surface->extents.height = rect.bottom - rect.top;
 
     surface->flags = _cairo_win32_flags_for_dc (surface->dc);
--- a/gfx/cairo/cairo/src/cairo-xlib-display.c
+++ b/gfx/cairo/cairo/src/cairo-xlib-display.c
@@ -24,16 +24,18 @@
  * 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):
+ *	Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
  */
 
 #include "cairoint.h"
 
 #include "cairo-xlib-private.h"
 #include "cairo-xlib-xrender-private.h"
 
 #include <fontconfig/fontconfig.h>
@@ -62,49 +64,41 @@ struct _cairo_xlib_job {
     } func;
 };
 
 static cairo_xlib_display_t *_cairo_xlib_display_list;
 
 static int buggy_repeat_force = -1;
 
 static void
+_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
+						cairo_xlib_hook_t *hook);
+
+static void
 _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
 {
     cairo_xlib_screen_info_t	    *screen;
-    cairo_xlib_hook_t		    *hooks, *list;
+    cairo_xlib_hook_t		    *hook;
 
     /* call all registered shutdown routines */
     CAIRO_MUTEX_LOCK (display->mutex);
 
     for (screen = display->screens; screen != NULL; screen = screen->next)
 	_cairo_xlib_screen_info_close_display (screen);
 
-    hooks = display->close_display_hooks;
-    while (hooks != NULL) {
-	display->close_display_hooks = NULL;
-	CAIRO_MUTEX_UNLOCK (display->mutex);
-
-	list = hooks;
-	do {
-	    cairo_xlib_hook_t *hook = list;
-	    list = hook->next;
+    while (TRUE) {
+	hook = display->close_display_hooks;
+	if (hook == NULL)
+	    break;
 
-	    hook->func (display->display, hook->data);
-	} while (list != NULL);
+	_cairo_xlib_remove_close_display_hook_internal (display, hook);
 
+	CAIRO_MUTEX_UNLOCK (display->mutex);
+	hook->func (display, hook);
 	CAIRO_MUTEX_LOCK (display->mutex);
-	do {
-	    cairo_xlib_hook_t *hook = hooks;
-	    hooks = hook->next;
-
-	    _cairo_freelist_free (&display->hook_freelist, hook);
-	} while (hooks != NULL);
-
-	hooks = display->close_display_hooks;
     }
     display->closed = TRUE;
 
     CAIRO_MUTEX_UNLOCK (display->mutex);
 }
 
 static void
 _cairo_xlib_display_discard_screens (cairo_xlib_display_t *display)
@@ -148,17 +142,16 @@ void
 	display->workqueue = job->next;
 
 	if (job->type == WORK && job->func.work.destroy != NULL)
 	    job->func.work.destroy (job->func.work.data);
 
 	_cairo_freelist_free (&display->wq_freelist, job);
     }
     _cairo_freelist_fini (&display->wq_freelist);
-    _cairo_freelist_fini (&display->hook_freelist);
 
     CAIRO_MUTEX_FINI (display->mutex);
 
     free (display);
 }
 
 static int
 _noop_error_handler (Display     *display,
@@ -274,17 +267,16 @@ cairo_xlib_display_t *
 	free (display);
 	display = NULL;
 	goto UNLOCK;
     }
 
     XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
 
     _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t));
-    _cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t));
 
     CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */
     CAIRO_MUTEX_INIT (display->mutex);
     display->display = dpy;
     display->screens = NULL;
     display->workqueue = NULL;
     display->close_display_hooks = NULL;
     display->closed = FALSE;
@@ -333,71 +325,53 @@ cairo_xlib_display_t *
     display->next = _cairo_xlib_display_list;
     _cairo_xlib_display_list = display;
 
 UNLOCK:
     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
     return display;
 }
 
-cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, const void *key)
+void
+_cairo_xlib_add_close_display_hook (cairo_xlib_display_t	*display,
+				    cairo_xlib_hook_t		*hook)
 {
-    cairo_xlib_display_t *display;
-    cairo_xlib_hook_t *hook;
-    cairo_bool_t ret = FALSE;
-
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return FALSE;
-
     CAIRO_MUTEX_LOCK (display->mutex);
-    if (display->closed == FALSE) {
-	hook = _cairo_freelist_alloc (&display->hook_freelist);
-	if (hook != NULL) {
-	    hook->func = func;
-	    hook->data = data;
-	    hook->key = key;
+    hook->prev = NULL;
+    hook->next = display->close_display_hooks;
+    if (hook->next != NULL)
+	hook->next->prev = hook;
+    display->close_display_hooks = hook;
+    CAIRO_MUTEX_UNLOCK (display->mutex);
+}
 
-	    hook->next = display->close_display_hooks;
-	    display->close_display_hooks = hook;
-	    ret = TRUE;
-	}
-    }
-    CAIRO_MUTEX_UNLOCK (display->mutex);
+/* display->mutex must be held */
+static void
+_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
+						cairo_xlib_hook_t *hook)
+{
+    if (display->close_display_hooks == hook)
+	display->close_display_hooks = hook->next;
+    else if (hook->prev != NULL)
+	hook->prev->next = hook->next;
 
-    _cairo_xlib_display_destroy (display);
+    if (hook->next != NULL)
+	hook->next->prev = hook->prev;
 
-    return ret;
+    hook->prev = NULL;
+    hook->next = NULL;
 }
 
 void
-_cairo_xlib_remove_close_display_hooks (Display *dpy, const void *key)
+_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t	*display,
+				       cairo_xlib_hook_t	*hook)
 {
-    cairo_xlib_display_t *display;
-    cairo_xlib_hook_t *hook, *next, **prev;
-
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return;
-
     CAIRO_MUTEX_LOCK (display->mutex);
-    prev = &display->close_display_hooks;
-    for (hook = display->close_display_hooks; hook != NULL; hook = next) {
-	next = hook->next;
-	if (hook->key == key) {
-	    *prev = hook->next;
-	    _cairo_freelist_free (&display->hook_freelist, hook);
-	} else
-	    prev = &hook->next;
-    }
-    *prev = NULL;
+    _cairo_xlib_remove_close_display_hook_internal (display, hook);
     CAIRO_MUTEX_UNLOCK (display->mutex);
-
-    _cairo_xlib_display_destroy (display);
 }
 
 cairo_status_t
 _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
 	                            cairo_xlib_notify_resource_func notify,
 				    XID xid)
 {
     cairo_xlib_job_t *job;
--- a/gfx/cairo/cairo/src/cairo-xlib-private.h
+++ b/gfx/cairo/cairo/src/cairo-xlib-private.h
@@ -23,16 +23,20 @@
  *
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributors(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ *	Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
  */
 
 #ifndef CAIRO_XLIB_PRIVATE_H
 #define CAIRO_XLIB_PRIVATE_H
 
 #include "cairo-xlib.h"
 #include "cairo-xlib-xrender-private.h"
 
@@ -43,36 +47,33 @@
 
 typedef struct _cairo_xlib_display cairo_xlib_display_t;
 typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
 typedef struct _cairo_xlib_job cairo_xlib_job_t;
 typedef void (*cairo_xlib_notify_func) (Display *, void *);
 typedef void (*cairo_xlib_notify_resource_func) (Display *, XID);
 
 struct _cairo_xlib_hook {
-    cairo_xlib_hook_t *next;
-    void (*func) (Display *display, void *data);
-    void *data;
-    const void *key;
+    cairo_xlib_hook_t *prev, *next; /* private */
+    void (*func) (cairo_xlib_display_t *display, void *data);
 };
 
 struct _cairo_xlib_display {
     cairo_xlib_display_t *next;
     cairo_reference_count_t ref_count;
     cairo_mutex_t mutex;
 
     Display *display;
     cairo_xlib_screen_info_t *screens;
 
     XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_A1 + 1];
 
     cairo_xlib_job_t *workqueue;
     cairo_freelist_t wq_freelist;
 
-    cairo_freelist_t hook_freelist;
     cairo_xlib_hook_t *close_display_hooks;
     unsigned int buggy_repeat :1;
     unsigned int closed :1;
 };
 
 /* size of color cube */
 #define CUBE_SIZE 6
 /* size of gray ramp */
@@ -107,20 +108,21 @@ struct _cairo_xlib_screen_info {
 cairo_private cairo_xlib_display_t *
 _cairo_xlib_display_get (Display *display);
 
 cairo_private cairo_xlib_display_t *
 _cairo_xlib_display_reference (cairo_xlib_display_t *info);
 cairo_private void
 _cairo_xlib_display_destroy (cairo_xlib_display_t *info);
 
-cairo_private cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, const void *key);
 cairo_private void
-_cairo_xlib_remove_close_display_hooks (Display *display, const void *key);
+_cairo_xlib_add_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook);
+
+cairo_private void
+_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook);
 
 cairo_private cairo_status_t
 _cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
 	                        cairo_xlib_notify_func notify,
 				void *data,
 				void (*destroy)(void *));
 cairo_private cairo_status_t
 _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
@@ -129,17 +131,17 @@ cairo_private cairo_status_t
 cairo_private void
 _cairo_xlib_display_notify (cairo_xlib_display_t *display);
 
 cairo_private XRenderPictFormat *
 _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t	*display,
 	                                cairo_format_t		 format);
 
 cairo_private cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (Display *display, Screen *screen);
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen);
 
 cairo_private cairo_xlib_screen_info_t *
 _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
 cairo_private void
 _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info);
 
 cairo_private void
 _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
--- a/gfx/cairo/cairo/src/cairo-xlib-screen.c
+++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c
@@ -101,56 +101,76 @@ get_boolean_default (Display       *dpy,
     return FALSE;
 }
 
 static cairo_bool_t
 get_integer_default (Display    *dpy,
 		     const char *option,
 		     int        *value)
 {
-    int i;
     char *v, *e;
 
     v = XGetDefault (dpy, "Xft", option);
     if (v) {
 #if CAIRO_HAS_FT_FONT
 	if (FcNameConstant ((FcChar8 *) v, value))
 	    return TRUE;
 #endif
 
-	i = strtol (v, &e, 0);
+	*value = strtol (v, &e, 0);
 	if (e != v)
 	    return TRUE;
     }
 
     return FALSE;
 }
 
 /* Old versions of fontconfig didn't have these options */
 #ifndef FC_HINT_NONE
 #define FC_HINT_NONE        0
 #define FC_HINT_SLIGHT      1
 #define FC_HINT_MEDIUM      2
 #define FC_HINT_FULL        3
 #endif
 
+/* Fontconfig version older than 2.6 didn't have these options */
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER	"lcdfilter"
+#endif
+/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE	0
+#define FC_LCD_DEFAULT	1
+#define FC_LCD_LIGHT	2
+#define FC_LCD_LEGACY	3
+#endif
+
 static void
 _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
 {
     cairo_bool_t xft_hinting;
     cairo_bool_t xft_antialias;
     int xft_hintstyle;
     int xft_rgba;
+    int xft_lcdfilter;
     cairo_antialias_t antialias;
     cairo_subpixel_order_t subpixel_order;
+    cairo_lcd_filter_t lcd_filter;
     cairo_hint_style_t hint_style;
 
     if (!get_boolean_default (dpy, "antialias", &xft_antialias))
 	xft_antialias = TRUE;
 
+    if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
+	/* -1 is an non-existant Fontconfig constant used to differentiate
+	 * the case when no lcdfilter property is available.
+	 */
+	xft_lcdfilter = -1;
+    }
+
     if (!get_boolean_default (dpy, "hinting", &xft_hinting))
 	xft_hinting = TRUE;
 
     if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
 	xft_hintstyle = FC_HINT_FULL;
 
     if (!get_integer_default (dpy, "rgba", &xft_rgba))
     {
@@ -223,28 +243,47 @@ static void
 	subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
 	break;
     case FC_RGBA_UNKNOWN:
     case FC_RGBA_NONE:
     default:
 	subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
     }
 
+    switch (xft_lcdfilter) {
+    case FC_LCD_NONE:
+	lcd_filter = CAIRO_LCD_FILTER_NONE;
+	break;
+    case FC_LCD_DEFAULT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR5;
+	break;
+    case FC_LCD_LIGHT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR3;
+	break;
+    case FC_LCD_LEGACY:
+	lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+	break;
+    default:
+	lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
+	break;
+    }
+
     if (xft_antialias) {
 	if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
 	    antialias = CAIRO_ANTIALIAS_GRAY;
 	else
 	    antialias = CAIRO_ANTIALIAS_SUBPIXEL;
     } else {
 	antialias = CAIRO_ANTIALIAS_NONE;
     }
 
     cairo_font_options_set_hint_style (&info->font_options, hint_style);
     cairo_font_options_set_antialias (&info->font_options, antialias);
     cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
+    cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
     cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
 }
 
 cairo_xlib_screen_info_t *
 _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
 {
     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
 
@@ -302,29 +341,24 @@ void
     _cairo_array_fini (&info->visuals);
 
     CAIRO_MUTEX_FINI (info->mutex);
 
     free (info);
 }
 
 cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
 {
-    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *info = NULL, **prev;
 
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return NULL;
-
     CAIRO_MUTEX_LOCK (display->mutex);
     if (display->closed) {
 	CAIRO_MUTEX_UNLOCK (display->mutex);
-	goto DONE;
+	return NULL;
     }
 
     for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
 	if (info->screen == screen) {
 	    /*
 	     * MRU the list
 	     */
 	    if (prev != &display->screens) {
@@ -350,32 +384,31 @@ cairo_xlib_screen_info_t *
 	    _cairo_font_options_init_default (&info->font_options);
 	    memset (info->gc, 0, sizeof (info->gc));
 	    info->gc_needs_clip_reset = 0;
 
 	    _cairo_array_init (&info->visuals,
 			       sizeof (cairo_xlib_visual_info_t*));
 
 	    if (screen) {
+		Display *dpy = display->display;
 		int event_base, error_base;
+
 		info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
 			(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
 		_cairo_xlib_init_screen_font_options (dpy, info);
 	    }
 
 	    CAIRO_MUTEX_LOCK (display->mutex);
 	    info->next = display->screens;
 	    display->screens = info;
 	    CAIRO_MUTEX_UNLOCK (display->mutex);
 	}
     }
 
-DONE:
-    _cairo_xlib_display_destroy (display);
-
     return info;
 }
 
 static int
 depth_to_index (int depth)
 {
     switch(depth){
 	case 1:  return 1;
--- a/gfx/cairo/cairo/src/cairo-xlib-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-xlib-surface-private.h
@@ -40,17 +40,19 @@
 #include "cairo-surface-private.h"
 
 typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
 
 struct _cairo_xlib_surface {
     cairo_surface_t base;
 
     Display *dpy;
+    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *screen_info;
+    cairo_xlib_hook_t close_display_hook;
 
     GC gc;
     Drawable drawable;
     Screen *screen;
     cairo_bool_t owns_pixmap;
     Visual *visual;
 
     int use_pixmap;
--- a/gfx/cairo/cairo/src/cairo-xlib-surface.c
+++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c
@@ -1,8 +1,9 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
  * Copyright © 2005 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
@@ -29,27 +30,31 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  *	Behdad Esfahbod <behdad@behdad.org>
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ *	Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
  */
 
 #include "cairoint.h"
 
 #include "cairo-xlib-private.h"
 #include "cairo-xlib-surface-private.h"
 #include "cairo-clip-private.h"
 #include "cairo-scaled-font-private.h"
 
 #include <X11/Xutil.h> /* for XDestroyImage */
 
+#define XLIB_COORD_MAX 32767
+
 /* Xlib doesn't define a typedef, so define one ourselves */
 typedef int (*cairo_xlib_error_func_t) (Display     *display,
 					XErrorEvent *event);
 
 static cairo_surface_t *
 _cairo_xlib_surface_create_internal (Display		       *dpy,
 				     Drawable		        drawable,
 				     Screen		       *screen,
@@ -125,16 +130,19 @@ static cairo_surface_t *
 						int		height)
 {
     cairo_xlib_surface_t *src = abstract_src;
     Display *dpy = src->dpy;
     Pixmap pix;
     cairo_xlib_surface_t *surface;
     XRenderPictFormat *xrender_format;
 
+    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
+	return NULL;
+
     /* As a good first approximation, if the display doesn't have even
      * the most elementary RENDER operation, then we're better off
      * using image surfaces for all temporary operations, so return NULL
      * and let the fallback code happen.
      */
     if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
 	return NULL;
 
@@ -195,16 +203,19 @@ static cairo_surface_t *
 				    int			width,
 				    int			height)
 {
     cairo_xlib_surface_t *src = abstract_src;
     XRenderPictFormat *xrender_format = src->xrender_format;
     cairo_xlib_surface_t *surface;
     Pixmap pix;
 
+    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
+	return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY));
+
     _cairo_xlib_display_notify (src->screen_info->display);
 
     /* Start by examining the surface's XRenderFormat, or if it
      * doesn't have one, then look one up through its visual (in the
      * case of a bitmap, it won't even have that). */
     if (xrender_format == NULL && src->visual != NULL)
         xrender_format = XRenderFindVisualFormat (src->dpy, src->visual);
 
@@ -304,21 +315,24 @@ static cairo_status_t
     }
 
     if (surface->clip_rects != surface->embedded_clip_rects)
 	free (surface->clip_rects);
 
     if (surface->screen_info != NULL)
 	_cairo_xlib_screen_info_destroy (surface->screen_info);
 
-    if (surface->dpy != NULL) {
-	_cairo_xlib_remove_close_display_hooks (surface->dpy, surface);
-	surface->dpy = NULL;
+    if (surface->display != NULL) {
+	_cairo_xlib_remove_close_display_hook (surface->display,
+					       &surface->close_display_hook);
+	_cairo_xlib_display_destroy (surface->display);
     }
 
+    surface->dpy = NULL;
+
     return status;
 }
 
 static int
 _noop_error_handler (Display     *display,
 		     XErrorEvent *event)
 {
     return False;		/* return value is ignored */
@@ -632,19 +646,19 @@ static cairo_status_t
 	 * temporary pixmap
 	 */
 	Pixmap pixmap;
 	cairo_status_t status = _cairo_xlib_surface_ensure_gc (surface);
 	if (status)
 	    return status;
 
 	pixmap = XCreatePixmap (surface->dpy,
-				       surface->drawable,
-				       x2 - x1, y2 - y1,
-				       surface->depth);
+				surface->drawable,
+				x2 - x1, y2 - y1,
+				surface->depth);
 	if (pixmap) {
 	    XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
 		       x1, y1, x2 - x1, y2 - y1, 0, 0);
 
 	    ximage = XGetImage (surface->dpy,
 				pixmap,
 				0, 0,
 				x2 - x1, y2 - y1,
@@ -904,30 +918,36 @@ static cairo_status_t
     ximage.green_mask = surface->g_mask;
     ximage.blue_mask = surface->b_mask;
     ximage.xoffset = 0;
 
     if (image_masks.red_mask   == surface->r_mask &&
 	image_masks.green_mask == surface->g_mask &&
 	image_masks.blue_mask  == surface->b_mask)
     {
+	int ret;
+
 	ximage.bits_per_pixel = image_masks.bpp;
 	ximage.bytes_per_line = image->stride;
 	ximage.data = (char *)image->data;
 	own_data = FALSE;
-	XInitImage (&ximage);
+
+	ret = XInitImage (&ximage);
+	assert (ret != 0);
     } else {
 	unsigned int stride, rowstride;
 	int x, y, x0, y0, x_off, y_off;
 	uint32_t in_pixel, out_pixel, *row;
 	int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0;
 	int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0;
 	int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
 	int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
 	cairo_xlib_visual_info_t *visual_info = NULL;
+	cairo_bool_t true_color;
+	int ret;
 
 	if (surface->depth > 16) {
 	    ximage.bits_per_pixel = 32;
 	} else if (surface->depth > 8) {
 	    ximage.bits_per_pixel = 16;
 	} else if (surface->depth > 1) {
 	    ximage.bits_per_pixel = 8;
 	} else {
@@ -937,75 +957,80 @@ static cairo_status_t
 					     ximage.bits_per_pixel);
 	ximage.bytes_per_line = stride;
 	ximage.data = _cairo_malloc_ab (stride, ximage.height);
 	if (ximage.data == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	own_data = TRUE;
 
-	XInitImage (&ximage);
+	ret = XInitImage (&ximage);
+	assert (ret != 0);
 
 	_characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
 	_characterize_field (image_masks.red_mask  , &i_r_width, &i_r_shift);
 	_characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
 	_characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
 
-	if (surface->visual == NULL || surface->visual->class == TrueColor) {
-
+	true_color = surface->visual == NULL ||
+	             surface->visual->class == TrueColor;
+	if (true_color) {
 	    _characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
 	    _characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
 	    _characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
 	    _characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
-
 	} else {
-
 	    status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
 							 surface->visual,
 							 &visual_info);
 	    if (status)
 		goto BAIL;
-
 	}
 
 	rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
 	row = (uint32_t *) cairo_image_surface_get_data (&image->base);
 	x0 = dst_x + surface->base.device_transform.x0;
 	y0 = dst_y + surface->base.device_transform.y0;
 	for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
 	     y < ximage.height;
-	     y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
+	     y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
+	{
 	    const int8_t *dither_row = dither_pattern[y_off];
+
 	    for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
 		 x < ximage.width;
-		 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
+		 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
+	    {
 		int dither_adjustment = dither_row[x_off];
-
 		int a, r, g, b;
 
 		if (image_masks.bpp <= 8)
 		    in_pixel = ((uint8_t*)row)[x];
 		else if (image_masks.bpp <= 16)
 		    in_pixel = ((uint16_t*)row)[x];
 		else
 		    in_pixel = row[x];
+
 		a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
 		r = _field_to_8 (in_pixel & image_masks.red_mask  , i_r_width, i_r_shift);
 		g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
 		b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
-		if (surface->visual == NULL || surface->visual->class == TrueColor) {
-		    out_pixel = (_field_from_8        (a, o_a_width, o_a_shift) |
-				 _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
-				 _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
-				 _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment));
+
+		if (true_color) {
+		    out_pixel = _field_from_8        (a, o_a_width, o_a_shift) |
+				_field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
+				_field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
+				_field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
 		} else {
 		    out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
 		}
+
 		XPutPixel (&ximage, x, y, out_pixel);
 	    }
+
 	    row += rowstride;
 	}
     }
 
     status = _cairo_xlib_surface_ensure_gc (surface);
     if (status)
 	goto BAIL;
 
@@ -1126,16 +1151,19 @@ static cairo_status_t
 	    return CAIRO_STATUS_SUCCESS;
 	}
     } else if (_cairo_surface_is_image (src)) {
 	cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
 
 	if (! CAIRO_FORMAT_VALID (image_src->format))
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
+	if (image_src->width > XLIB_COORD_MAX || image_src->height > XLIB_COORD_MAX)
+	    return CAIRO_STATUS_NO_MEMORY;
+
 	clone = (cairo_xlib_surface_t *)
 	    _cairo_xlib_surface_create_similar_with_format (surface, image_src->format,
 						image_src->width, image_src->height);
 	if (clone == NULL)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	if (clone->base.status)
 	    return clone->base.status;
@@ -1167,53 +1195,58 @@ static cairo_surface_t *
      * _cairo_xlib_surface_solid_fill_rectangles() to do dithered "solid"
      * fills using core protocol */
 
     cairo_xlib_surface_t *other = abstract_surface;
     cairo_image_surface_t *image;
     cairo_xlib_surface_t *surface = NULL;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-    Pixmap pixmap;
+    int width = ARRAY_LENGTH (dither_pattern[0]);
+    int height = ARRAY_LENGTH (dither_pattern);
+
+    Pixmap pixmap = None;
 
     if (CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other))
 	return NULL;
 
+    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
+	return NULL;
+
     image = (cairo_image_surface_t *)
 	    _cairo_image_surface_create_with_content (solid_pattern->content,
-						      ARRAY_LENGTH (dither_pattern[0]),
-						      ARRAY_LENGTH (dither_pattern));
+						      width, height);
     status = image->base.status;
     if (status)
 	goto BAIL;
 
     pixmap = XCreatePixmap (other->dpy,
 			    other->drawable,
-			    image->width, image->height,
+			    width, height,
 			    other->depth);
 
     surface = (cairo_xlib_surface_t *)
 	      _cairo_xlib_surface_create_internal (other->dpy,
 						   pixmap,
 						   other->screen, other->visual,
-						   NULL,
-						   image->width, image->height,
-						   0);
+						   other->xrender_format,
+						   width, height,
+						   other->depth);
     status = surface->base.status;
     if (status)
 	goto BAIL;
     surface->owns_pixmap = TRUE;
 
     status = _cairo_surface_paint (&image->base, CAIRO_OPERATOR_SOURCE, &solid_pattern->base);
     if (status)
 	goto BAIL;
 
     status = _draw_image_surface (surface, image,
 				  0, 0,
-				  image->width, image->height,
+				  width, height,
 				  0, 0);
     if (status)
 	goto BAIL;
 
 
   BAIL:
     cairo_surface_destroy (&image->base);
 
@@ -1308,63 +1341,59 @@ static cairo_status_t
 
     XRenderSetPictureFilter (surface->dpy, surface->src_picture,
 			     (char *) render_filter, NULL, 0);
     surface->filter = filter;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+static void
 _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat)
 {
     XRenderPictureAttributes pa;
     unsigned long	     mask;
 
     if (!surface->src_picture)
-	return CAIRO_STATUS_SUCCESS;
+	return;
 
     if (surface->repeat == repeat)
-	return CAIRO_STATUS_SUCCESS;
+	return;
 
     mask = CPRepeat;
     pa.repeat = repeat;
 
     XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa);
     surface->repeat = repeat;
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t	    *surface,
 				    cairo_surface_attributes_t	    *attributes)
 {
     cairo_int_status_t status;
 
     _cairo_xlib_surface_ensure_src_picture (surface);
 
     status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix);
     if (status)
 	return status;
 
     switch (attributes->extend) {
     case CAIRO_EXTEND_NONE:
-	status = _cairo_xlib_surface_set_repeat (surface, 0);
+	_cairo_xlib_surface_set_repeat (surface, 0);
 	break;
     case CAIRO_EXTEND_REPEAT:
-	status = _cairo_xlib_surface_set_repeat (surface, 1);
+	_cairo_xlib_surface_set_repeat (surface, 1);
 	break;
     case CAIRO_EXTEND_REFLECT:
     case CAIRO_EXTEND_PAD:
     default:
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
-    if (status)
-	return status;
 
     status = _cairo_xlib_surface_set_filter (surface, attributes->filter);
     if (status)
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1882,22 +1911,27 @@ static Picture
 		    XRenderColor         *color,
 		    int                   width,
 		    int                   height,
 		    cairo_bool_t          repeat)
 {
     XRenderPictureAttributes pa;
     unsigned long mask = 0;
 
-    Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable,
-				   width <= 0 ? 1 : width,
-				   height <= 0 ? 1 : height,
-				   8);
+    Pixmap pixmap;
     Picture picture;
 
+    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
+	return None;
+
+    pixmap = XCreatePixmap (surface->dpy, surface->drawable,
+			    width <= 0 ? 1 : width,
+			    height <= 0 ? 1 : height,
+			    8);
+
     if (repeat) {
 	pa.repeat = TRUE;
 	mask = CPRepeat;
     }
 
     picture = XRenderCreatePicture (surface->dpy, pixmap,
 				    XRenderFindStandardFormat (surface->dpy, PictStandardA8),
 				    mask, &pa);
@@ -1930,17 +1964,17 @@ static Picture
     /* This would be considerably simpler using XRenderAddTraps(), but since
      * we are only using this in the unbounded-operator case, we stick with
      * XRenderCompositeTrapezoids, which is available on older versions
      * of RENDER rather than conditionalizing. We should still hit an
      * optimization that avoids creating another intermediate surface on
      * the servers that have XRenderAddTraps().
      */
     mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
-    if (num_traps == 0)
+    if (mask_picture == None || num_traps == 0)
 	return mask_picture;
 
     offset_traps = _cairo_malloc_ab (num_traps, sizeof (XTrapezoid));
     if (!offset_traps) {
 	XRenderFreePicture (dst->dpy, mask_picture);
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return None;
     }
@@ -2166,18 +2200,21 @@ static cairo_int_status_t
 	status = _cairo_region_intersect (&bounded, &bound, region);
 	if (status) {
 	    _cairo_region_fini (&bound);
 	    _cairo_region_fini (&bounded);
 	    return status;
 	}
 
 	status = _cairo_region_get_boxes (&bounded, &n_boxes, &boxes);
-        if (status)
-            return status;
+	if (status) {
+	    _cairo_region_fini (&bound);
+	    _cairo_region_fini (&bounded);
+	    return status;
+	}
 
 	if (n_boxes > ARRAY_LENGTH (surface->embedded_clip_rects)) {
 	    rects = _cairo_malloc_ab (n_boxes, sizeof (XRectangle));
 	    if (rects == NULL) {
                 _cairo_region_boxes_fini (&bounded, boxes);
 		_cairo_region_fini (&bound);
 		_cairo_region_fini (&bounded);
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2339,21 +2376,26 @@ static const cairo_surface_backend_t cai
  * Return value: True if the surface is an xlib surface
  **/
 static cairo_bool_t
 _cairo_surface_is_xlib (cairo_surface_t *surface)
 {
     return surface->backend == &cairo_xlib_surface_backend;
 }
 
+/* callback from CloseDisplay */
 static void
-_cairo_xlib_surface_detach_display (Display *dpy, void *data)
+_cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data)
 {
-    cairo_xlib_surface_t *surface = data;
-
+    cairo_xlib_surface_t *surface = cairo_container_of (data,
+							cairo_xlib_surface_t,
+							close_display_hook);
+    Display *dpy;
+
+    dpy = surface->dpy;
     surface->dpy = NULL;
 
     if (surface->dst_picture != None) {
 	XRenderFreePicture (dpy, surface->dst_picture);
 	surface->dst_picture = None;
     }
 
     if (surface->src_picture != None) {
@@ -2379,58 +2421,69 @@ static cairo_surface_t *
 				     Screen		       *screen,
 				     Visual		       *visual,
 				     XRenderPictFormat	       *xrender_format,
 				     int			width,
 				     int			height,
 				     int			depth)
 {
     cairo_xlib_surface_t *surface;
+    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *screen_info;
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    screen_info = _cairo_xlib_screen_info_get (dpy, screen);
-    if (screen_info == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    surface = malloc (sizeof (cairo_xlib_surface_t));
-    if (surface == NULL) {
-	_cairo_xlib_screen_info_destroy (screen_info);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    if (! _cairo_xlib_add_close_display_hook (dpy,
-	    _cairo_xlib_surface_detach_display, surface, surface)) {
-	free (surface);
-	_cairo_xlib_screen_info_destroy (screen_info);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
     if (xrender_format) {
 	depth = xrender_format->depth;
+
+	/* XXX find matching visual for core/dithering fallbacks? */
     } else if (visual) {
 	int j, k;
 
 	/* This is ugly, but we have to walk over all visuals
-	 * for the display to find the depth.
+	 * for the display to find the correct depth.
 	 */
+	depth = 0;
 	for (j = 0; j < screen->ndepths; j++) {
 	    Depth *d = &screen->depths[j];
 	    for (k = 0; k < d->nvisuals; k++) {
 		if (&d->visuals[k] == visual) {
 		    depth = d->depth;
 		    goto found;
 		}
 	    }
 	}
     found:
 	;
     }
 
+    if (depth == 0)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
+
+    display = _cairo_xlib_display_get (dpy);
+    if (display == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    screen_info = _cairo_xlib_screen_info_get (display, screen);
+    if (screen_info == NULL) {
+	_cairo_xlib_display_destroy (display);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    surface = malloc (sizeof (cairo_xlib_surface_t));
+    if (surface == NULL) {
+	_cairo_xlib_screen_info_destroy (screen_info);
+	_cairo_xlib_display_destroy (display);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    /* initialize and hook into the CloseDisplay callback */
+    surface->close_display_hook.func = _cairo_xlib_surface_detach_display;
+    _cairo_xlib_add_close_display_hook (display, &surface->close_display_hook);
+
     if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
 	surface->render_major = -1;
 	surface->render_minor = -1;
     }
 
     if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
 	if (!xrender_format) {
 	    if (visual)
@@ -2441,16 +2494,17 @@ static cairo_surface_t *
     } else {
 	xrender_format = NULL;
     }
 
     _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
 			 _xrender_format_to_content (xrender_format));
 
     surface->dpy = dpy;
+    surface->display = display;
     surface->screen_info = screen_info;
 
     surface->gc = NULL;
     surface->drawable = drawable;
     surface->screen = screen;
     surface->owns_pixmap = FALSE;
     surface->use_pixmap = 0;
     surface->width = width;
@@ -2940,43 +2994,56 @@ typedef struct _cairo_xlib_font_glyphset
 typedef struct _cairo_xlib_font_glyphset_info {
     GlyphSet		glyphset;
     cairo_format_t	format;
     XRenderPictFormat	*xrender_format;
     cairo_xlib_font_glyphset_free_glyphs_t *pending_free_glyphs;
 } cairo_xlib_font_glyphset_info_t;
 
 typedef struct _cairo_xlib_surface_font_private {
+    cairo_scaled_font_t		    *scaled_font;
+    cairo_xlib_hook_t                close_display_hook;
     cairo_xlib_display_t	    *display;
     cairo_xlib_font_glyphset_info_t  glyphset_info[NUM_GLYPHSETS];
 } cairo_xlib_surface_font_private_t;
 
+/* callback from CloseDisplay */
 static void
-_cairo_xlib_surface_remove_scaled_font (Display *dpy,
-	                                void    *data)
+_cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t	*display,
+	                                void			*data)
 {
-    cairo_scaled_font_t *scaled_font = data;
     cairo_xlib_surface_font_private_t	*font_private;
+    cairo_scaled_font_t			*scaled_font;
+
+    font_private = cairo_container_of (data,
+				       cairo_xlib_surface_font_private_t,
+				       close_display_hook);
+    scaled_font = font_private->scaled_font;
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
     font_private  = scaled_font->surface_private;
     scaled_font->surface_private = NULL;
 
     _cairo_scaled_font_reset_cache (scaled_font);
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
     if (font_private != NULL) {
+	Display *dpy;
 	int i;
 
+	dpy = display->display;
 	for (i = 0; i < NUM_GLYPHSETS; i++) {
 	    cairo_xlib_font_glyphset_info_t *glyphset_info;
 
 	    glyphset_info = &font_private->glyphset_info[i];
 	    if (glyphset_info->glyphset)
 		XRenderFreeGlyphSet (dpy, glyphset_info->glyphset);
+
+	    if (glyphset_info->pending_free_glyphs != NULL)
+		free (glyphset_info->pending_free_glyphs);
 	}
 
 	_cairo_xlib_display_destroy (font_private->display);
 	free (font_private);
     }
 }
 
 static cairo_status_t
@@ -2985,26 +3052,30 @@ static cairo_status_t
 {
     cairo_xlib_surface_font_private_t	*font_private;
     int i;
 
     font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
     if (font_private == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    if (! _cairo_xlib_add_close_display_hook (dpy,
-		                         _cairo_xlib_surface_remove_scaled_font,
-					 scaled_font, scaled_font))
-    {
+    font_private->scaled_font = scaled_font;
+    font_private->display = _cairo_xlib_display_get (dpy);
+    if (font_private->display == NULL) {
 	free (font_private);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-
-    font_private->display = _cairo_xlib_display_get (dpy);
+    /* initialize and hook into the CloseDisplay callback */
+    font_private->close_display_hook.func =
+	_cairo_xlib_surface_remove_scaled_font;
+    _cairo_xlib_add_close_display_hook (font_private->display,
+					&font_private->close_display_hook);
+
+
     for (i = 0; i < NUM_GLYPHSETS; i++) {
 	cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
 	switch (i) {
 	case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break;
 	case GLYPHSET_INDEX_A8:     glyphset_info->format = CAIRO_FORMAT_A8;     break;
 	case GLYPHSET_INDEX_A1:     glyphset_info->format = CAIRO_FORMAT_A1;     break;
 	default:                    ASSERT_NOT_REACHED;                          break;
 	}
@@ -3025,17 +3096,18 @@ static void
     cairo_xlib_surface_font_private_t *font_private;
 
     font_private = scaled_font->surface_private;
     if (font_private != NULL) {
 	cairo_xlib_display_t *display;
 	int i;
 
 	display = font_private->display;
-	_cairo_xlib_remove_close_display_hooks (display->display, scaled_font);
+	_cairo_xlib_remove_close_display_hook (display,
+					       &font_private->close_display_hook);
 
 	for (i = 0; i < NUM_GLYPHSETS; i++) {
 	    cairo_xlib_font_glyphset_info_t *glyphset_info;
 
 	    glyphset_info = &font_private->glyphset_info[i];
 
 	    if (glyphset_info->pending_free_glyphs != NULL)
 		free (glyphset_info->pending_free_glyphs);
--- a/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
+++ b/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
@@ -28,16 +28,21 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  */
 
 #ifndef CAIRO_XLIB_XRENDER_PRIVATE_H
 #define CAIRO_XLIB_XRENDER_PRIVATE_H
 
+#include "cairo-features.h"
+#include "cairo-compiler-private.h"
+
+#include <X11/Xlib.h>
+
 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
 
 #include "cairo-xlib-xrender.h"
 
 #include <X11/extensions/Xrender.h>
 #include <X11/extensions/renderproto.h>
 
 #else /* !CAIRO_HAS_XLIB_XRENDER_SURFACE */
@@ -47,17 +52,17 @@
 
 
 /* Functions */
 
 /* As it happens, it is the case that, all libxrender functions
  * take a pointer as first argument */
 
 __attribute__((__unused__)) static void   _void_consume        (void *p, ...)   { }
-__attribute__((__unused__)) static void * _voidp_consume       (void *p, ...)   { return NULL; }
+__attribute__((__unused__)) static void * _voidp_consume       (void *p, ...)   { return (void *)0; }
 __attribute__((__unused__)) static int    _int_consume         (void *p, ...)   { return 0; }
 __attribute__((__unused__)) static void   _void_consume_free   (Display *p, XID n) { }
 
 #define XRenderQueryExtension				_int_consume
 #define XRenderQueryVersion				_int_consume
 #define XRenderQueryFormats				_int_consume
 #define XRenderQuerySubpixelOrder			_int_consume
 #define XRenderSetSubpixelOrder				_int_consume
--- a/gfx/cairo/cairo/src/cairo.c
+++ b/gfx/cairo/cairo/src/cairo.c
@@ -115,59 +115,16 @@ static void
     /* Don't overwrite an existing error. This preserves the first
      * error, which is the most significant. */
     _cairo_status_set_error (&cr->status, status);
 
     status = _cairo_error (status);
 }
 
 /**
- * cairo_version:
- *
- * Returns the version of the cairo library encoded in a single
- * integer as per %CAIRO_VERSION_ENCODE. The encoding ensures that
- * later versions compare greater than earlier versions.
- *
- * A run-time comparison to check that cairo's version is greater than
- * or equal to version X.Y.Z could be performed as follows:
- *
- * <informalexample><programlisting>
- * if (cairo_version() >= CAIRO_VERSION_ENCODE(X,Y,Z)) {...}
- * </programlisting></informalexample>
- *
- * See also cairo_version_string() as well as the compile-time
- * equivalents %CAIRO_VERSION and %CAIRO_VERSION_STRING.
- *
- * Return value: the encoded version.
- **/
-int
-cairo_version (void)
-{
-    return CAIRO_VERSION;
-}
-
-/**
- * cairo_version_string:
- *
- * Returns the version of the cairo library as a human-readable string
- * of the form "X.Y.Z".
- *
- * See also cairo_version() as well as the compile-time equivalents
- * %CAIRO_VERSION_STRING and %CAIRO_VERSION.
- *
- * Return value: a string containing the version.
- **/
-const char*
-cairo_version_string (void)
-{
-    return CAIRO_VERSION_STRING;
-}
-slim_hidden_def (cairo_version_string);
-
-/**
  * cairo_create:
  * @target: target surface for the context
  *
  * Creates a new #cairo_t with all graphics state parameters set to
  * default values and with @target as a target surface. The target
  * surface should be constructed with a backend-specific function such
  * as cairo_image_surface_create() (or any other
  * cairo_<emphasis>backend</emphasis>_surface_create() variant).
@@ -582,17 +539,27 @@ cairo_pop_group (cairo_t *cr)
 
     group_pattern = cairo_pattern_create_for_surface (group_surface);
     if (cairo_pattern_status (group_pattern)) {
 	_cairo_set_error (cr, cairo_pattern_status (group_pattern));
         goto done;
     }
 
     _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
-    cairo_pattern_set_matrix (group_pattern, &group_matrix);
+    /* Transform by group_matrix centered around device_transform so that when
+     * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
+     * with a matrix equivalent to the device_transform of group_surface. */
+    if (_cairo_surface_has_device_transform (group_surface)) {
+	cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
+	_cairo_pattern_transform (group_pattern, &group_matrix);
+	_cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
+    } else {
+	cairo_pattern_set_matrix (group_pattern, &group_matrix);
+    }
+
 done:
     cairo_surface_destroy (group_surface);
 
     return group_pattern;
 }
 slim_hidden_def(cairo_pop_group);
 
 /**
@@ -2604,17 +2571,17 @@ cairo_copy_clip_rectangle_list (cairo_t 
  * Note: The cairo_select_font_face() function call is part of what
  * the cairo designers call the "toy" text API. It is convenient for
  * short demos and simple programs, but it is not expected to be
  * adequate for serious text-using applications.
  *
  * Selects a family and style of font from a simplified description as
  * a family name, slant and weight. Cairo provides no operation to
  * list available family names on the system (this is a "toy",
- * remember"), but the standard CSS2 generic family names, ("serif",
+ * remember), but the standard CSS2 generic family names, ("serif",
  * "sans-serif", "cursive", "fantasy", "monospace"), are likely to
  * work as expected.
  *
  * For "real" font selection, see the font-backend-specific
  * font_face_create functions for the font backend you are using. (For
  * example, if you are using the freetype-based cairo-ft font backend,
  * see cairo_ft_font_face_create_for_ft_face() or
  * cairo_ft_font_face_create_for_pattern().) The resulting font face
@@ -2626,18 +2593,22 @@ cairo_copy_clip_rectangle_list (cairo_t 
  * freetype), for operations such as listing available fonts, etc.
  *
  * It is expected that most applications will need to use a more
  * comprehensive font handling and text layout library, (for example,
  * pango), in conjunction with cairo.
  *
  * If text is drawn without a call to cairo_select_font_face(), (nor
  * cairo_set_font_face() nor cairo_set_scaled_font()), the default
- * family is "sans", slant is %CAIRO_FONT_SLANT_NORMAL, and weight is
+ * family is platform-specific, but is essentially "sans-serif".
+ * Default slant is %CAIRO_FONT_SLANT_NORMAL, and default weight is
  * %CAIRO_FONT_WEIGHT_NORMAL.
+ *
+ * This function is equivalent to a call to cairo_toy_font_face_create()
+ * followed by cairo_set_font_face().
  **/
 void
 cairo_select_font_face (cairo_t              *cr,
 			const char           *family,
 			cairo_font_slant_t    slant,
 			cairo_font_weight_t   weight)
 {
     cairo_status_t status;
@@ -2886,16 +2857,21 @@ void
 cairo_set_scaled_font (cairo_t                   *cr,
 		       const cairo_scaled_font_t *scaled_font)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
 
+    if (scaled_font == NULL) {
+	status = CAIRO_STATUS_NULL_POINTER;
+	goto BAIL;
+    }
+
     status = scaled_font->status;
     if (status)
         goto BAIL;
 
     status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
     if (status)
         goto BAIL;
 
@@ -2947,17 +2923,17 @@ cairo_get_scaled_font (cairo_t *cr)
     }
 
     return scaled_font;
 }
 
 /**
  * cairo_text_extents:
  * @cr: a #cairo_t
- * @utf8: a string of text encoded in UTF-8, or %NULL
+ * @utf8: a NUL-terminated string of text encoded in UTF-8, or %NULL
  * @extents: a #cairo_text_extents_t object into which the results
  * will be stored
  *
  * Gets the extents for a string of text. The extents describe a
  * user-space rectangle that encloses the "inked" portion of the text,
  * (as it would be drawn by cairo_show_text()). Additionally, the
  * x_advance and y_advance values indicate the amount by which the
  * current point would be advanced by cairo_show_text().
@@ -2989,26 +2965,28 @@ cairo_text_extents (cairo_t             
     if (cr->status)
 	return;
 
     if (utf8 == NULL)
 	return;
 
     cairo_get_current_point (cr, &x, &y);
 
-    status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+    status = _cairo_gstate_text_to_glyphs (cr->gstate,
 					   x, y,
-					   &glyphs, &num_glyphs);
+					   utf8, strlen (utf8),
+					   &glyphs, &num_glyphs,
+					   NULL, NULL,
+					   NULL);
 
     if (status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_gstate_glyph_extents (cr->gstate,
 		                              glyphs, num_glyphs,
 					      extents);
-    if (glyphs)
-	free (glyphs);
+    cairo_glyph_free (glyphs);
 
     if (status)
 	_cairo_set_error (cr, status);
 }
 
 /**
  * cairo_glyph_extents:
  * @cr: a #cairo_t
@@ -3062,17 +3040,17 @@ cairo_glyph_extents (cairo_t            
 					  extents);
     if (status)
 	_cairo_set_error (cr, status);
 }
 
 /**
  * cairo_show_text:
  * @cr: a cairo context
- * @utf8: a string of text encoded in UTF-8, or %NULL
+ * @utf8: a NUL-terminated string of text encoded in UTF-8, or %NULL
  *
  * A drawing operator that generates the shape from a string of UTF-8
  * characters, rendered according to the current font_face, font_size
  * (font_matrix), and font_options.
  *
  * This function first computes a set of glyphs for the string of
  * text. The first glyph is placed so that its origin is at the
  * current point. The origin of each subsequent glyph is offset from
@@ -3092,72 +3070,79 @@ cairo_glyph_extents (cairo_t            
  * "real" text display API in cairo.
  **/
 void
 cairo_show_text (cairo_t *cr, const char *utf8)
 {
     cairo_text_extents_t extents;
     cairo_status_t status;
     cairo_glyph_t *glyphs = NULL, *last_glyph;
-    int num_glyphs;
+    cairo_text_cluster_t *clusters = NULL;
+    int utf8_len, num_glyphs, num_clusters;
+    cairo_bool_t backward;
     double x, y;
 
     if (cr->status)
 	return;
 
     if (utf8 == NULL)
 	return;
 
     cairo_get_current_point (cr, &x, &y);
 
-    status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+    utf8_len = strlen (utf8);
+
+    status = _cairo_gstate_text_to_glyphs (cr->gstate,
 					   x, y,
-					   &glyphs, &num_glyphs);
+					   utf8, utf8_len,
+					   &glyphs, &num_glyphs,
+					   cairo_has_show_text_glyphs (cr) ? &clusters : NULL, &num_clusters,
+					   &backward);
     if (status)
 	goto BAIL;
 
     if (num_glyphs == 0)
 	return;
 
     status = _cairo_gstate_show_text_glyphs (cr->gstate,
-					     NULL, 0,
+					     utf8, utf8_len,
 					     glyphs, num_glyphs,
-					     NULL, 0,
-					     FALSE);
+					     clusters, num_clusters,
+					     backward);
     if (status)
 	goto BAIL;
 
     last_glyph = &glyphs[num_glyphs - 1];
     status = _cairo_gstate_glyph_extents (cr->gstate,
 					  last_glyph, 1,
 					  &extents);
     if (status)
 	goto BAIL;
 
     x = last_glyph->x + extents.x_advance;