b=462938, Upgrade cairo to 1.8.2 and pixman to 0.12.0 [cairo piece]
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 05 Nov 2008 23:48:23 -0800
changeset 21379 ce976e0708ab4a7fc43cf78fcad0c6b21c8a06ff
parent 21378 69224da04e45b6af348854c3fe0e52ae4bb54815
child 21380 85f7383ab46f51ba7f8e37083b16ce65dba7ed83
push idunknown
push userunknown
push dateunknown
bugs462938
milestone1.9.1b2pre
b=462938, Upgrade cairo to 1.8.2 and pixman to 0.12.0 [cairo piece]
gfx/cairo/README
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface-private.h
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-array.c
gfx/cairo/cairo/src/cairo-atomic-private.h
gfx/cairo/cairo/src/cairo-atomic.c
gfx/cairo/cairo/src/cairo-bentley-ottmann.c
gfx/cairo/cairo/src/cairo-cache.c
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-color.c
gfx/cairo/cairo/src/cairo-compiler-private.h
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-directfb.h
gfx/cairo/cairo/src/cairo-features-win32.h
gfx/cairo/cairo/src/cairo-font-face-twin-data.c
gfx/cairo/cairo/src/cairo-font-face-twin.c
gfx/cairo/cairo/src/cairo-font-face.c
gfx/cairo/cairo/src/cairo-font-options.c
gfx/cairo/cairo/src/cairo-ft-font.c
gfx/cairo/cairo/src/cairo-glitz-surface.c
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-hull.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-meta-surface-private.h
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-misc.c
gfx/cairo/cairo/src/cairo-mutex-impl-private.h
gfx/cairo/cairo/src/cairo-mutex-list-private.h
gfx/cairo/cairo/src/cairo-mutex-private.h
gfx/cairo/cairo/src/cairo-mutex-type-private.h
gfx/cairo/cairo/src/cairo-mutex.c
gfx/cairo/cairo/src/cairo-no-features.h
gfx/cairo/cairo/src/cairo-os2-private.h
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-output-stream-private.h
gfx/cairo/cairo/src/cairo-output-stream.c
gfx/cairo/cairo/src/cairo-paginated-private.h
gfx/cairo/cairo/src/cairo-paginated-surface.c
gfx/cairo/cairo/src/cairo-path-fill.c
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-operators-private.h
gfx/cairo/cairo/src/cairo-pdf-operators.c
gfx/cairo/cairo/src/cairo-pdf-surface-private.h
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-png.c
gfx/cairo/cairo/src/cairo-polygon.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-quartz-image-surface.c
gfx/cairo/cairo/src/cairo-quartz-private.h
gfx/cairo/cairo/src/cairo-quartz-surface.c
gfx/cairo/cairo/src/cairo-quartz.h
gfx/cairo/cairo/src/cairo-reference-count-private.h
gfx/cairo/cairo/src/cairo-region-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.c
gfx/cairo/cairo/src/cairo-skiplist.c
gfx/cairo/cairo/src/cairo-slope.c
gfx/cairo/cairo/src/cairo-surface-fallback-private.h
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-system.c
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-type3-glyph-surface-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.c
gfx/cairo/cairo/src/cairo-wideint-private.h
gfx/cairo/cairo/src/cairo-wideint-type-private.h
gfx/cairo/cairo/src/cairo-wideint.c
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-win32.c
gfx/cairo/cairo/src/cairo-win32.h
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/test-fallback-surface.c
gfx/cairo/cairo/src/test-meta-surface.c
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/nonfatal-assertions.patch
--- 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.7.4-136-g5ea2555)
-  pixman (pixman-0.11.10-8-g7180230)
+  cairo (1.8.2)
+  pixman (pixman-0.12.0-19-g95f2af9)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
 ==== Patches ====
 
 Some specific things:
@@ -23,15 +23,17 @@ max-font-size.patch: Clamp freetype font
 win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
 
 nonfatal-assertions.patch: Make assertions non-fatal
 
 buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583.
 
 tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
 
+cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds
+
 ==== pixman patches ====
 
 endian.patch: include cairo-platform.h for endian macros
 
 ==== disable printing patch ====
 
 disable-printing.patch:  allows us to use NS_PRINTING to disable printing.
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -80,16 +80,18 @@ CSRCS   = \
         cairo-bentley-ottmann.c \
         cairo-cache.c \
         cairo-clip.c \
         cairo-color.c \
         cairo-debug.c \
         cairo-deflate-stream.c \
         cairo-fixed.c \
 	cairo-font-face.c \
+	cairo-font-face-twin.c \
+	cairo-font-face-twin-data.c \
         cairo-font-options.c \
         cairo-freelist.c \
         cairo-gstate.c \
         cairo-hash.c \
         cairo-hull.c \
         cairo-image-surface.c \
         cairo-lzw.c \
         cairo-matrix.c \
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -61,13 +61,16 @@ cairo_private cairo_bool_t
 
 cairo_private cairo_bool_t
 _cairo_analysis_surface_has_unsupported (cairo_surface_t *surface);
 
 cairo_private void
 _cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
 					  cairo_box_t     *bbox);
 
+cairo_private cairo_int_status_t
+_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
+				      cairo_int_status_t status_b);
 
 cairo_private cairo_surface_t *
 _cairo_null_surface_create (cairo_content_t content);
 
 #endif /* CAIRO_ANALYSIS_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -57,19 +57,51 @@ typedef struct {
     cairo_rectangle_int_t current_clip;
     cairo_box_t page_bbox;
 
     cairo_bool_t has_ctm;
     cairo_matrix_t ctm;
 
 } cairo_analysis_surface_t;
 
+cairo_int_status_t
+_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
+				      cairo_int_status_t status_b)
+{
+    /* fatal errors should be checked and propagated at source */
+    assert (! _cairo_status_is_error (status_a));
+    assert (! _cairo_status_is_error (status_b));
+
+    /* return the most important status */
+    if (status_a == CAIRO_INT_STATUS_UNSUPPORTED ||
+	status_b == CAIRO_INT_STATUS_UNSUPPORTED)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK ||
+	status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK)
+	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+
+    if (status_a == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN ||
+	status_b == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+
+    if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY ||
+	status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
+	return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+
+    /* at this point we have checked all the valid internal codes, so... */
+    assert (status_a == CAIRO_STATUS_SUCCESS &&
+	    status_b == CAIRO_STATUS_SUCCESS);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
-_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
-						      cairo_pattern_t	       *pattern)
+_analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
+			       cairo_pattern_t		*pattern)
 {
     cairo_surface_t *analysis = &surface->base;
     cairo_surface_pattern_t *surface_pattern;
     cairo_status_t status;
     cairo_bool_t old_has_ctm;
     cairo_matrix_t old_ctm, p2d;
     cairo_rectangle_int_t old_clip;
     cairo_rectangle_int_t meta_extents;
@@ -113,19 +145,19 @@ static cairo_int_status_t
     surface->current_clip = old_clip;
     surface->width = old_width;
     surface->height = old_height;
 
     return status;
 }
 
 static cairo_int_status_t
-_cairo_analysis_surface_add_operation  (cairo_analysis_surface_t *surface,
-					cairo_rectangle_int_t    *rect,
-					cairo_int_status_t        backend_status)
+_add_operation  (cairo_analysis_surface_t *surface,
+		 cairo_rectangle_int_t    *rect,
+		 cairo_int_status_t        backend_status)
 {
     cairo_int_status_t status;
     cairo_box_t bbox;
 
     if (rect->width == 0 || rect->height == 0) {
 	/* Even though the operation is not visible we must be careful
 	 * to not allow unsupported operations to be replayed to the
 	 * backend during CAIRO_PAGINATED_MODE_RENDER */
@@ -297,75 +329,81 @@ static cairo_int_status_t
 
     if (!surface->target->backend->paint)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->paint) (surface->target, op,
                                                              source);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-									       source);
+	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
 	if (status)
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &source_extents);
     }
 
     _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_mask (void		*abstract_surface,
 			      cairo_operator_t	 op,
 			      cairo_pattern_t	*source,
 			      cairo_pattern_t	*mask)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	      status, backend_status;
+    cairo_int_status_t	      status, backend_status;
     cairo_rectangle_int_t   extents;
 
     if (!surface->target->backend->mask)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->mask) (surface->target, op,
                                                             source, mask);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
+	cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
+	cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
+
 	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
-	    if (_cairo_surface_is_meta (surface_pattern->surface))
-		backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-										       source);
-	    if (backend_status != CAIRO_STATUS_SUCCESS &&
-		backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
-		return backend_status;
+	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
+		backend_source_status =
+		    _analyze_meta_surface_pattern (surface, source);
+		if (_cairo_status_is_error (backend_source_status))
+		    return backend_source_status;
+	    }
 	}
 
 	if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
-	    if (_cairo_surface_is_meta (surface_pattern->surface))
-		backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-										       mask);
-	    if (backend_status != CAIRO_STATUS_SUCCESS &&
-		backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
-		return backend_status;
+	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
+		backend_mask_status =
+		    _analyze_meta_surface_pattern (surface, mask);
+		if (_cairo_status_is_error (backend_mask_status))
+		    return backend_mask_status;
+	    }
 	}
+
+	backend_status =
+	    _cairo_analysis_surface_merge_status (backend_source_status,
+						  backend_mask_status);
     }
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
@@ -379,17 +417,17 @@ static cairo_int_status_t
 	if (status)
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &source_extents);
     }
 
     _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_stroke (void			*abstract_surface,
 				cairo_operator_t	 op,
 				cairo_pattern_t		*source,
@@ -398,30 +436,28 @@ static cairo_int_status_t
 				cairo_matrix_t		*ctm,
 				cairo_matrix_t		*ctm_inverse,
 				double			 tolerance,
 				cairo_antialias_t	 antialias)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_traps_t            traps;
-    cairo_box_t              box;
     cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->stroke)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->stroke) (surface->target, op,
 							      source, path, style,
 							      ctm, ctm_inverse,
 							      tolerance, antialias);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-									       source);
+	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
@@ -429,78 +465,66 @@ static cairo_int_status_t
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &source_extents);
     }
 
     _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	box.p1.x = _cairo_fixed_from_int (extents.x);
-	box.p1.y = _cairo_fixed_from_int (extents.y);
-	box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
-	box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
+	cairo_box_t box;
+
+	_cairo_box_from_rectangle (&box, &extents);
 
 	_cairo_traps_init (&traps);
 	_cairo_traps_limit (&traps, &box);
 	status = _cairo_path_fixed_stroke_to_traps (path,
 						    style,
 						    ctm, ctm_inverse,
 						    tolerance,
 						    &traps);
 	if (status) {
 	    _cairo_traps_fini (&traps);
 	    return status;
 	}
 
-	if (traps.num_traps == 0) {
-	    extents.x = 0;
-	    extents.y = 0;
-	    extents.width = 0;
-	    extents.height = 0;
-	} else {
-	    _cairo_traps_extents (&traps, &box);
-	    extents.x = _cairo_fixed_integer_floor (box.p1.x);
-	    extents.y = _cairo_fixed_integer_floor (box.p1.y);
-	    extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
-	    extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
-	}
+	_cairo_traps_extents (&traps, &box);
 	_cairo_traps_fini (&traps);
+
+        _cairo_box_round_to_rectangle (&box, &extents);
     }
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_fill (void			*abstract_surface,
 			      cairo_operator_t		 op,
 			      cairo_pattern_t		*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
 			      cairo_antialias_t		 antialias)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_traps_t            traps;
-    cairo_box_t              box;
     cairo_rectangle_int_t  extents;
 
     if (!surface->target->backend->fill)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->fill) (surface->target, op,
 						    source, path, fill_rule,
 						    tolerance, antialias);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-									       source);
+	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
@@ -508,49 +532,38 @@ static cairo_int_status_t
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &source_extents);
     }
 
     _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	box.p1.x = _cairo_fixed_from_int (extents.x);
-	box.p1.y = _cairo_fixed_from_int (extents.y);
-	box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
-	box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
+	cairo_box_t box;
+
+	_cairo_box_from_rectangle (&box, &extents);
 
 	_cairo_traps_init (&traps);
 	_cairo_traps_limit (&traps, &box);
 	status = _cairo_path_fixed_fill_to_traps (path,
 						  fill_rule,
 						  tolerance,
 						  &traps);
 	if (status) {
 	    _cairo_traps_fini (&traps);
 	    return status;
 	}
 
-	if (traps.num_traps == 0) {
-	    extents.x = 0;
-	    extents.y = 0;
-	    extents.width = 0;
-	    extents.height = 0;
-	} else {
-	    _cairo_traps_extents (&traps, &box);
-	    extents.x = _cairo_fixed_integer_floor (box.p1.x);
-	    extents.y = _cairo_fixed_integer_floor (box.p1.y);
-	    extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
-	    extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
-	}
+	_cairo_traps_extents (&traps, &box);
+	_cairo_traps_fini (&traps);
 
-	_cairo_traps_fini (&traps);
+        _cairo_box_round_to_rectangle (&box, &extents);
     }
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_operator_t	   op,
 				     cairo_pattern_t	  *source,
@@ -577,18 +590,17 @@ static cairo_int_status_t
 								     glyphs, num_glyphs,
 								     NULL, 0,
 								     FALSE,
 								     scaled_font);
     else
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-									       source);
+	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
@@ -606,17 +618,17 @@ static cairo_int_status_t
 							  num_glyphs,
 							  &glyph_extents);
 	if (status)
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &glyph_extents);
     }
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static cairo_bool_t
 _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
@@ -629,49 +641,47 @@ static cairo_int_status_t
 					  cairo_operator_t	     op,
 					  cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
 					  int			     num_glyphs,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
-					  cairo_bool_t		     backward,
+					  cairo_text_cluster_flags_t cluster_flags,
 					  cairo_scaled_font_t	    *scaled_font)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
 
     /* Adapted from _cairo_surface_show_glyphs */
     backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     if (surface->target->backend->show_text_glyphs)
 	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
 								     source,
 								     utf8, utf8_len,
 								     glyphs, num_glyphs,
-								     clusters, num_clusters,
-								     backward,
+								     clusters, num_clusters, cluster_flags,
 								     scaled_font);
     if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
 	int remaining_glyphs = num_glyphs;
 	backend_status = surface->target->backend->show_glyphs (surface->target, op,
 								source,
 								glyphs, num_glyphs,
 								scaled_font,
 								&remaining_glyphs);
 	glyphs += num_glyphs - remaining_glyphs;
 	num_glyphs = remaining_glyphs;
 	if (remaining_glyphs == 0)
 	    backend_status = CAIRO_STATUS_SUCCESS;
     }
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
-									       source);
+	backend_status = _analyze_meta_surface_pattern (surface, source);
 
     status = _cairo_surface_get_extents (&surface->base, &extents);
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     if (_cairo_operator_bounded_by_source (op)) {
 	cairo_rectangle_int_t source_extents;
 	status = _cairo_pattern_get_extents (source, &source_extents);
@@ -689,17 +699,17 @@ static cairo_int_status_t
 							  num_glyphs,
 							  &glyph_extents);
 	if (status)
 	    return status;
 
 	_cairo_rectangle_intersect (&extents, &glyph_extents);
     }
 
-    status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
+    status = _add_operation (surface, &extents, backend_status);
 
     return status;
 }
 
 static const cairo_surface_backend_t cairo_analysis_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
     NULL, /* create_similar */
     _cairo_analysis_surface_finish,
@@ -737,16 +747,21 @@ static const cairo_surface_backend_t cai
 };
 
 cairo_surface_t *
 _cairo_analysis_surface_create (cairo_surface_t		*target,
 				int			 width,
 				int			 height)
 {
     cairo_analysis_surface_t *surface;
+    cairo_status_t status;
+
+    status = target->status;
+    if (status)
+	return _cairo_surface_create_in_error (status);
 
     surface = malloc (sizeof (cairo_analysis_surface_t));
     if (surface == NULL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     /* I believe the content type here is truly arbitrary. I'm quite
      * sure nothing will ever use this value. */
     _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
@@ -780,27 +795,32 @@ cairo_surface_t *
 	surface->current_clip.y = 0;
 	surface->current_clip.width = width;
 	surface->current_clip.height = height;
     }
 
     return &surface->base;
 }
 
-cairo_private void
+void
 _cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
 				 cairo_matrix_t  *ctm)
 {
-    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
+    cairo_analysis_surface_t	*surface;
+
+    if (abstract_surface->status)
+	return;
+
+    surface = (cairo_analysis_surface_t *) abstract_surface;
 
     surface->ctm = *ctm;
     surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
 }
 
-cairo_private void
+void
 _cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
 				 cairo_matrix_t  *ctm)
 {
     cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 
     *ctm = surface->ctm;
 }
 
--- a/gfx/cairo/cairo/src/cairo-array.c
+++ b/gfx/cairo/cairo/src/cairo-array.c
@@ -80,16 +80,17 @@ void
     array->element_size = other->element_size;
     array->elements = other->elements;
 
     array->is_snapshot = TRUE;
 }
 
 /**
  * _cairo_array_fini:
+ * @array: A #cairo_array_t
  *
  * Free all resources associated with @array. After this call, @array
  * should not be used again without a subsequent call to
  * _cairo_array_init() again first.
  **/
 void
 _cairo_array_fini (cairo_array_t *array)
 {
@@ -99,16 +100,17 @@ void
     if (array->elements) {
 	free (* array->elements);
 	free (array->elements);
     }
 }
 
 /**
  * _cairo_array_grow_by:
+ * @array: a #cairo_array_t
  *
  * Increase the size of @array (if needed) so that there are at least
  * @additional free spaces in the array. The actual size of the array
  * is always increased by doubling as many times as necessary.
  **/
 cairo_status_t
 _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
 {
@@ -153,48 +155,52 @@ cairo_status_t
 
     *array->elements = new_elements;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_array_truncate:
+ * @array: a #cairo_array_t
  *
  * Truncate size of the array to @num_elements if less than the
  * current size. No memory is actually freed. The stored objects
  * beyond @num_elements are simply "forgotten".
  **/
 void
 _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
 {
     assert (! array->is_snapshot);
 
     if (num_elements < array->num_elements)
 	array->num_elements = num_elements;
 }
 
 /**
  * _cairo_array_index:
+ * @array: a #cairo_array_t
+ * Returns: A pointer to the object stored at @index.
  *
- * Return value: A pointer to object stored at @index. If the
- * resulting value is assigned to a pointer to an object of the same
+ * If the resulting value is assigned to a pointer to an object of the same
  * element_size as initially passed to _cairo_array_init() then that
  * pointer may be used for further direct indexing with []. For
  * example:
  *
- * 	#cairo_array_t array;
+ * <informalexample><programlisting>
+ *	cairo_array_t array;
  *	double *values;
  *
  *	_cairo_array_init (&array, sizeof(double));
  *	... calls to _cairo_array_append() here ...
  *
  *	values = _cairo_array_index (&array, 0);
  *      for (i = 0; i < _cairo_array_num_elements (&array); i++)
  *	    ... use values[i] here ...
+ * </programlisting></informalexample>
  **/
 void *
 _cairo_array_index (cairo_array_t *array, unsigned int index)
 {
     /* We allow an index of 0 for the no-elements case.
      * This makes for cleaner calling code which will often look like:
      *
      *    elements = _cairo_array_index (array, num_elements);
@@ -210,28 +216,30 @@ void *
 
     assert (index < array->num_elements);
 
     return (void *) &(*array->elements)[index * array->element_size];
 }
 
 /**
  * _cairo_array_copy_element:
+ * @array: a #cairo_array_t
  *
  * Copy a single element out of the array from index @index into the
  * location pointed to by @dst.
  **/
 void
 _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
 {
     memcpy (dst, _cairo_array_index (array, index), array->element_size);
 }
 
 /**
  * _cairo_array_append:
+ * @array: a #cairo_array_t
  *
  * Append a single item onto the array by growing the array by at
  * least one element, then copying element_size bytes from @element
  * into the array. The address of the resulting object within the
  * array can be determined with:
  *
  * _cairo_array_index (array, _cairo_array_num_elements (array) - 1);
  *
@@ -245,16 +253,17 @@ cairo_status_t
 {
     assert (! array->is_snapshot);
 
     return _cairo_array_append_multiple (array, element, 1);
 }
 
 /**
  * _cairo_array_append:
+ * @array: a #cairo_array_t
  *
  * Append one or more items onto the array by growing the array by
  * @num_elements, then copying @num_elements * element_size bytes from
  * @elements into the array.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
  * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
  * operation.
@@ -275,16 +284,17 @@ cairo_status_t
 
     memcpy (dest, elements, num_elements * array->element_size);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_array_allocate:
+ * @array: a #cairo_array_t
  *
  * Allocate space at the end of the array for @num_elements additional
  * elements, providing the address of the new memory chunk in
  * @elements. This memory will be unitialized, but will be accounted
  * for in the return value of _cairo_array_num_elements().
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
  * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
@@ -309,30 +319,34 @@ cairo_status_t
 
     array->num_elements += num_elements;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_array_num_elements:
+ * @array: a #cairo_array_t
+ * Returns: The number of elements stored in @array.
  *
- * Return value: The number of elements stored in @array.
+ * This space was left intentionally blank, but gtk-doc filled it.
  **/
 int
 _cairo_array_num_elements (cairo_array_t *array)
 {
     return array->num_elements;
 }
 
 /**
  * _cairo_array_size:
+ * @array: a #cairo_array_t
+ * Returns: The number of elements for which there is currently space
+ * allocated in @array.
  *
- * Return value: The number of elements for which there is currently
- * space allocated in array.
+ * This space was left intentionally blank, but gtk-doc filled it.
  **/
 int
 _cairo_array_size (cairo_array_t *array)
 {
     return array->size;
 }
 
 /* #cairo_user_data_array_t */
--- a/gfx/cairo/cairo/src/cairo-atomic-private.h
+++ b/gfx/cairo/cairo/src/cairo-atomic-private.h
@@ -32,53 +32,54 @@
  *
  * Contributor(s):
  *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 #ifndef CAIRO_ATOMIC_PRIVATE_H
 #define CAIRO_ATOMIC_PRIVATE_H
 
+# include "cairo-compiler-private.h"
+
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 CAIRO_BEGIN_DECLS
 
-#define CAIRO_HAS_ATOMIC_OPS 1
+#if HAVE_INTEL_ATOMIC_PRIMITIVES
 
-#if CAIRO_HAS_INTEL_ATOMIC_PRIMITIVES
+#define HAS_ATOMIC_OPS 1
 
 typedef int cairo_atomic_int_t;
 
 # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
 # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
 # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
 
-#else
+#endif
 
-# include "cairo-compiler-private.h"
 
-# undef CAIRO_HAS_ATOMIC_OPS
+#ifndef HAS_ATOMIC_OPS
 
 typedef int cairo_atomic_int_t;
 
 cairo_private void
 _cairo_atomic_int_inc (int *x);
 
 cairo_private cairo_bool_t
 _cairo_atomic_int_dec_and_test (int *x);
 
 cairo_private int
 _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
 
 #endif
 
 
-#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
+#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
 
 # include "cairo-compiler-private.h"
 
 cairo_private int
 _cairo_atomic_int_get (int *x);
 
 cairo_private void
 _cairo_atomic_int_set (int *x, int value);
--- a/gfx/cairo/cairo/src/cairo-atomic.c
+++ b/gfx/cairo/cairo/src/cairo-atomic.c
@@ -31,17 +31,17 @@
  *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 #include "cairoint.h"
 
 #include "cairo-atomic-private.h"
 #include "cairo-mutex-private.h"
 
-#ifndef CAIRO_HAS_ATOMIC_OPS
+#ifndef HAS_ATOMIC_OPS
 void
 _cairo_atomic_int_inc (int *x)
 {
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     *x += 1;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 }
 
@@ -68,17 +68,17 @@ int
 	*x = newv;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
 
 #endif
 
-#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
+#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
 int
 _cairo_atomic_int_get (int *x)
 {
     int ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -34,16 +34,19 @@
  */
 
 /* Provide definitions for standalone compilation */
 #include "cairoint.h"
 
 #include "cairo-skiplist-private.h"
 #include "cairo-freelist-private.h"
 
+#define DEBUG_VALIDATE 0
+#define DEBUG_PRINT_STATE 0
+
 typedef cairo_point_t cairo_bo_point32_t;
 
 typedef struct _cairo_bo_point128 {
     cairo_int128_t x;
     cairo_int128_t y;
 } cairo_bo_point128_t;
 
 typedef struct _cairo_bo_intersect_ordinate {
@@ -193,79 +196,180 @@ static int
     int32_t adx = a->bottom.x - a->top.x;
     int32_t bdx = b->bottom.x - b->top.x;
 
     /* Since the dy's are all positive by construction we can fast
      * path the case where the two edges point in different directions
      * with respect to x. */
     if ((adx ^ bdx) < 0) {
 	return adx < 0 ? -1 : +1;
-    }
-    else {
+    } else {
 	int32_t ady = a->bottom.y - a->top.y;
 	int32_t bdy = b->bottom.y - b->top.y;
-	int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
-	int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+	cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+	cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
 
-	/* if (adx * bdy > bdx * ady) */
-	if (_cairo_int64_gt (adx_bdy, bdx_ady))
-	    return 1;
-
-	/* if (adx * bdy < bdx * ady) */
-	if (_cairo_int64_lt (adx_bdy, bdx_ady))
-	    return -1;
-	return 0;
+	return _cairo_int64_cmp (adx_bdy, bdx_ady);
     }
 }
 
-static cairo_quorem64_t
-edge_x_for_y (cairo_bo_edge_t *edge,
-	      int32_t y)
+/*
+ * We need to compare the x-coordinates of a pair of lines for a particular y,
+ * without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ *   X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ *   A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
+ * where -?- is our inequality operator.
+ *
+ * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ *   A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
+ *                                 - (Y - A_y) * A_dx * B_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 128 bit arithmetic.
+ *
+ * (And put the burden of the work on developing fast 128 bit ops, which are
+ * required throughout the tessellator.)
+ *
+ * See the similar discussion for _slope_compare().
+ */
+static int
+edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
+			       const cairo_bo_edge_t *b,
+			       int32_t y)
 {
     /* XXX: We're assuming here that dx and dy will still fit in 32
      * bits. That's not true in general as there could be overflow. We
      * should prevent that before the tessellation algorithm
      * begins.
      */
-    int32_t dx = edge->bottom.x - edge->top.x;
-    int32_t dy = edge->bottom.y - edge->top.y;
-    int64_t numerator;
-    cairo_quorem64_t quorem;
+    int32_t adx, ady;
+    int32_t bdx, bdy;
+    cairo_int128_t L, R;
+
+    adx = a->bottom.x - a->top.x;
+    ady = a->bottom.y - a->top.y;
+
+    bdx = b->bottom.x - b->top.x;
+    bdy = b->bottom.y - b->top.y;
+
+    L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
+				 a->top.x - b->top.x);
+
+    R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
+									    ady),
+						    y - b->top.y),
+			   _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
+									    bdy),
+						    y - a->top.y));
+
+    /* return _cairo_int128_cmp (L, R); */
+    if (_cairo_int128_lt (L, R))
+	return -1;
+    if (_cairo_int128_gt (L, R))
+	return 1;
+    return 0;
+}
 
-    if (edge->middle.y == y) {
-       quorem.quo = edge->middle.x;
-       quorem.rem = 0;
-       return quorem;
+/*
+ * We need to compare the x-coordinate of a line for a particular y wrt to a
+ * given x, without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ *   X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ *   A_x + (Y - A_y) * A_dx / A_dy -?- X
+ * where -?- is our inequality operator.
+ *
+ * By construction, we know that A_dy (and (Y - A_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ *   (Y - A_y) * A_dx -?- (X - A_x) * A_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 64 bit arithmetic.
+ *
+ * See the similar discussion for _slope_compare() and
+ * edges_compare_x_for_y_general().
+ */
+static int
+edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
+			      int32_t y,
+			      int32_t x)
+{
+    int32_t adx, ady;
+    int32_t dx, dy;
+    cairo_int64_t L, R;
+
+    adx = a->bottom.x - a->top.x;
+    ady = a->bottom.y - a->top.y;
+
+    dy = y - a->top.y;
+    dx = x - a->top.x;
+
+    L = _cairo_int32x32_64_mul (dy, adx);
+    R = _cairo_int32x32_64_mul (dx, ady);
+
+    return _cairo_int64_cmp (L, R);
+}
+
+static int
+edges_compare_x_for_y (const cairo_bo_edge_t *a,
+		       const cairo_bo_edge_t *b,
+		       int32_t y)
+{
+    /* If the sweep-line is currently on an end-point of a line,
+     * then we know its precise x value (and considering that we often need to
+     * compare events at end-points, this happens frequently enough to warrant
+     * special casing).
+     */
+    enum {
+       HAVE_NEITHER = 0x0,
+       HAVE_AX      = 0x1,
+       HAVE_BX      = 0x2,
+       HAVE_BOTH    = HAVE_AX | HAVE_BX
+    } have_ax_bx = HAVE_BOTH;
+    int32_t ax, bx;
+
+    if (y == a->top.y)
+	ax = a->top.x;
+    else if (y == a->bottom.y)
+	ax = a->bottom.x;
+    else
+	have_ax_bx &= ~HAVE_AX;
+
+    if (y == b->top.y)
+	bx = b->top.x;
+    else if (y == b->bottom.y)
+	bx = b->bottom.x;
+    else
+	have_ax_bx &= ~HAVE_BX;
+
+    switch (have_ax_bx) {
+    default:
+    case HAVE_NEITHER:
+	return edges_compare_x_for_y_general (a, b, y);
+    case HAVE_AX:
+	return - edge_compare_for_y_against_x (b, y, ax);
+    case HAVE_BX:
+	return edge_compare_for_y_against_x (a, y, bx);
+    case HAVE_BOTH:
+	return ax - bx;
     }
-    if (edge->bottom.y == y) {
-       quorem.quo = edge->bottom.x;
-       quorem.rem = 0;
-       return quorem;
-    }
-    if (dy == 0) {
-	quorem.quo = _cairo_int32_to_int64 (edge->top.x);
-	quorem.rem = 0;
-	return quorem;
-    }
-
-    /* edge->top.x + (y - edge->top.y) * dx / dy */
-    numerator = _cairo_int32x32_64_mul ((y - edge->top.y), dx);
-    quorem = _cairo_int64_divrem (numerator, dy);
-    quorem.quo += edge->top.x;
-
-    return quorem;
 }
 
 static int
 _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t	*sweep_line,
 				    cairo_bo_edge_t		*a,
 				    cairo_bo_edge_t		*b)
 {
-    cairo_quorem64_t ax;
-    cairo_quorem64_t bx;
     int cmp;
 
     if (a == b)
 	return 0;
 
     /* don't bother solving for abscissa if the edges' bounding boxes
      * can be used to order them. */
     {
@@ -284,28 +388,19 @@ static int
            } else {
                    bmin = b->bottom.x;
                    bmax = b->middle.x;
            }
            if (amax < bmin) return -1;
            if (amin > bmax) return +1;
     }
 
-    ax = edge_x_for_y (a, sweep_line->current_y);
-    bx = edge_x_for_y (b, sweep_line->current_y);
-    if (ax.quo > bx.quo)
-	return 1;
-    else if (ax.quo < bx.quo)
-	return -1;
-
-    /* Quotients are identical, test remainder. */
-    if (ax.rem > bx.rem)
-	return 1;
-    else if (ax.rem < bx.rem)
-	return -1;
+    cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
+    if (cmp)
+	return cmp;
 
     /* The two edges intersect exactly at y, so fall back on slope
      * comparison. We know that this compare_edges function will be
      * called only when starting a new edge, (not when stopping an
      * edge), so we don't have to worry about conditionally inverting
      * the sense of _slope_compare. */
     cmp = _slope_compare (a, b);
     if (cmp)
@@ -484,27 +579,27 @@ det32_64 (int32_t a,
     /* det = a * d - b * c */
     ad = _cairo_int32x32_64_mul (a, d);
     bc = _cairo_int32x32_64_mul (b, c);
 
     return _cairo_int64_sub (ad, bc);
 }
 
 static inline cairo_int128_t
-det64_128 (cairo_int64_t a,
-	   cairo_int64_t b,
-	   cairo_int64_t c,
-	   cairo_int64_t d)
+det64x32_128 (cairo_int64_t a,
+	      int32_t       b,
+	      cairo_int64_t c,
+	      int32_t       d)
 {
     cairo_int128_t ad;
     cairo_int128_t bc;
 
     /* det = a * d - b * c */
-    ad = _cairo_int64x64_128_mul (a, d);
-    bc = _cairo_int64x64_128_mul (b, c);
+    ad = _cairo_int64x32_128_mul (a, d);
+    bc = _cairo_int64x32_128_mul (c, b);
 
     return _cairo_int128_sub (ad, bc);
 }
 
 /* Compute the intersection of two lines as defined by two edges. The
  * result is provided as a coordinate pair of 128-bit integers.
  *
  * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
@@ -527,41 +622,41 @@ intersect_lines (cairo_bo_edge_t		*a,
     int32_t dy1 = a->top.y - a->bottom.y;
 
     int32_t dx2 = b->top.x - b->bottom.x;
     int32_t dy2 = b->top.y - b->bottom.y;
 
     cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
     cairo_quorem64_t qr;
 
-    if (_cairo_int64_eq (den_det, 0))
+    if (_cairo_int64_is_zero (den_det))
 	return CAIRO_BO_STATUS_PARALLEL;
 
     a_det = det32_64 (a->top.x, a->top.y,
 		      a->bottom.x, a->bottom.y);
     b_det = det32_64 (b->top.x, b->top.y,
 		      b->bottom.x, b->bottom.y);
 
     /* x = det (a_det, dx1, b_det, dx2) / den_det */
-    qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dx1,
-						    b_det, dx2),
-					 den_det);
-    if (_cairo_int64_eq (qr.rem,den_det))
-	return CAIRO_BO_STATUS_NO_INTERSECTION;
-    intersection->x.ordinate = qr.quo;
-    intersection->x.exactness = qr.rem ? INEXACT : EXACT;
-
-    /* y = det (a_det, dy1, b_det, dy2) / den_det */
-    qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dy1,
-						    b_det, dy2),
+    qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
+						       b_det, dx2),
 					 den_det);
     if (_cairo_int64_eq (qr.rem, den_det))
 	return CAIRO_BO_STATUS_NO_INTERSECTION;
-    intersection->y.ordinate = qr.quo;
-    intersection->y.exactness = qr.rem ? INEXACT : EXACT;
+    intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
+    intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+
+    /* y = det (a_det, dy1, b_det, dy2) / den_det */
+    qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
+						       b_det, dy2),
+					 den_det);
+    if (_cairo_int64_eq (qr.rem, den_det))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
+    intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
 
     return CAIRO_BO_STATUS_INTERSECTION;
 }
 
 static int
 _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t	a,
 					 int32_t			b)
 {
@@ -936,17 +1031,16 @@ static void
 
     left->next = right->next;
     right->next = left;
 
     right->prev = left->prev;
     left->prev = right;
 }
 
-#define DEBUG_PRINT_STATE 0
 #if DEBUG_PRINT_STATE
 static void
 _cairo_bo_edge_print (cairo_bo_edge_t *edge)
 {
     printf ("(0x%x, 0x%x)-(0x%x, 0x%x)",
 	    edge->top.x, edge->top.y,
 	    edge->bottom.x, edge->bottom.y);
 }
@@ -1073,45 +1167,45 @@ static cairo_status_t
     if (right->bottom.y < bot)
 	bot = right->bottom.y;
 
     fixed_top = trap->top;
     fixed_bot = bot;
 
     /* Only emit trapezoids with positive height. */
     if (fixed_top < fixed_bot) {
-	cairo_point_t left_top, left_bot, right_top, right_bot;
+	cairo_line_t left_line;
+	cairo_line_t right_line;
 	cairo_fixed_t xmin = bo_traps->xmin;
 	cairo_fixed_t ymin = bo_traps->ymin;
 	fixed_top += ymin;
 	fixed_bot += ymin;
 
-	left_top.x = left->top.x + xmin;
-	left_top.y = left->top.y + ymin;
-	right_top.x = right->top.x + xmin;
-	right_top.y = right->top.y + ymin;
-	left_bot.x = left->bottom.x + xmin;
-	left_bot.y = left->bottom.y + ymin;
-	right_bot.x = right->bottom.x + xmin;
-	right_bot.y = right->bottom.y + ymin;
+	left_line.p1.x  = left->top.x + xmin;
+	left_line.p1.y  = left->top.y + ymin;
+	right_line.p1.x = right->top.x + xmin;
+	right_line.p1.y = right->top.y + ymin;
+
+	left_line.p2.x  = left->bottom.x + xmin;
+	left_line.p2.y  = left->bottom.y + ymin;
+	right_line.p2.x = right->bottom.x + xmin;
+	right_line.p2.y = right->bottom.y + ymin;
 
 	/* Avoid emitting the trapezoid if it is obviously degenerate.
 	 * TODO: need a real collinearity test here for the cases
 	 * where the trapezoid is degenerate, yet the top and bottom
 	 * coordinates aren't equal.  */
-	if (left_top.x != right_top.x ||
-	    left_top.y != right_top.y ||
-	    left_bot.x != right_bot.x ||
-	    left_bot.y != right_bot.y)
+	if (left_line.p1.x != right_line.p1.x ||
+	    left_line.p1.y != right_line.p1.y ||
+	    left_line.p2.x != right_line.p2.x ||
+	    left_line.p2.y != right_line.p2.y)
 	{
-	    _cairo_traps_add_trap_from_points (bo_traps->traps,
-					       fixed_top,
-					       fixed_bot,
-					       left_top, left_bot,
-					       right_top, right_bot);
+	    _cairo_traps_add_trap (bo_traps->traps,
+				   fixed_top, fixed_bot,
+				   &left_line, &right_line);
 
 #if DEBUG_PRINT_STATE
 	    printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
 		    "right=(%08x,%08x)-(%08x,%08x) top=%08x, bot=%08x\n",
 		    left->top.x, left->top.y, left->bottom.x, left->bottom.y,
 		    right->top.x, right->top.y, right->bottom.x, right->bottom.y,
 		    trap->top, bot);
 #endif
@@ -1172,41 +1266,43 @@ static void
 }
 
 static void
 _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
 {
     _cairo_freelist_fini (&bo_traps->freelist);
 }
 
+#if DEBUG_VALIDATE
 static void
 _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
 {
     cairo_bo_edge_t *edge;
     skip_elt_t *elt;
 
     /* March through both the skip list's singly-linked list and the
      * sweep line's own list through pointers in the edges themselves
      * and make sure they agree at every point. */
 
     for (edge = sweep_line->head, elt = sweep_line->active_edges.chains[0];
 	 edge && elt;
 	 edge = edge->next, elt = elt->next[0])
     {
 	if (SKIP_ELT_TO_EDGE (elt) != edge) {
 	    fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n");
-	    exit (1);
+	    abort ();
 	}
     }
 
     if (edge || elt) {
 	fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
-	exit (1);
+	abort ();
     }
 }
+#endif
 
 
 static cairo_status_t
 _active_edges_to_traps (cairo_bo_edge_t		*head,
 			int32_t			 top,
 			cairo_fill_rule_t	 fill_rule,
 			cairo_bo_traps_t	*bo_traps)
 {
@@ -1319,19 +1415,18 @@ static cairo_status_t
 
 	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
 	    if (status)
 		goto unwind;
 
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing start", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
+	    break;
 
-	    break;
 	case CAIRO_BO_EVENT_TYPE_STOP:
 	    edge = event->e1;
 
 	    left = edge->prev;
 	    right = edge->next;
 
 	    _cairo_bo_sweep_line_delete (&sweep_line, edge);
 
@@ -1341,19 +1436,18 @@ static cairo_status_t
 
 	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
 	    if (status)
 		goto unwind;
 
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing stop", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
+	    break;
 
-	    break;
 	case CAIRO_BO_EVENT_TYPE_INTERSECTION:
 	    edge1 = event->e1;
 	    edge2 = event->e2;
 
 	    /* skip this intersection if its edges are not adjacent */
 	    if (edge2 != edge1->next)
 		break;
 
@@ -1377,20 +1471,21 @@ static cairo_status_t
 	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
 								       edge1, right);
 	    if (status)
 		goto unwind;
 
 #if DEBUG_PRINT_STATE
 	    print_state ("After processing intersection", &event_queue, &sweep_line);
 #endif
-	    _cairo_bo_sweep_line_validate (&sweep_line);
-
 	    break;
 	}
+#if DEBUG_VALIDATE
+	_cairo_bo_sweep_line_validate (&sweep_line);
+#endif
     }
 
     *num_intersections = intersection_count;
  unwind:
     for (edge = sweep_line.head; edge; edge = edge->next) {
 	cairo_status_t status2 = _cairo_bo_edge_end_trap (edge,
 							  sweep_line.current_y,
 							  &bo_traps);
@@ -1422,22 +1517,26 @@ cairo_status_t
     int intersections;
     cairo_status_t status;
     cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)];
     cairo_bo_edge_t *edges;
     cairo_fixed_t xmin = 0x7FFFFFFF;
     cairo_fixed_t ymin = 0x7FFFFFFF;
     cairo_fixed_t xmax = -0x80000000;
     cairo_fixed_t ymax = -0x80000000;
+    cairo_box_t limit;
+    cairo_bool_t has_limits;
     int num_bo_edges;
     int i;
 
     if (0 == polygon->num_edges)
 	return CAIRO_STATUS_SUCCESS;
 
+    has_limits = _cairo_traps_get_limit (traps, &limit);
+
     if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
 	edges = stack_edges;
     } else {
 	edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
 	if (edges == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
@@ -1466,16 +1565,23 @@ cairo_status_t
     if (ymax - ymin < 0)
 	ymax = ymin + 0x7FFFFFFF;
 
     for (i = 0, num_bo_edges = 0; i < polygon->num_edges; i++) {
 	cairo_bo_edge_t *edge = &edges[num_bo_edges];
 	cairo_point_t top = polygon->edges[i].edge.p1;
 	cairo_point_t bot = polygon->edges[i].edge.p2;
 
+	/* Discard the edge if it lies outside the limits of traps. */
+	if (has_limits) {
+	    /* Strictly above or below the limits? */
+	    if (bot.y <= limit.p1.y || top.y >= limit.p2.y)
+		continue;
+	}
+
 	/* Offset coordinates into the non-negative range. */
 	top.x -= xmin;
 	top.y -= ymin;
 	bot.x -= xmin;
 	bot.y -= ymin;
 
 	/* If the coordinates are still negative, then their extent is
 	 * overflowing 2^31-1.  We're going to kludge it and clamp the
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -87,16 +87,17 @@ static void
     cache->size = 0;
 }
 
 /**
  * _cairo_cache_create:
  * @keys_equal: a function to return %TRUE if two keys are equal
  * @entry_destroy: destroy notifier for cache entries
  * @max_size: the maximum size for this cache
+ * Returns: the newly created #cairo_cache_t
  *
  * Creates a new cache using the keys_equal() function to determine
  * the equality of entries.
  *
  * Data is provided to the cache in the form of user-derived version
  * of #cairo_cache_entry_t. A cache entry must be able to hold hash
  * code, a size, and the key/value pair being stored in the
  * cache. Sometimes only the key will be necessary, (as in
@@ -114,18 +115,16 @@ static void
  * undesired. If the cache entries have reference counts, then it is a
  * simple matter to use the reference counts to ensure that entries
  * continue to live even after being ejected from the cache. However,
  * in some cases the memory overhead of adding a reference count to
  * the entry would be objectionable. In such cases, the
  * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
  * used to establish a window during which no automatic removal of
  * entries will occur.
- *
- * Return value:
  **/
 cairo_cache_t *
 _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
 		     cairo_destroy_func_t	   entry_destroy,
 		     unsigned long		   max_size)
 {
     cairo_status_t status;
     cairo_cache_t *cache;
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -143,33 +143,36 @@ static cairo_status_t
 				         cairo_rectangle_int_t   *rectangle)
 {
     while (clip_path) {
         cairo_status_t status;
         cairo_traps_t traps;
         cairo_box_t extents;
         cairo_rectangle_int_t extents_rect;
 
+	_cairo_box_from_rectangle (&extents, rectangle);
+
         _cairo_traps_init (&traps);
+	_cairo_traps_limit (&traps, &extents);
 
         status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
                                                   clip_path->fill_rule,
                                                   clip_path->tolerance,
                                                   &traps);
         if (status) {
             _cairo_traps_fini (&traps);
             return status;
         }
 
         _cairo_traps_extents (&traps, &extents);
+        _cairo_traps_fini (&traps);
+
         _cairo_box_round_to_rectangle (&extents, &extents_rect);
         _cairo_rectangle_intersect (rectangle, &extents_rect);
 
-        _cairo_traps_fini (&traps);
-
         clip_path = clip_path->prev;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
 _cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
@@ -431,19 +434,18 @@ static cairo_status_t
     _cairo_traps_extents (traps, &extents);
     _cairo_box_round_to_rectangle (&extents, &surface_rect);
 
     if (clip->surface != NULL)
 	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);
 
     /* Intersect with the target surface rectangle so we don't use
      * more memory and time than we need to. */
-
     status = _cairo_surface_get_extents (target, &target_rect);
-    if (!status)
+    if (status == CAIRO_STATUS_SUCCESS)
 	_cairo_rectangle_intersect (&surface_rect, &target_rect);
 
     if (surface_rect.width == 0 || surface_rect.height == 0) {
 	surface = NULL;
 	status = CAIRO_STATUS_SUCCESS;
 	if (clip->surface != NULL)
 	    cairo_surface_destroy (clip->surface);
 	goto DONE;
@@ -556,16 +558,17 @@ cairo_status_t
 _cairo_clip_clip (cairo_clip_t       *clip,
 		  cairo_path_fixed_t *path,
 		  cairo_fill_rule_t   fill_rule,
 		  double              tolerance,
 		  cairo_antialias_t   antialias,
 		  cairo_surface_t    *target)
 {
     cairo_status_t status;
+    cairo_rectangle_int_t rectangle;
     cairo_traps_t traps;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
     /* catch the empty clip path */
     if (! path->has_current_point) {
 	_cairo_clip_set_all_clipped (clip, target);
@@ -577,16 +580,27 @@ cairo_status_t
 					 antialias);
     if (status == CAIRO_STATUS_SUCCESS)
         clip->serial = _cairo_surface_allocate_clip_serial (target);
 
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
     _cairo_traps_init (&traps);
+
+    /* Limit the traps to the target surface
+     * - so we don't add more traps than needed. */
+    status = _cairo_surface_get_extents (target, &rectangle);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	cairo_box_t box;
+
+	_cairo_box_from_rectangle (&box, &rectangle);
+	_cairo_traps_limit (&traps, &box);
+    }
+
     status = _cairo_path_fixed_fill_to_traps (path,
 					      fill_rule,
 					      tolerance,
 					      &traps);
     if (status)
 	goto bail;
 
     status = _cairo_clip_intersect_region (clip, &traps, target);
@@ -671,26 +685,32 @@ cairo_status_t
             status = _cairo_region_copy (&clip->region, &other->region);
 	    if (status)
 		goto BAIL;
 
 	    clip->has_region = TRUE;
         }
 
         if (other->surface) {
+	    int dx, dy;
             status = _cairo_surface_clone_similar (target, other->surface,
 					           0,
 						   0,
 						   other->surface_rect.width,
 						   other->surface_rect.height,
+						   &dx, &dy,
 						   &clip->surface);
 	    if (status)
 		goto BAIL;
 
             clip->surface_rect = other->surface_rect;
+
+	    /* src offset was 0, so we expect an exact replica of the surface */
+	    assert (dx == 0);
+	    assert (dy == 0);
         }
 
         if (other->path) {
             status = _cairo_clip_path_reapply_clip_path (clip, other->path);
 	    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 		goto BAIL;
         }
     }
--- a/gfx/cairo/cairo/src/cairo-color.c
+++ b/gfx/cairo/cairo/src/cairo-color.c
@@ -160,13 +160,16 @@ void
     *blue  = color->blue  * color->alpha;
     *alpha = color->alpha;
 }
 
 cairo_bool_t
 _cairo_color_equal (const cairo_color_t *color_a,
 	            const cairo_color_t *color_b)
 {
+    if (color_a == color_b)
+	return TRUE;
+
     return color_a->red_short   == color_b->red_short   &&
            color_a->green_short == color_b->green_short &&
            color_a->blue_short  == color_b->blue_short  &&
            color_a->alpha_short == color_b->alpha_short;
 }
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -33,16 +33,18 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_COMPILER_PRIVATE_H
 #define CAIRO_COMPILER_PRIVATE_H
 
+#include "cairo.h"
+
 #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))
@@ -104,23 +106,52 @@
 # define CAIRO_FUNCTION_ALIAS(old, new)		\
 	extern __typeof (new) old		\
 	__asm__ ("" #old)			\
 	__attribute__((__alias__("" #new)))
 #else
 # define CAIRO_FUNCTION_ALIAS(old, new)
 #endif
 
+/*
+ * Cairo uses the following function attributes in order to improve the
+ * generated code (effectively by manual inter-procedural analysis).
+ *
+ *   'cairo_pure': The function is only allowed to read from its arguments
+ *                 and global memory (i.e. following a pointer argument or
+ *                 accessing a shared variable). The return value should
+ *                 only depend on its arguments, and for an identical set of
+ *                 arguments should return the same value.
+ *
+ *   'cairo_const': The function is only allowed to read from its arguments.
+ *                  It is not allowed to access global memory. The return
+ *                  value should only depend its arguments, and for an
+ *                  identical set of arguments should return the same value.
+ *                  This is currently the most strict function attribute.
+ *
+ * Both these function attributes allow gcc to perform CSE and
+ * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents
+ * do not change across the function call.
+ */
+#if __GNUC__ >= 3
+#define cairo_pure __attribute__((pure))
+#define cairo_const __attribute__((const))
+#else
+#define cairo_pure
+#define cairo_const
+#endif
+
 #ifndef __GNUC__
 #undef __attribute__
 #define __attribute__(x)
 #endif
 
 #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
 #define snprintf _snprintf
+#define popen _popen
 #endif
 
 #ifdef _MSC_VER
 #undef inline
 #define inline __inline
 #endif
 
 #ifdef __STRICT_ANSI__
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -29,109 +29,103 @@
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *    Michael Emmel <mike.emmel@gmail.com>
  *    Claudio Ciccani <klan@users.sf.net>
  */
- 
 
 #include "cairoint.h"
 #include "cairo-directfb.h"
 
-#include <stdlib.h>
-
 #include <directfb.h>
 #include <direct/types.h>
 #include <direct/debug.h>
 #include <direct/memcpy.h>
 #include <direct/util.h>
 
+#include "cairo-clip-private.h"
 
 /*
  * Rectangle works fine.
  * Bugs 361377, 359553, 359243 in Gnome BTS are caused
  * by GDK/DirectFB, not by Cairo/DirectFB.
  */
 #define DFB_RECTANGLES 1
 
 /*
  * Composite works fine.
  */
-#define DFB_COMPOSITE 1 
+#define DFB_COMPOSITE 1
 
 /*
  * CompositeTrapezoids works (without antialiasing).
  */
 #define DFB_COMPOSITE_TRAPEZOIDS 1
 
 /*
  * ShowGlyphs works fine.
  */
 #define DFB_SHOW_GLYPHS 1
 
 
-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" );
+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;
-    
+
     IDirectFB           *dfb;
     IDirectFBSurface    *dfbsurface;
     IDirectFBSurface    *tmpsurface;
-    
-    /* color buffer */
-    cairo_surface_t     *color;
-        
+
+    cairo_bool_t         has_clip;
     DFBRegion           *clips;
     int                  n_clips;
-    
+
     int                  width;
     int                  height;
-    
-    cairo_bool_t         local;
+
+    unsigned             local : 1;
+    unsigned             blit_premultiplied : 1;
 } cairo_directfb_surface_t;
 
 
 typedef struct _cairo_directfb_font_cache {
-    IDirectFB           *dfb; 
+    IDirectFB           *dfb;
     IDirectFBSurface    *dfbsurface;
 
     int                  width;
     int                  height;
 
-    /* coordinates within the surface 
+    /* coordinates within the surface
      * of the last loaded glyph */
     int                  x;
     int                  y;
 } cairo_directfb_font_cache_t;
-    
 
-static cairo_surface_backend_t cairo_directfb_surface_backend;
+static cairo_surface_backend_t _cairo_directfb_surface_backend;
 
 /*****************************************************************************/
 
 static int _directfb_argb_font = 0;
 
 /*****************************************************************************/
 
-
-#define RUN_CLIPPED( surface, clip, func ) {\
-    if ((surface)->clips) {\
+#define RUN_CLIPPED(surface, clip, func) {\
+    if ((surface)->has_clip) {\
         int k;\
         for (k = 0; k < (surface)->n_clips; k++) {\
             if (clip) {\
                 DFBRegion  reg = (surface)->clips[k];\
                 DFBRegion *cli = (clip);\
                 if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
                     reg.x1 > cli->x2 || reg.y1 > cli->y2)\
                     continue;\
@@ -139,909 +133,957 @@ static int _directfb_argb_font = 0;
                     reg.x1 = cli->x1;\
                 if (reg.y1 < cli->y1)\
                     reg.y1 = cli->y1;\
                 if (reg.x2 > cli->x2)\
                     reg.x2 = cli->x2;\
                 if (reg.y2 > cli->y2)\
                     reg.y2 = cli->y2;\
                 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg);\
-            }\
-            else {\
+            } else {\
                 (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\
                                            &(surface)->clips[k]);\
             }\
             func;\
         }\
-    }\
-    else {\
+    } else {\
         (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
         func;\
     }\
 }
 
-#define TRANSFORM_POINT2X( m, x, y, ret_x, ret_y ) {\
+#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) {\
     double _x = (x);\
     double _y = (y);\
     (ret_x) = (_x * (m).xx + (m).x0);\
     (ret_y) = (_y * (m).yy + (m).y0);\
 }
 
-#define TRANSFORM_POINT3X( m, x, y, ret_x, ret_y ) {\
+#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\
     double _x = (x);\
     double _y = (y);\
     (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\
     (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\
 }
 
 /* XXX: A1 has a different bits ordering in cairo.
  *      Probably we should drop it.
  */
 
-static cairo_content_t 
+static cairo_content_t
 _directfb_format_to_content (DFBSurfacePixelFormat format)
 {
-    if (DFB_PIXELFORMAT_HAS_ALPHA(format)) {
-        if (DFB_COLOR_BITS_PER_PIXEL(format))
+    if (DFB_PIXELFORMAT_HAS_ALPHA (format)) {
+        if (DFB_COLOR_BITS_PER_PIXEL (format))
             return CAIRO_CONTENT_COLOR_ALPHA;
-            
+
         return CAIRO_CONTENT_ALPHA;
     }
-    
+
     return CAIRO_CONTENT_COLOR;
 }
 
-                                                           
-static inline DFBSurfacePixelFormat 
+static inline DFBSurfacePixelFormat
 _cairo_to_directfb_format (cairo_format_t format)
 {
     switch (format) {
-        case CAIRO_FORMAT_RGB24:
-            return DSPF_RGB32;
-        case CAIRO_FORMAT_ARGB32:
-            return DSPF_ARGB; 
-        case CAIRO_FORMAT_A8:
-            return DSPF_A8; 
-        case CAIRO_FORMAT_A1:
-            return DSPF_A1; 
-        default:
-            break;
+    case CAIRO_FORMAT_RGB24:
+	return DSPF_RGB32;
+    case CAIRO_FORMAT_ARGB32:
+	return DSPF_ARGB;
+    case CAIRO_FORMAT_A8:
+	return DSPF_A8;
+    case CAIRO_FORMAT_A1:
+	return DSPF_A1;
+    default:
+	break;
     }
-    
+
     return -1;
 }
 
 static inline cairo_format_t
 _directfb_to_cairo_format (DFBSurfacePixelFormat format)
 {
     switch (format) {
-        case DSPF_RGB32:
-            return CAIRO_FORMAT_RGB24;
-        case DSPF_ARGB:
-            return CAIRO_FORMAT_ARGB32;
-        case DSPF_A8:
-            return CAIRO_FORMAT_A8;
-        case DSPF_A1:
-            return CAIRO_FORMAT_A1;
-        default:
-            break;
+    case DSPF_RGB32:
+	return CAIRO_FORMAT_RGB24;
+    case DSPF_ARGB:
+	return CAIRO_FORMAT_ARGB32;
+    case DSPF_A8:
+	return CAIRO_FORMAT_A8;
+    case DSPF_A1:
+	return CAIRO_FORMAT_A1;
+    default:
+	break;
     }
-    
+
     return -1;
 }
 
-
-static cairo_status_t
+static cairo_bool_t
 _directfb_get_operator (cairo_operator_t         operator,
                         DFBSurfaceBlendFunction *ret_srcblend,
-                        DFBSurfaceBlendFunction *ret_dstblend )
+                        DFBSurfaceBlendFunction *ret_dstblend)
 {
     DFBSurfaceBlendFunction srcblend = DSBF_ONE;
     DFBSurfaceBlendFunction dstblend = DSBF_ZERO;
-    
+
     switch (operator) {
-        case CAIRO_OPERATOR_CLEAR:
-            srcblend = DSBF_ZERO;
-            dstblend = DSBF_ZERO;
-            break;
-        case CAIRO_OPERATOR_SOURCE:
-            srcblend = DSBF_ONE;
-            dstblend = DSBF_ZERO;
-            break;
-        case CAIRO_OPERATOR_OVER:
-            srcblend = DSBF_ONE;
-            dstblend = DSBF_INVSRCALPHA;
-            break;
-        case CAIRO_OPERATOR_IN:
-            srcblend = DSBF_DESTALPHA;
-            dstblend = DSBF_ZERO;
-            break;
-        case CAIRO_OPERATOR_OUT:
-            srcblend = DSBF_INVDESTALPHA;
-            dstblend = DSBF_ZERO;
-            break;
-        case CAIRO_OPERATOR_ATOP:
-            srcblend = DSBF_DESTALPHA;
-            dstblend = DSBF_INVSRCALPHA;
-            break;
-        case CAIRO_OPERATOR_DEST:
-            srcblend = DSBF_ZERO;
-            dstblend = DSBF_ONE;
-            break;
-        case CAIRO_OPERATOR_DEST_OVER:
-            srcblend = DSBF_INVDESTALPHA;
-            dstblend = DSBF_ONE;
-            break;
-        case CAIRO_OPERATOR_DEST_IN:
-            srcblend = DSBF_ZERO;
-            dstblend = DSBF_SRCALPHA;
-            break;
-        case CAIRO_OPERATOR_DEST_OUT:
-            srcblend = DSBF_ZERO;
-            dstblend = DSBF_INVSRCALPHA;
-            break;
-        case CAIRO_OPERATOR_DEST_ATOP:
-            srcblend = DSBF_INVDESTALPHA;
-            dstblend = DSBF_SRCALPHA;
-            break;                        
-        case CAIRO_OPERATOR_XOR:
-            srcblend = DSBF_INVDESTALPHA;
-            dstblend = DSBF_INVSRCALPHA;
-            break;
-        case CAIRO_OPERATOR_ADD:
-            srcblend = DSBF_ONE;
-            dstblend = DSBF_ONE;
-            break;
-        case CAIRO_OPERATOR_SATURATE:
-            srcblend = DSBF_SRCALPHASAT;
-            dstblend = DSBF_ONE;
-            break;
-        default:
-            return CAIRO_INT_STATUS_UNSUPPORTED;
+    case CAIRO_OPERATOR_CLEAR:
+	srcblend = DSBF_ZERO;
+	dstblend = DSBF_ZERO;
+	break;
+    case CAIRO_OPERATOR_SOURCE:
+	srcblend = DSBF_ONE;
+	dstblend = DSBF_ZERO;
+	break;
+    case CAIRO_OPERATOR_OVER:
+	srcblend = DSBF_ONE;
+	dstblend = DSBF_INVSRCALPHA;
+	break;
+    case CAIRO_OPERATOR_IN:
+	srcblend = DSBF_DESTALPHA;
+	dstblend = DSBF_ZERO;
+	break;
+    case CAIRO_OPERATOR_OUT:
+	srcblend = DSBF_INVDESTALPHA;
+	dstblend = DSBF_ZERO;
+	break;
+    case CAIRO_OPERATOR_ATOP:
+	srcblend = DSBF_DESTALPHA;
+	dstblend = DSBF_INVSRCALPHA;
+	break;
+    case CAIRO_OPERATOR_DEST:
+	srcblend = DSBF_ZERO;
+	dstblend = DSBF_ONE;
+	break;
+    case CAIRO_OPERATOR_DEST_OVER:
+	srcblend = DSBF_INVDESTALPHA;
+	dstblend = DSBF_ONE;
+	break;
+    case CAIRO_OPERATOR_DEST_IN:
+	srcblend = DSBF_ZERO;
+	dstblend = DSBF_SRCALPHA;
+	break;
+    case CAIRO_OPERATOR_DEST_OUT:
+	srcblend = DSBF_ZERO;
+	dstblend = DSBF_INVSRCALPHA;
+	break;
+    case CAIRO_OPERATOR_DEST_ATOP:
+	srcblend = DSBF_INVDESTALPHA;
+	dstblend = DSBF_SRCALPHA;
+	break;
+    case CAIRO_OPERATOR_XOR:
+	srcblend = DSBF_INVDESTALPHA;
+	dstblend = DSBF_INVSRCALPHA;
+	break;
+    case CAIRO_OPERATOR_ADD:
+	srcblend = DSBF_ONE;
+	dstblend = DSBF_ONE;
+	break;
+    case CAIRO_OPERATOR_SATURATE:
+	/* XXX This does not work. */
+#if 0
+	srcblend = DSBF_SRCALPHASAT;
+	dstblend = DSBF_ONE;
+	break;
+#endif
+    default:
+	return FALSE;
     }
 
-    if (ret_srcblend)
-        *ret_srcblend = srcblend;
-    if (ret_dstblend)
-        *ret_dstblend = dstblend;
-    
-    return CAIRO_STATUS_SUCCESS;
+    *ret_srcblend = srcblend;
+    *ret_dstblend = dstblend;
+
+    return TRUE;
 }
 
-static IDirectFBSurface*
-_directfb_buffer_surface_create (IDirectFB             *dfb, 
+static cairo_status_t
+_directfb_buffer_surface_create (IDirectFB             *dfb,
                                  DFBSurfacePixelFormat  format,
                                  int                    width,
-                                 int                    height)
+                                 int                    height,
+				 IDirectFBSurface     **out)
 {
     IDirectFBSurface      *buffer;
     DFBSurfaceDescription  dsc;
     DFBResult              ret;
-    
+
     dsc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
+    dsc.caps        = DSCAPS_PREMULTIPLIED;
     dsc.width       = width;
     dsc.height      = height;
     dsc.pixelformat = format;
 
     ret = dfb->CreateSurface (dfb, &dsc, &buffer);
     if (ret) {
         DirectFBError ("IDirectFB::CreateSurface()", ret);
-        return NULL;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
-    
-    return buffer;
+
+    *out = buffer;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_directfb_acquire_surface (cairo_directfb_surface_t  *surface, 
+_directfb_acquire_surface (cairo_directfb_surface_t  *surface,
                            cairo_rectangle_int_t     *intrest_rec,
                            cairo_image_surface_t    **image_out,
                            cairo_rectangle_int_t     *image_rect_out,
                            void                     **image_extra,
                            DFBSurfaceLockFlags        lock_flags)
-{   
+{
     IDirectFBSurface *buffer = NULL;
     DFBRectangle source_rect;
+    cairo_surface_t *image;
     cairo_format_t cairo_format;
+    cairo_status_t status;
     void *data;
-    int   pitch; 
+    int   pitch;
 
-    if (surface->format == (cairo_format_t) -1) {
+    if (surface->format == (cairo_format_t) -1 ||
+	(lock_flags & DSLF_WRITE && surface->has_clip))
+    {
         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; 
+            source_rect.w = intrest_rec->width;
+            source_rect.h = intrest_rec->height;
         } else {
             source_rect.x = 0;
             source_rect.y = 0;
             surface->dfbsurface->GetSize (surface->dfbsurface,
-                                          &source_rect.w, &source_rect.h);   
+                                          &source_rect.w, &source_rect.h);
         }
 
         if (surface->tmpsurface) {
             int w, h;
             surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h);
             if (w < source_rect.w || h < source_rect.h) {
                 surface->tmpsurface->Release (surface->tmpsurface);
                 surface->tmpsurface = NULL;
             }
         }
-        
+
         cairo_format = _cairo_format_from_content (surface->content);
         if (!surface->tmpsurface) {
             D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
-       
-            surface->tmpsurface = 
-                _directfb_buffer_surface_create (surface->dfb, 
+
+            status =
+                _directfb_buffer_surface_create (surface->dfb,
                                                  _cairo_to_directfb_format (cairo_format),
-                                                 source_rect.w, source_rect.h);
-            if (!surface->tmpsurface)
+                                                 source_rect.w, source_rect.h,
+						 &surface->tmpsurface);
+            if (status)
                 goto ERROR;
         }
         buffer = surface->tmpsurface;
-        
+
 /*        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
         if (caps & DSCAPS_FLIPPING) {
-            DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, 
+            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 {
+    } else {
         /*might be a subsurface get the offset*/
         surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
         cairo_format = surface->format;
-        buffer = surface->dfbsurface;     
+        buffer = surface->dfbsurface;
     }
-    
-    *image_extra = buffer;
-    
+
     if (buffer->Lock (buffer, lock_flags, &data, &pitch)) {
         D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n");
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
         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) 
+
+    image = cairo_image_surface_create_for_data (data, cairo_format,
+						 source_rect.w, source_rect.h,
+						 pitch);
+    status = image->status;
+    if (status)
         goto ERROR;
 
     if (image_rect_out) {
         image_rect_out->x = source_rect.x;
         image_rect_out->y = source_rect.y;
         image_rect_out->width = source_rect.w;
         image_rect_out->height = source_rect.h;
     } else {
         /* lock for read */
-        cairo_surface_t *sur = &((*image_out)->base); 
         /* might be a subsurface */
-        if (buffer == surface->dfbsurface)
-            cairo_surface_set_device_offset (sur, source_rect.x, source_rect.y);
+        if (buffer == surface->dfbsurface) {
+            cairo_surface_set_device_offset (image,
+					     source_rect.x, source_rect.y);
+	}
     }
-   
+
+    *image_extra = buffer;
+    *image_out = (cairo_image_surface_t *) image;
     return CAIRO_STATUS_SUCCESS;
 
 ERROR:
-    *image_extra = NULL;
     if (buffer) {
         buffer->Unlock (buffer);
-        if (buffer != surface->dfbsurface) 
+        if (buffer != surface->dfbsurface)
             buffer->Release (buffer);
     }
-    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    return status;
 }
 
-
-
 static cairo_surface_t *
 _cairo_directfb_surface_create_similar (void            *abstract_src,
                                         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 (CairoDFB_Surface, 
+    cairo_status_t	      status;
+
+    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));
-    if (!surface) {
-        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-        return NULL;
-    }
-   
+    format = _cairo_format_from_content (content);
+    surface = calloc (1, sizeof (cairo_directfb_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
     surface->dfb = source->dfb;
-    
+
     if (width < 8 || height < 8) {
         IDirectFBSurface *tmp;
+	DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
+
         /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
-        tmp =  _directfb_buffer_surface_create (surface->dfb, 
+        status =  _directfb_buffer_surface_create (surface->dfb,
                                         _cairo_to_directfb_format (format),
-                                        MAX (width, 8), MAX (height, 8));
-        if (tmp) {
-            DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
-            tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
-            tmp->Release (tmp);
-        }
+                                        MAX (width, 8), MAX (height, 8),
+					&tmp);
+	if (status) {
+	    free (surface);
+	    return _cairo_surface_create_in_error (status);
+	}
+
+	tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
+	tmp->Release (tmp);
+    } else {
+	status =
+	    _directfb_buffer_surface_create (surface->dfb,
+					     _cairo_to_directfb_format (format),
+					     width, height,
+					     &surface->dfbsurface);
+	if (status) {
+	    free (surface);
+	    return _cairo_surface_create_in_error (status);
+	}
     }
-    else {
-        surface->dfbsurface = _directfb_buffer_surface_create (surface->dfb,
-                                    _cairo_to_directfb_format (format), width, height);
-    }
-    
-    if (!surface->dfbsurface) {
-        D_ASSERT (surface->dfbsurface != NULL);
-        free (surface);
-        return NULL;
-    }
-    
-    _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, content);
+
+    _cairo_surface_init (&surface->base,
+			 &_cairo_directfb_surface_backend,
+			 content);
     surface->format  = format;
     surface->content = content;
     surface->width   = width;
     surface->height  = height;
-    surface->local   = true;
-    
+    surface->local   = TRUE;
+    surface->blit_premultiplied = TRUE;
+
     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 (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface);
-        
+
     if (surface->clips) {
         free (surface->clips);
         surface->clips   = NULL;
         surface->n_clips = 0;
     }
-    
-    if (surface->color) {
-        cairo_surface_destroy (surface->color);
-        surface->color = NULL;
-    }
-    
+
     if (surface->tmpsurface) {
         surface->tmpsurface->Release (surface->tmpsurface);
         surface->tmpsurface = NULL;
     }
 
     if (surface->dfbsurface) {
         surface->dfbsurface->Release (surface->dfbsurface);
         surface->dfbsurface = NULL;
     }
-    
+
     if (surface->dfb)
         surface->dfb = NULL;
-        
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_directfb_surface_acquire_source_image (void                   *abstract_surface,
                                               cairo_image_surface_t **image_out,
                                               void                  **image_extra)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
-    
-    D_DEBUG_AT (CairoDFB_Acquire, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
-    
-    return _directfb_acquire_surface (surface, NULL, image_out, 
-                                      NULL, image_extra, DSLF_READ);
+
+    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 (CairoDFB_Acquire, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
-    
+
+    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 (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  : (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);
+
+    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  : (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 (CairoDFB_Acquire, 
-                "%s( surface=%p ).\n", __FUNCTION__, surface);
-    
+    IDirectFBSurface *buffer = image_extra;
+
+    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 };
-        surface->dfbsurface->SetClip (surface->dfbsurface, &region);
-        surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
-        surface->dfbsurface->Blit (surface->dfbsurface, buffer,
-                                   NULL, image_rect->x, image_rect->y);
+	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
+	};
+	surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
+	RUN_CLIPPED (surface, &region,
+		     surface->dfbsurface->Blit (surface->dfbsurface,
+						buffer, NULL,
+						image_rect->x, image_rect->y));
     }
-    
+
     cairo_surface_destroy (&image->base);
 }
 
 static cairo_status_t
 _cairo_directfb_surface_clone_similar (void             *abstract_surface,
                                        cairo_surface_t  *src,
                                        int               src_x,
                                        int               src_y,
                                        int               width,
                                        int               height,
+                                       int              *clone_offset_x,
+                                       int              *clone_offset_y,
                                        cairo_surface_t **clone_out)
 {
     cairo_directfb_surface_t *surface = abstract_surface;
     cairo_directfb_surface_t *clone;
-    
-    D_DEBUG_AT (CairoDFB_Surface, 
-                "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src);
+
+    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;
-    }
-    else if (_cairo_surface_is_image (src)) {
-        cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
-        unsigned char         *dst, *src = image_src->data;
-        int                    pitch;
-        int                    i, j;
-        DFBResult              ret;
-        
-        clone = (cairo_directfb_surface_t *)
-                _cairo_directfb_surface_create_similar (surface, 
-                            _cairo_content_from_format (image_src->format),
-                            image_src->width, image_src->height);
-        if (!clone)
-            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-            
-        ret = clone->dfbsurface->Lock (clone->dfbsurface, 
-                                   DSLF_WRITE, (void *)&dst, &pitch);
-        if (ret) {
-            DirectFBError ("IDirectFBSurface::Lock()", ret);
-            cairo_surface_destroy ((cairo_surface_t *)clone);
-            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        }
+	*clone_offset_x = 0;
+	*clone_offset_y = 0;
+	*clone_out = cairo_surface_reference (src);
+
+	return CAIRO_STATUS_SUCCESS;
+    } else if (_cairo_surface_is_image (src)) {
+	cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
+	unsigned char         *dst, *src = image_src->data;
+	int                    pitch;
+	int                    i, j;
+	DFBResult              ret;
+
+	clone = (cairo_directfb_surface_t *)
+	    _cairo_directfb_surface_create_similar (surface,
+						    _cairo_content_from_format (image_src->format),
+						    width, height);
+	if (clone == NULL)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	if (clone->base.status)
+	    return clone->base.status;
+
+	ret = clone->dfbsurface->Lock (clone->dfbsurface,
+				       DSLF_WRITE, (void *)&dst, &pitch);
+	if (ret) {
+	    DirectFBError ("IDirectFBSurface::Lock()", ret);
+	    cairo_surface_destroy (&clone->base);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
 
-        dst += pitch * src_y;
-        src += image_src->stride * src_y;
-        
-        if (image_src->format == CAIRO_FORMAT_A1) {
-            /* A1 -> A8 */
-            for (i = 0; i < height; i++) {
-                for (j = src_x; j < src_x + width; j++)
-                    dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
-                dst += pitch;
-                src += image_src->stride;
-            }
-        }
-        else {
-            int len;
-            
-            if (image_src->format == CAIRO_FORMAT_A8) {
-                dst += src_x;
-                src += src_x;
-                len  = width;
-            } else {
-                dst += src_x * 4;
-                src += src_x * 4;
-                len  = width * 4;
-            }
-            
-            for (i = 0; i < height; i++) {
-                direct_memcpy (dst, src, len);
-                dst += pitch;
-                src += image_src->stride;
-            }
-        }
-        
-        clone->dfbsurface->Unlock (clone->dfbsurface);
-        
-        *clone_out = &clone->base;
-                
-        return CAIRO_STATUS_SUCCESS;
+	src += image_src->stride * src_y;
+	if (image_src->format == CAIRO_FORMAT_A1) {
+	    /* A1 -> A8 */
+	    dst -= src_x;
+	    for (i = 0; i < height; i++) {
+		for (j = src_x; j < src_x + width; j++)
+		    dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
+		dst += pitch;
+		src += image_src->stride;
+	    }
+	} else {
+	    int len;
+
+	    if (image_src->format == CAIRO_FORMAT_A8) {
+		src += src_x;
+		len  = width;
+	    } else {
+		src += src_x * 4;
+		len  = width * 4;
+	    }
+
+	    for (i = 0; i < height; i++) {
+		direct_memcpy (dst, src, len);
+		dst += pitch;
+		src += image_src->stride;
+	    }
+	}
+
+	clone->dfbsurface->Unlock (clone->dfbsurface);
+
+	*clone_offset_x = src_x;
+	*clone_offset_y = src_y;
+	*clone_out = &clone->base;
+	return CAIRO_STATUS_SUCCESS;
     }
-    
+
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _directfb_prepare_composite (cairo_directfb_surface_t    *dst,
                              cairo_pattern_t             *src_pattern,
                              cairo_pattern_t             *mask_pattern,
                              cairo_operator_t             op,
                              int *src_x,             int *src_y,
                              int *mask_x,            int *mask_y,
                              unsigned int                 width,
-                             unsigned int                 height,                        
+                             unsigned int                 height,
                              cairo_directfb_surface_t   **ret_src,
                              cairo_surface_attributes_t  *ret_src_attr)
 {
     cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
-    cairo_status_t              ret;
+    cairo_status_t              status;
     DFBSurfaceBlittingFlags     flags;
     DFBSurfaceBlendFunction     sblend;
     DFBSurfaceBlendFunction     dblend;
-    DFBColor                    color;
-    
-    if (_directfb_get_operator (op, &sblend, &dblend))
+    const cairo_color_t        *color;
+
+    /* XXX Unbounded operators are not handled correctly */
+    if (! _cairo_operator_bounded_by_source (op))
         return CAIRO_INT_STATUS_UNSUPPORTED;
-     
+
+    if (! _directfb_get_operator (op, &sblend, &dblend))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     if (mask_pattern) {
-        cairo_solid_pattern_t *pattern;
-        
-        if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
-            cairo_pattern_t *tmp;
-            int              tmp_x, tmp_y;
-            
-            if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
-                sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
-                return CAIRO_INT_STATUS_UNSUPPORTED;
-                
-            D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
-                
-            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;
-            *mask_x = tmp_x; *mask_y = tmp_y;
-            
-            if (sblend == DSBF_ONE) {                  
-                sblend = DSBF_SRCALPHA;
-                /*dblend = DSBF_INVSRCALPHA;*/
-            }
-        }
-            
-        pattern = (cairo_solid_pattern_t *)mask_pattern;
-        color.a = pattern->color.alpha_short >> 8;
-        color.r = pattern->color.red_short   >> 8;
-        color.g = pattern->color.green_short >> 8;
-        color.b = pattern->color.blue_short  >> 8;
-    } 
-    else {
-        color.a = color.r = color.g = color.b = 0xff;
-    }
-        
-    if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
-        cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *)src_pattern;
-         
-        if (!dst->color) {
-            dst->color = _cairo_directfb_surface_create_similar (dst,
-                                                CAIRO_CONTENT_COLOR_ALPHA, 1, 1);
-            if (!dst->color)
-                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        }
-        
-        src = (cairo_directfb_surface_t *)dst->color;
-        src->dfbsurface->Clear (src->dfbsurface,
-                                pattern->color.red_short   >> 8,
-                                pattern->color.green_short >> 8,
-                                pattern->color.blue_short  >> 8,
-                                pattern->color.alpha_short >> 8);
-                                  
-        src_attr.matrix   = src_pattern->matrix;
-        src_attr.extend   = CAIRO_EXTEND_NONE;
-        src_attr.filter   = CAIRO_FILTER_NEAREST;
-        src_attr.x_offset =
-        src_attr.y_offset = 0;
-    }
-    else {
-        ret = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
-                                              *src_x, *src_y, width, height,
-                                              (cairo_surface_t **)&src, &src_attr);
-        if (ret)
-            return ret;
-    }
-    
-    if (src->content == CAIRO_CONTENT_COLOR) {
-        if (sblend == DSBF_SRCALPHA)
-            sblend = DSBF_ONE;
-        else if (sblend == DSBF_INVSRCALPHA)
-            sblend = DSBF_ZERO;
-            
-        if (dblend == DSBF_SRCALPHA)
-            dblend = DSBF_ONE;
-        else if (dblend == DSBF_INVSRCALPHA)
-            dblend = DSBF_ZERO;
-    }
-    if (dst->content == CAIRO_CONTENT_COLOR) {
-        if (sblend == DSBF_DESTALPHA)
-            sblend = DSBF_ONE;
-        else if (sblend == DSBF_INVDESTALPHA)
-            sblend = DSBF_ZERO;
-         
-        if (dblend == DSBF_DESTALPHA)
-            dblend = DSBF_ONE;
-        else if (dblend == DSBF_INVDESTALPHA)
-            dblend = DSBF_ZERO;   
+	cairo_solid_pattern_t *pattern;
+
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	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 (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;
+	    *mask_x = tmp_x; *mask_y = tmp_y;
+
+	    if (sblend == DSBF_ONE) {
+		sblend = DSBF_SRCALPHA;
+		/*dblend = DSBF_INVSRCALPHA;*/
+	    }
+	}
+
+	color = &((cairo_solid_pattern_t *) mask_pattern)->color;
+    } else {
+	color = _cairo_stock_color (CAIRO_STOCK_WHITE);
     }
 
-    flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) 
-            ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; 
-    if (color.a != 0xff)
-        flags |= DSBLIT_BLEND_COLORALPHA;
-    if (color.r != 0xff || color.g != 0xff || color.b != 0xff)
-        flags |= DSBLIT_COLORIZE;
-            
+    /* XXX DirectFB currently does not support filtering, so force NEAREST
+     * in order to hit optimisations inside core.
+    */
+    src_pattern->filter = CAIRO_FILTER_NEAREST;
+
+    status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+					     *src_x, *src_y, width, height,
+					     (cairo_surface_t **) &src,
+					     &src_attr);
+    if (status)
+	return status;
+
+    if (src->base.backend != &_cairo_directfb_surface_backend ||
+	src->dfb != dst->dfb)
+    {
+	_cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (src->content == CAIRO_CONTENT_COLOR) {
+	if (sblend == DSBF_SRCALPHA)
+	    sblend = DSBF_ONE;
+	else if (sblend == DSBF_INVSRCALPHA)
+	    sblend = DSBF_ZERO;
+
+	if (dblend == DSBF_SRCALPHA)
+	    dblend = DSBF_ONE;
+	else if (dblend == DSBF_INVSRCALPHA)
+	    dblend = DSBF_ZERO;
+    }
+
+    if (dst->content == CAIRO_CONTENT_COLOR) {
+	if (sblend == DSBF_DESTALPHA)
+	    sblend = DSBF_ONE;
+	else if (sblend == DSBF_INVDESTALPHA)
+	    sblend = DSBF_ZERO;
+
+	if (dblend == DSBF_DESTALPHA)
+	    dblend = DSBF_ONE;
+	else if (dblend == DSBF_INVDESTALPHA)
+	    dblend = DSBF_ZERO;
+    }
+
+    flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO)
+	? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL;
+    if (! CAIRO_COLOR_IS_OPAQUE (color))
+	flags |= DSBLIT_BLEND_COLORALPHA;
+    if (! _cairo_color_equal (color, _cairo_stock_color (CAIRO_STOCK_WHITE)))
+	flags |= DSBLIT_COLORIZE;
+
     dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
-    
+
     if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
-        dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
-        dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
+	dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
+	dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
     }
-    
-    if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE))    
-        dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); 
-        
+
+    if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) {
+	if (dst->blit_premultiplied) {
+	    dst->dfbsurface->SetColor (dst->dfbsurface,
+				       color->red_short >> 8,
+				       color->green_short >> 8,
+				       color->blue_short >> 8,
+				       color->alpha_short >> 8);
+	} else {
+	    dst->dfbsurface->SetColor (dst->dfbsurface,
+				       color->red * 0xff,
+				       color->green * 0xff,
+				       color->blue * 0xff,
+				       color->alpha * 0xff);
+	}
+    }
+
     *ret_src = src;
     *ret_src_attr = src_attr;
-    
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _directfb_finish_composite (cairo_directfb_surface_t   *dst,
                             cairo_pattern_t            *src_pattern,
                             cairo_surface_t            *src,
                             cairo_surface_attributes_t *src_attr)
 {
-    if (src != dst->color)
-         _cairo_pattern_release_surface (src_pattern, src, src_attr);
+    _cairo_pattern_release_surface (src_pattern, src, src_attr);
 }
-#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */        
+#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
 
 #if DFB_COMPOSITE
 static DFBAccelerationMask
 _directfb_categorize_operation (cairo_surface_attributes_t *src_attr)
 {
     cairo_matrix_t *m = &src_attr->matrix;
-    
+
     if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) {
-        if (src_attr->extend != CAIRO_EXTEND_NONE)
-            return DFXL_NONE;
-        return DFXL_TEXTRIANGLES;
+	if (src_attr->extend != CAIRO_EXTEND_NONE)
+	    return DFXL_NONE;
+
+	return DFXL_TEXTRIANGLES;
     }
-        
+
     if (m->xx != 1 || m->yy != 1) {
-        if (src_attr->extend != CAIRO_EXTEND_NONE)
-            return DFXL_NONE;
-        return DFXL_STRETCHBLIT;
+	if (src_attr->extend != CAIRO_EXTEND_NONE)
+	    return DFXL_NONE;
+
+	return DFXL_STRETCHBLIT;
     }
-     
-    if (src_attr->extend != CAIRO_EXTEND_NONE &&
-        src_attr->extend != CAIRO_EXTEND_REPEAT)
-        return DFXL_NONE;
-           
-    return DFXL_BLIT;
+
+    switch (src_attr->extend) {
+    case CAIRO_EXTEND_NONE:
+    case CAIRO_EXTEND_REPEAT:
+	if (_cairo_matrix_is_integer_translation (&src_attr->matrix,
+						  NULL, NULL))
+	{
+	    return DFXL_BLIT;
+	}
+	else
+	{
+	    return DFXL_STRETCHBLIT;
+	}
+
+    default:
+    case CAIRO_EXTEND_REFLECT:
+    case CAIRO_EXTEND_PAD:
+	return DFXL_NONE;
+    }
 }
 
 static cairo_int_status_t
 _cairo_directfb_surface_composite (cairo_operator_t  op,
                                    cairo_pattern_t  *src_pattern,
                                    cairo_pattern_t  *mask_pattern,
                                    void             *abstract_dst,
                                    int  src_x,  int  src_y,
                                    int  mask_x, int  mask_y,
                                    int  dst_x,  int  dst_y,
                                    unsigned int      width,
                                    unsigned int      height)
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
     cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
+    cairo_bool_t                is_integer_translation;
     DFBAccelerationMask         accel, mask;
-    cairo_int_status_t          ret;
-    
+    cairo_int_status_t          status;
+    int                         tx, ty;
+
     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;
-        
+		"%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);
+
+    status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
+					  &src_x, &src_y, &mask_x, &mask_y,
+					  width, height, &src, &src_attr);
+    if (status)
+	return status;
+
     accel = _directfb_categorize_operation (&src_attr);
-    
-    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &mask);
-    if (!(mask & 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;
-        }
+    if (accel == DFXL_NONE) {
+	_directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
-    
+
+    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
+					  src->dfbsurface,
+					  &mask);
+    if ((mask & accel) == 0) {
+	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;
-    
+
     switch (accel) {
-        case DFXL_BLIT: {
-            DFBRectangle sr;
-        
-            sr.x = src_x + _cairo_lround (src_attr.matrix.x0);
-            sr.y = src_y + _cairo_lround (src_attr.matrix.y0);
-            sr.w = width;
-            sr.h = height;
-        
-            if (src_attr.extend == CAIRO_EXTEND_NONE) {
-                D_DEBUG_AT (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 (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: {
-            DFBRectangle sr, dr;
-            double       x1, y1, x2, y2;
-            
-            TRANSFORM_POINT2X (src_attr.matrix, 
-                               src_x, src_y, x1, y1);
-            TRANSFORM_POINT2X (src_attr.matrix, 
-                               src_x+width, src_y+height, x2, y2);
-                               
-            sr.x = _cairo_lround (x1);
-            sr.y = _cairo_lround (y1);
-            sr.w = _cairo_lround (x2-x1);
-            sr.h = _cairo_lround (y2-y1);
-            
-            dr.x = dst_x;
-            dr.y = dst_y;
-            dr.w = width;
-            dr.h = height;
-            
-            D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n");
+    case DFXL_BLIT:
+	{
+	    DFBRectangle sr;
+
+	    is_integer_translation =
+		_cairo_matrix_is_integer_translation (&src_attr.matrix,
+						      &tx, &ty);
+	    assert (is_integer_translation);
+
+	    sr.x = src_x + tx;
+	    sr.y = src_y + ty;
+	    sr.w = width;
+	    sr.h = height;
+
+	    if (src_attr.extend == CAIRO_EXTEND_NONE) {
+		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 (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:
+	{
+	    DFBRectangle sr, dr;
+	    double       x1, y1, x2, y2;
+
+	    TRANSFORM_POINT2X (src_attr.matrix,
+			       src_x, src_y, x1, y1);
+	    TRANSFORM_POINT2X (src_attr.matrix,
+			       src_x+width, src_y+height, x2, y2);
+
+	    sr.x = floor (x1);
+	    sr.y = floor (y1);
+	    sr.w = ceil (x2) - sr.x;
+	    sr.h = ceil (y2) - sr.y;
+
+	    dr.x = dst_x;
+	    dr.y = dst_y;
+	    dr.w = width;
+	    dr.h = height;
+
+	    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;
-            DFBVertex v[4];
-            float     x1, y1, x2, y2;
-            int       w, h;
-            
-            if (cairo_matrix_invert (&src_attr.matrix) != CAIRO_STATUS_SUCCESS) {
-                ret = CAIRO_INT_STATUS_UNSUPPORTED;
-                break;
-            }
-            
-            x1 = src_attr.x_offset;
-            y1 = src_attr.y_offset;
-            x2 = src->width  - x1;
-            y2 = src->height - y1;
-            
-            src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
-            
-            TRANSFORM_POINT3X (src_attr.matrix, 
-                               x1, y1, v[0].x, v[0].y);
-            v[0].z = 0;
-            v[0].w = 1;
-            v[0].s = x1 / w;
-            v[0].t = y1 / h;
-        
-            TRANSFORM_POINT3X (src_attr.matrix, 
-                               x2, y1, v[1].x, v[1].y);
-            v[1].z = 0;
-            v[1].w = 1;
-            v[1].s = x2 / w;
-            v[1].t = y1 / h;
-        
-            TRANSFORM_POINT3X (src_attr.matrix,
-                               x2, y2, v[2].x, v[2].y);
-            v[2].z = 0;
-            v[2].w = 1;
-            v[2].s = x2 / w;
-            v[2].t = y2 / h;
-        
-            TRANSFORM_POINT3X (src_attr.matrix, 
-                               x1, y2, v[3].x, v[3].y);
-            v[3].z = 0;
-            v[3].w = 1;
-            v[3].s = x1 / w;
-            v[3].t = y2 / h;
-            
-            clip.x1 = dst_x;
-            clip.y1 = dst_y;
-            clip.x2 = dst_x + width  - 1;
-            clip.y2 = dst_y + height - 1;
-        
-            D_DEBUG_AT (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");
-            break;
+	    RUN_CLIPPED (dst, NULL,
+			 dst->dfbsurface->StretchBlit (dst->dfbsurface,
+						       src->dfbsurface, &sr, &dr));
+	    break;
+	}
+
+    case DFXL_TEXTRIANGLES:
+	{
+	    DFBRegion clip;
+	    DFBVertex v[4];
+	    float     x1, y1, x2, y2;
+	    int       w, h;
+
+	    status = cairo_matrix_invert (&src_attr.matrix);
+	    /* guaranteed by cairo_pattern_set_matrix (); */
+	    assert (status == CAIRO_STATUS_SUCCESS);
+
+	    x1 = src_x;
+	    y1 = src_y;
+	    x2 = width  + x1;
+	    y2 = height + y1;
+
+	    src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
+
+	    TRANSFORM_POINT3X (src_attr.matrix,
+			       x1, y1, v[0].x, v[0].y);
+	    v[0].z = 0;
+	    v[0].w = 1;
+	    v[0].s = x1 / w;
+	    v[0].t = y1 / h;
+
+	    TRANSFORM_POINT3X (src_attr.matrix,
+			       x2, y1, v[1].x, v[1].y);
+	    v[1].z = 0;
+	    v[1].w = 1;
+	    v[1].s = x2 / w;
+	    v[1].t = y1 / h;
+
+	    TRANSFORM_POINT3X (src_attr.matrix,
+			       x2, y2, v[2].x, v[2].y);
+	    v[2].z = 0;
+	    v[2].w = 1;
+	    v[2].s = x2 / w;
+	    v[2].t = y2 / h;
+
+	    TRANSFORM_POINT3X (src_attr.matrix,
+			       x1, y2, v[3].x, v[3].y);
+	    v[3].z = 0;
+	    v[3].w = 1;
+	    v[3].s = x1 / w;
+	    v[3].t = y2 / h;
+
+	    clip.x1 = dst_x;
+	    clip.y1 = dst_y;
+	    clip.x2 = dst_x + width  - 1;
+	    clip.y2 = dst_y + height - 1;
+
+	    D_DEBUG_AT (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");
+	break;
     }
 
     _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
-    
-    return ret;
+
+    return status;
 }
 #endif /* DFB_COMPOSITE */
 
 #if DFB_RECTANGLES
 static cairo_int_status_t
 _cairo_directfb_surface_fill_rectangles (void                  *abstract_surface,
                                          cairo_operator_t       op,
                                          const cairo_color_t   *color,
@@ -1049,316 +1091,320 @@ static cairo_int_status_t
                                          int                    n_rects)
 {
     cairo_directfb_surface_t *dst   = abstract_surface;
     DFBSurfaceDrawingFlags    flags;
     DFBSurfaceBlendFunction   sblend;
     DFBSurfaceBlendFunction   dblend;
     DFBRectangle              r[n_rects];
     int                       i;
-    
-    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))
+    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 (! _cairo_operator_bounded_by_source (op))
         return CAIRO_INT_STATUS_UNSUPPORTED;
-        
-    if (color->alpha_short >= 0xff00) {
-        if (sblend == DSBF_SRCALPHA)
-            sblend = DSBF_ONE;
-        else if (sblend == DSBF_INVSRCALPHA)
-            sblend = DSBF_ZERO;
-            
-        if (dblend == DSBF_SRCALPHA)
-            dblend = DSBF_ONE;
-        else if (dblend == DSBF_INVSRCALPHA)
-            dblend = DSBF_ZERO;
+
+    if (! _directfb_get_operator (op, &sblend, &dblend))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (CAIRO_COLOR_IS_OPAQUE (color)) {
+	if (sblend == DSBF_SRCALPHA)
+	    sblend = DSBF_ONE;
+	else if (sblend == DSBF_INVSRCALPHA)
+	    sblend = DSBF_ZERO;
+
+	if (dblend == DSBF_SRCALPHA)
+	    dblend = DSBF_ONE;
+	else if (dblend == DSBF_INVSRCALPHA)
+	    dblend = DSBF_ZERO;
     }
     if (dst->content == CAIRO_CONTENT_COLOR) {
-        if (sblend == DSBF_DESTALPHA)
-            sblend = DSBF_ONE;
-        else if (sblend == DSBF_INVDESTALPHA)
-            sblend = DSBF_ZERO;
-         
-        if (dblend == DSBF_DESTALPHA)
-            dblend = DSBF_ONE;
-        else if (dblend == DSBF_INVDESTALPHA)
-            dblend = DSBF_ZERO;   
+	if (sblend == DSBF_DESTALPHA)
+	    sblend = DSBF_ONE;
+	else if (sblend == DSBF_INVDESTALPHA)
+	    sblend = DSBF_ZERO;
+
+	if (dblend == DSBF_DESTALPHA)
+	    dblend = DSBF_ONE;
+	else if (dblend == DSBF_INVDESTALPHA)
+	    dblend = DSBF_ZERO;
     }
-    
+
     flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND;
     dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags);
     if (flags & DSDRAW_BLEND) {
-        dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
-        dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
-    }    
-    
-    dst->dfbsurface->SetColor (dst->dfbsurface, 
-                               color->red_short   >> 8,
-                               color->green_short >> 8, 
-                               color->blue_short  >> 8, 
-                               color->alpha_short >> 8 );
-       
+	dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
+	dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
+    }
+
+    dst->dfbsurface->SetColor (dst->dfbsurface,
+			       color->red_short >> 8,
+			       color->green_short >> 8,
+			       color->blue_short >> 8,
+			       color->alpha_short >> 8);
+
     for (i = 0; i < n_rects; i++) {
-        r[i].x = rects[i].x;
-        r[i].y = rects[i].y;
-        r[i].w = rects[i].width;
-        r[i].h = rects[i].height;
+	r[i].x = rects[i].x;
+	r[i].y = rects[i].y;
+	r[i].w = rects[i].width;
+	r[i].h = rects[i].height;
     }
-     
+
     RUN_CLIPPED (dst, NULL,
-                 dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
-    
+		 dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
+
     return CAIRO_STATUS_SUCCESS;
 }
 #endif
 
 #if DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t   op,
                                               cairo_pattern_t   *pattern,
                                               void              *abstract_dst,
                                               cairo_antialias_t  antialias,
                                               int  src_x,   int  src_y,
                                               int  dst_x,   int  dst_y,
                                               unsigned int       width,
                                               unsigned int       height,
                                               cairo_trapezoid_t *traps,
-                                              int                num_traps )
+                                              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;
+    cairo_status_t              status;
     DFBAccelerationMask         accel;
-    
+
     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;
-        
+
     /* Textures are not supported yet. */
     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
         return CAIRO_INT_STATUS_UNSUPPORTED;
-    
-    ret = _directfb_prepare_composite (dst, pattern, NULL, op,
-                                       &src_x, &src_y, NULL, NULL, 
-                                       width, height, &src, &src_attr);
-    if (ret)
-        return ret;
-   
-    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel);
-    
-    ret = CAIRO_INT_STATUS_UNSUPPORTED;
-    
+
+    status = _directfb_prepare_composite (dst, pattern, NULL, op,
+					  &src_x, &src_y, NULL, NULL,
+					  width, height, &src, &src_attr);
+    if (status)
+        return status;
+
+    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
+					  src->dfbsurface,
+					  &accel);
+
+    status = CAIRO_INT_STATUS_UNSUPPORTED;
+
     if (accel & DFXL_TEXTRIANGLES) {
         DFBVertex  vertex[6*num_traps];
         DFBVertex *v = &vertex[0];
-        int        n;
-      
-#define ADD_TRI(id, x1, y1, s1, t1, x2, y2, s2, t2, x3, y3, s3, t3) {\
+        int        n = 0;
+
+#define ADD_TRI_V(V, X, Y) do { \
+    (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \
+} while (0)
+#define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\
     const int p = (id)*3;\
-    v[p+0].x=(x1); v[p+0].y=(y1); v[p+0].z=0; v[p+0].w=1; v[p+0].s=(s1); v[p+0].t=(t1);\
-    v[p+1].x=(x2); v[p+1].y=(y2); v[p+1].z=0; v[p+1].w=1; v[p+1].s=(s2); v[p+1].t=(t2);\
-    v[p+2].x=(x3); v[p+2].y=(y3); v[p+2].z=0; v[p+2].w=1; v[p+2].s=(s3); v[p+2].t=(t3);\
-}         
-       
-        for (n = 0; num_traps; num_traps--) {
-            float lx1, ly1, lx2, ly2;
-            float rx1, ry1, rx2, ry2;
-            
-            /* XXX: Do we need to validate the trapezoid? */
- 
-            lx1 = traps->left.p1.x/65536.0;
-            ly1 = traps->left.p1.y/65536.0;
-            lx2 = traps->left.p2.x/65536.0;
-            ly2 = traps->left.p2.y/65536.0;
-            rx1 = traps->right.p1.x/65536.0;
-            ry1 = traps->right.p1.y/65536.0;
-            rx2 = traps->right.p2.x/65536.0;
-            ry2 = traps->right.p2.y/65536.0;
-            
+    ADD_TRI_V (v+p+0, x1, y1); \
+    ADD_TRI_V (v+p+1, x2, y2); \
+    ADD_TRI_V (v+p+2, x3, y3); \
+} while (0)
+	while (num_traps--) {
+            double lx1, ly1, lx2, ly2;
+            double rx1, ry1, rx2, ry2;
+
+            lx1 = _cairo_fixed_to_double (traps->left.p1.x);
+            ly1 = _cairo_fixed_to_double (traps->left.p1.y);
+            lx2 = _cairo_fixed_to_double (traps->left.p2.x);
+            ly2 = _cairo_fixed_to_double (traps->left.p2.y);
+            rx1 = _cairo_fixed_to_double (traps->right.p1.x);
+            ry1 = _cairo_fixed_to_double (traps->right.p1.y);
+            rx2 = _cairo_fixed_to_double (traps->right.p2.x);
+            ry2 = _cairo_fixed_to_double (traps->right.p2.y);
+
             if (traps->left.p1.y < traps->top) {
-                float y = traps->top/65536.0;
+                double y = _cairo_fixed_to_double (traps->top);
                 if (lx2 != lx1)
                     lx1 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
                 ly1 = y;
-            } 
+            }
             if (traps->left.p2.y > traps->bottom) {
-                float y = traps->bottom/65536.0;
+                double y = _cairo_fixed_to_double (traps->bottom);
                 if (lx2 != lx1)
                     lx2 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
                 ly2 = y;
             }
-            
+
             if (traps->right.p1.y < traps->top) {
-                float y = traps->top/65536.0;
+                double y = _cairo_fixed_to_double (traps->top);
                 if (rx2 != rx1)
                     rx1 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
                 ry1 = y;
             }
             if (traps->right.p2.y > traps->bottom) {
-                float y = traps->bottom/65536.0;
+                double y = _cairo_fixed_to_double (traps->bottom);
                 if (rx2 != rx1)
                     rx2 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
                 ry2 = y;
             }
-             
+
             if (lx1 == rx1 && ly1 == ry1) {
-                ADD_TRI (0, lx2, ly2, 0, 0,
-                            lx1, ly1, 0, 0,
-                            rx2, ry2, 0, 0 );
+                ADD_TRI (0, lx2, ly2, lx1, ly1, rx2, ry2);
                 v += 3;
                 n += 3;
-            }
-            else if (lx2 == rx2 && ly2 == ry2) {
-                ADD_TRI (0, lx1, ly1, 0, 0,
-                            lx2, ly2, 0, 0,
-                            rx1, ry1, 0, 0 );
+            } else if (lx2 == rx2 && ly2 == ry2) {
+                ADD_TRI (0, lx1, ly1, lx2, ly2, rx1, ry1);
                 v += 3;
                 n += 3;
-            }
-            else {
-                ADD_TRI (0, lx1, ly1, 0, 0, 
-                            rx1, ry1, 0, 0,
-                            lx2, ly2, 0, 0);
-                ADD_TRI (1, lx2, ly2, 0, 0,
-                            rx1, ry1, 0, 0,
-                            rx2, ry2, 0, 0);            
+            } else {
+                ADD_TRI (0, lx1, ly1, rx1, ry1, lx2, ly2);
+                ADD_TRI (1, lx2, ly2, rx1, ry1, rx2, ry2);
                 v += 6;
                 n += 6;
             }
-            
+
             traps++;
         }
-        
 #undef ADD_TRI
-              
+#undef ADD_TRI_V
+
         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;
+                     dst->dfbsurface->TextureTriangles (dst->dfbsurface,
+							src->dfbsurface,
+							vertex, NULL, n,
+							DTTF_LIST));
+
+        status = CAIRO_STATUS_SUCCESS;
     }
-    
+
     _directfb_finish_composite (dst, pattern, &src->base, &src_attr);
 
-    return ret;
+    return status;
 }
 #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 (CairoDFB_Clip, 
-                "%s( surface=%p, region=%p ).\n",
-                __FUNCTION__, surface, region);
-    
+
+    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;
+	cairo_box_int_t *boxes;
+	int              n_boxes;
+	cairo_status_t   status;
+	int              i;
+
+	surface->has_clip = TRUE;
+
+	status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
+	if (n_boxes == 0)
+	    return CAIRO_STATUS_SUCCESS;
+	if (status)
+	    return status;
+
+	if (surface->n_clips != n_boxes) {
+	    if (surface->clips)
+		free (surface->clips);
 
-        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));
-            if (!surface->clips) {
-                surface->n_clips = 0;
-                _cairo_region_boxes_fini (region, boxes);
-                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-            }
-        
-            surface->n_clips = n_boxes;
-        }
-        
-        for (i = 0; i < n_boxes; i++) {
-            surface->clips[i].x1 = boxes[i].p1.x;
-            surface->clips[i].y1 = boxes[i].p1.y;
-            surface->clips[i].x2 = boxes[i].p2.x;
-            surface->clips[i].y2 = boxes[i].p2.y;
-        }
+	    surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion));
+	    if (!surface->clips) {
+		surface->n_clips = 0;
+		_cairo_region_boxes_fini (region, boxes);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+
+	    surface->n_clips = n_boxes;
+	}
 
-        _cairo_region_boxes_fini (region, boxes);
-    }
-    else {
-        if (surface->clips) {
-            free (surface->clips);
-            surface->clips = NULL;
-            surface->n_clips = 0;
-        }
+	for (i = 0; i < n_boxes; i++) {
+	    surface->clips[i].x1 = boxes[i].p1.x;
+	    surface->clips[i].y1 = boxes[i].p1.y;
+	    surface->clips[i].x2 = boxes[i].p2.x - 1;
+	    surface->clips[i].y2 = boxes[i].p2.y - 1;
+	}
+
+	_cairo_region_boxes_fini (region, boxes);
+    } else {
+	surface->has_clip = FALSE;
+	if (surface->clips) {
+	    free (surface->clips);
+	    surface->clips = NULL;
+	    surface->n_clips = 0;
+	}
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 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 (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);
-        }   
-        rectangle->x = 0;
-        rectangle->y = 0;
-        rectangle->width  = surface->width;
-        rectangle->height = surface->height;
+		"%s( surface=%p, rectangle=%p ).\n",
+		__FUNCTION__, surface, rectangle);
+
+    if (!surface->local) {
+	surface->dfbsurface->GetSize (surface->dfbsurface,
+				      &surface->width, &surface->height);
     }
-    
+
+    rectangle->x = 0;
+    rectangle->y = 0;
+    rectangle->width  = surface->width;
+    rectangle->height = surface->height;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 #if DFB_SHOW_GLYPHS
-static cairo_directfb_font_cache_t*
-_directfb_allocate_font_cache (IDirectFB *dfb, int width, int height)
+static cairo_status_t
+_directfb_allocate_font_cache (IDirectFB *dfb,
+			       int width, int height,
+			       cairo_directfb_font_cache_t **out)
 {
     cairo_directfb_font_cache_t *cache;
+    cairo_status_t status;
 
-    cache = calloc (1, sizeof(cairo_directfb_font_cache_t));
-    if (!cache)
-        return NULL;
+    cache = calloc (1, sizeof (cairo_directfb_font_cache_t));
+    if (cache == NULL)
+        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     cache->dfb = dfb;
-    cache->dfbsurface = _directfb_buffer_surface_create (dfb, 
-                            _directfb_argb_font ? DSPF_ARGB : DSPF_A8, width, height);
-    if (!cache->dfbsurface) {
+    status = _directfb_buffer_surface_create (dfb,
+                            _directfb_argb_font ? DSPF_ARGB : DSPF_A8,
+			    width, height,
+			    &cache->dfbsurface);
+    if (status) {
         free (cache);
-        return NULL;
+	return status;
     }
+
     cache->width  = width;
     cache->height = height;
-
-    return cache;
+    *out = cache;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
 {
     cache->dfbsurface->Release (cache->dfbsurface);
     free (cache);
 }
@@ -1366,374 +1412,400 @@ static void
 static cairo_status_t
 _directfb_acquire_font_cache (cairo_directfb_surface_t     *surface,
                               cairo_scaled_font_t          *scaled_font,
                               const cairo_glyph_t          *glyphs,
                               int                           num_glyphs,
                               cairo_directfb_font_cache_t **ret_cache,
                               DFBRectangle                 *rects,
                               DFBPoint                     *points,
-                              int                          *ret_num )
+			      int                          *ret_num)
 {
-    cairo_status_t               ret;
+    cairo_status_t               status;
     cairo_scaled_glyph_t        *chars[num_glyphs];
     int                          num_chars = 0;
-    cairo_directfb_font_cache_t *cache     = NULL; 
+    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 );
 
+    _cairo_cache_freeze (scaled_font->glyphs);
+
     if (scaled_font->surface_private) {
-        cache = scaled_font->surface_private;
-        x = cache->x;
-        y = cache->y;
+	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 );
+	cairo_scaled_glyph_t  *scaled_glyph;
+	cairo_image_surface_t *img;
+
+	D_DEBUG_AT (CairoDFB_Font, "  -> [%2d] = %4lu\n", i, glyphs[i].index );
+
+	status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
+					  CAIRO_SCALED_GLYPH_INFO_SURFACE,
+					  &scaled_glyph);
+	if (status) {
+	    _cairo_cache_thaw (scaled_font->glyphs);
+	    return status;
+	}
 
-        ret = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
-                                          CAIRO_SCALED_GLYPH_INFO_SURFACE,
-                                          &scaled_glyph);
-        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 (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 );
+	img = scaled_glyph->surface;
+	switch (img->format) {
+	case CAIRO_FORMAT_A1:
+	case CAIRO_FORMAT_A8:
+	case CAIRO_FORMAT_ARGB32:
+	    break;
+	default:
+	    D_DEBUG_AT (CairoDFB_Font,
+			"  -> Unsupported font format %d!\n", img->format);
+	    _cairo_cache_thaw (scaled_font->glyphs);
+	    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;
+	}
+
+	if (scaled_glyph->surface_private == NULL) {
+	    DFBRectangle *rect;
 
-        if (points[n].x >= surface->width  ||
-            points[n].y >= surface->height ||
-            points[n].x+img->width  <= 0   ||
-            points[n].y+img->height <= 0)
-        {
-             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;
-            }
-        
-            rects[n].x = x;
-            rects[n].y = y;
-            rects[n].w = img->width;
-            rects[n].h = img->height;
- 
-            x += img->width;
-            h  = MAX (h, img->height);
-            w  = MAX (w, x);
-            
-            /* Remember glyph location */ 
-            rect = malloc (sizeof(DFBRectangle));
-            if (!rect) {
-                _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 (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 (CairoDFB_Font, "  -> exists at  %4d,%2d\n", rects[n].x, rects[n].y);
-        }
-            
-        n++;
+	    if (x+img->width > 2048) {
+		x = 0;
+		y = h;
+		h = 0;
+	    }
+
+	    rects[n].x = x;
+	    rects[n].y = y;
+	    rects[n].w = img->width;
+	    rects[n].h = img->height;
+
+	    x += img->width;
+	    h  = MAX (h, img->height);
+	    w  = MAX (w, x);
+
+	    /* Remember glyph location */
+	    rect = malloc (sizeof (DFBRectangle));
+	    if (rect == NULL) {
+		_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 (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 (CairoDFB_Font, "  -> exists at  %4d,%2d\n", rects[n].x, rects[n].y);
+	}
+
+	n++;
     }
-    
-    if (!n) {
-        _cairo_cache_thaw( scaled_font->glyphs );
-        return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+    if (n == 0) {
+	_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 (CairoDFB_Font, "  -> Reallocating font cache (%dx%d).\n", w, h);
-            
-            new_cache = _directfb_allocate_font_cache (surface->dfb, w, h);
-            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;
-        }
+
+    /* XXX query maximum surface size */
+    if (w > 2048 || h > 2048) {
+	_cairo_cache_thaw (scaled_font->glyphs);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
-    else {
-        D_DEBUG_AT (CairoDFB_Font, "  -> Allocating font cache (%dx%d).\n", w, h);
-        
-        cache = _directfb_allocate_font_cache (surface->dfb, w, h);
-        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);
+
+    if (cache) {
+	if (cache->width < w || cache->height < h) {
+	    cairo_directfb_font_cache_t *new_cache;
+
+	    w = MAX (w, cache->width);
+	    h = MAX (h, cache->height);
+
+	    D_DEBUG_AT (CairoDFB_Font, "  -> Reallocating font cache (%dx%d).\n", w, h);
 
-        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;
-            int                    j;
-            
-            D_DEBUG_AT (CairoDFB_Font, "  -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]);
+	    status = _directfb_allocate_font_cache (surface->dfb,
+						    w, h,
+						    &new_cache);
+	    if (status) {
+		_cairo_cache_thaw (scaled_font->glyphs);
+		return status;
+	    }
 
-            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);
+	    new_cache->dfbsurface->Blit (new_cache->dfbsurface,
+					 cache->dfbsurface, NULL, 0, 0);
 
-            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++)
-                            dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0;
-                    }
-                    
-                    dst += pitch;
-                    src += img->stride;
-                }
-            }
-            else if (img->format == CAIRO_FORMAT_A8) {
-                for (h = rect->h; h; h--) {
-                    if (_directfb_argb_font) {
-                        for (j = 0; j < rect->w; j++)
-                            ((uint32_t *)dst)[j] = src[j] * 0x01010101;
-                    }
-                    else {
-                        direct_memcpy (dst, src, rect->w);
-                    }
-                    
-                    dst += pitch;
-                    src += img->stride;
-                }
-            }
-            else { /* ARGB32 */
-                for (h = rect->h; h; h--) {
-                    if (_directfb_argb_font) {
-                        direct_memcpy (dst, src, rect->w<<2);
-                    }
-                    else {
-                        for (j = 0; j < rect->w; j++)
-                            dst[j] = ((uint32_t *)src)[j] >> 24;
-                    }
-                    
-                    dst += pitch;
-                    src += img->stride;
-                }
-            }
-        }
-        
-        cache->dfbsurface->Unlock (cache->dfbsurface);
+	    _directfb_destroy_font_cache (cache);
+	    scaled_font->surface_private = cache = new_cache;
+	}
+    } else {
+	D_DEBUG_AT (CairoDFB_Font, "  -> Allocating font cache (%dx%d).\n", w, h);
+
+	status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache);
+	if (status) {
+	    _cairo_cache_thaw (scaled_font->glyphs);
+	    return status;
+	}
+
+	scaled_font->surface_backend = &_cairo_directfb_surface_backend;
+	scaled_font->surface_private = cache;
     }
 
-    _cairo_cache_thaw( scaled_font->glyphs );
+    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;
+	    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++)
+			    dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0;
+		    }
+
+		    dst += pitch;
+		    src += img->stride;
+		}
+	    } else if (img->format == CAIRO_FORMAT_A8) {
+		for (h = rect->h; h; h--) {
+		    if (_directfb_argb_font) {
+			for (j = 0; j < rect->w; j++)
+			    ((uint32_t *) dst)[j] = src[j] * 0x01010101;
+		    } else {
+			direct_memcpy (dst, src, rect->w);
+		    }
+
+		    dst += pitch;
+		    src += img->stride;
+		}
+	    } else { /* ARGB32 */
+		for (h = rect->h; h; h--) {
+		    if (_directfb_argb_font) {
+			direct_memcpy (dst, src, rect->w<<2);
+		    } else {
+			for (j = 0; j < rect->w; j++)
+			    dst[j] = ((uint32_t *) src)[j] >> 24;
+		    }
+
+		    dst += pitch;
+		    src += img->stride;
+		}
+	    }
+	}
+
+	cache->dfbsurface->Unlock (cache->dfbsurface);
+    }
+
+    _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 (CairoDFB_Font,
-                "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font);
-    
-    if (cache) {
-        _directfb_destroy_font_cache (cache);
-        scaled_font->surface_private = NULL;
+		"%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font);
+
+    if (cache != NULL) {
+	_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 (CairoDFB_Font,
                  "%s( scaled_glyph=%p, scaled_font=%p ).\n",
                  __FUNCTION__, scaled_glyph, scaled_font);
 
-     if (scaled_glyph->surface_private) {
+     if (scaled_glyph->surface_private != NULL) {
           free (scaled_glyph->surface_private);
           scaled_glyph->surface_private = NULL;
      }
 }
 
 static cairo_int_status_t
 _cairo_directfb_surface_show_glyphs (void                *abstract_dst,
                                      cairo_operator_t     op,
                                      cairo_pattern_t     *pattern,
                                      cairo_glyph_t       *glyphs,
                                      int                  num_glyphs,
                                      cairo_scaled_font_t *scaled_font,
 				     int		 *remaining_glyphs)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
-    cairo_status_t               ret;
+    cairo_status_t               status;
     DFBSurfaceBlittingFlags      flags;
     DFBSurfaceBlendFunction      sblend;
     DFBSurfaceBlendFunction      dblend;
-    DFBColor                     color;
     DFBRectangle                 rects[num_glyphs];
     DFBPoint                     points[num_glyphs];
     int                          num;
-    
+    const cairo_color_t         *color;
+
+
     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);
-                            
+		"%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;
+
+    /* Fallback if we need to emulate clip regions */
+    if (dst->base.clip &&
+        (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
+         dst->base.clip->surface != NULL))
+    {
         return CAIRO_INT_STATUS_UNSUPPORTED;
-        
-    if (_directfb_get_operator (op, &sblend, &dblend) ||
-        sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) 
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-        
-    ret = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
-                                        &cache, &rects[0], &points[0], &num);
-    if (ret) {
-        if (ret == CAIRO_INT_STATUS_NOTHING_TO_DO)
-            ret = CAIRO_STATUS_SUCCESS;
-        return ret;
     }
-        
-    color.a = ((cairo_solid_pattern_t *)pattern)->color.alpha_short >> 8;
-    color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short   >> 8;
-    color.g = ((cairo_solid_pattern_t *)pattern)->color.green_short >> 8;
-    color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short  >> 8;
-    
+
+    /* XXX Unbounded operators are not handled correctly */
+    if (! _cairo_operator_bounded_by_mask (op))
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (! _cairo_operator_bounded_by_source (op))
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (! _directfb_get_operator (op, &sblend, &dblend) ||
+	sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA)
+    {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    status = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
+					   &cache, &rects[0], &points[0], &num);
+    if (status) {
+	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+	    status = CAIRO_STATUS_SUCCESS;
+	return status;
+    }
+
+    color = &((cairo_solid_pattern_t *) pattern)->color;
+
     flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
-    if (color.a != 0xff)
-        flags |= DSBLIT_BLEND_COLORALPHA;
-        
+    if (! CAIRO_COLOR_IS_OPAQUE (color))
+	flags |= DSBLIT_BLEND_COLORALPHA;
+
     if (!_directfb_argb_font) {
-        if (sblend == DSBF_ONE) {
-            sblend = DSBF_SRCALPHA;
-            if (dblend == DSBF_ZERO)
-                dblend = DSBF_INVSRCALPHA;
-        }
-    } 
-        
+	if (sblend == DSBF_ONE) {
+	    sblend = DSBF_SRCALPHA;
+	    if (dblend == DSBF_ZERO)
+		dblend = DSBF_INVSRCALPHA;
+	}
+    }
+
     dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
     dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
     dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
-    dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a);
-    
+    if (dst->blit_premultiplied) {
+	dst->dfbsurface->SetColor (dst->dfbsurface,
+				   color->red_short >> 8,
+				   color->green_short >> 8,
+				   color->blue_short >> 8,
+				   color->alpha_short >> 8);
+    } else {
+	dst->dfbsurface->SetColor (dst->dfbsurface,
+				   color->red * 0xff,
+				   color->green * 0xff,
+				   color->blue * 0xff,
+				   color->alpha * 0xff);
+    }
+
     D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n");
-        
+
     RUN_CLIPPED (dst, NULL,
-                 dst->dfbsurface->BatchBlit (dst->dfbsurface,
-                                         cache->dfbsurface, rects, points, num));
-        
+		 dst->dfbsurface->BatchBlit (dst->dfbsurface,
+					     cache->dfbsurface, rects, points, num));
+
     return CAIRO_STATUS_SUCCESS;
 }
 #endif /* DFB_SHOW_GLYPHS */
 
 
 static cairo_bool_t
 _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
 {
     cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
     cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
 
     return a->dfb == b->dfb;
 }
 
-static cairo_surface_backend_t cairo_directfb_surface_backend = {
+static cairo_surface_backend_t
+_cairo_directfb_surface_backend = {
          CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
         _cairo_directfb_surface_create_similar,/*create_similar*/
         _cairo_directfb_surface_finish, /*finish*/
         _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
         _cairo_directfb_surface_release_source_image,/*release_source_image*/
         _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
-        _cairo_directfb_surface_release_dest_image,/*release_dest_image*/ 
+        _cairo_directfb_surface_release_dest_image,/*release_dest_image*/
         _cairo_directfb_surface_clone_similar,/*clone_similar*/
 #if DFB_COMPOSITE
         _cairo_directfb_surface_composite,/*composite*/
 #else
         NULL,/*composite*/
 #endif
 #if DFB_RECTANGLES
         _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/
@@ -1775,83 +1847,86 @@ static cairo_surface_backend_t cairo_dir
         NULL /* reset */
 };
 
 
 static void
 cairo_directfb_surface_backend_init (IDirectFB *dfb)
 {
     static int done = 0;
-    
+
     if (done)
-        return;
-        
+	return;
+
     if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
 #if DFB_RECTANGLES
-        cairo_directfb_surface_backend.fill_rectangles = NULL;
+	_cairo_directfb_surface_backend.fill_rectangles = NULL;
 #endif
 #if DFB_COMPOSITE
-        cairo_directfb_surface_backend.composite = NULL;
+	_cairo_directfb_surface_backend.composite = NULL;
 #endif
 #if DFB_COMPOSITE_TRAPEZOIDS
-        cairo_directfb_surface_backend.composite_trapezoids = NULL;
+	_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;
+	_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 (CairoDFB_Surface, "Acceleration disabled.\n");
-    }
-    else {
-        DFBGraphicsDeviceDescription dsc;
-        
-        dfb->GetDeviceDescription (dfb, &dsc);
-    
+	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 (CairoDFB_Surface, "Using ARGB fonts.\n");
+	_directfb_argb_font = 1;
+	D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n");
     }
 
     done = 1;
-}   
-
+}
 
 cairo_surface_t *
-cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) 
+cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
 {
     cairo_directfb_surface_t *surface;
     DFBSurfacePixelFormat     format;
-   
+    DFBSurfaceCapabilities caps;
+
     D_ASSERT (dfb != NULL);
     D_ASSERT (dfbsurface != NULL);
 
     cairo_directfb_surface_backend_init (dfb);
-        
-    surface = calloc (1, sizeof(cairo_directfb_surface_t));
-    if (!surface)
-        return NULL;
-     
-    dfbsurface->AddRef (dfbsurface);   
+
+    surface = calloc (1, sizeof (cairo_directfb_surface_t));
+    if (surface == NULL)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    dfbsurface->AddRef (dfbsurface);
     dfbsurface->GetPixelFormat (dfbsurface, &format);
     dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height);
     surface->dfb = dfb;
-    surface->dfbsurface = dfbsurface;  
+    surface->dfbsurface = dfbsurface;
     surface->format = _directfb_to_cairo_format (format);
     surface->content = _directfb_format_to_content (format);
 
-    _cairo_surface_init (&surface->base, 
-                         &cairo_directfb_surface_backend, surface->content);  
+    dfbsurface->GetCapabilities (dfbsurface, &caps);
+    if (caps & DSCAPS_PREMULTIPLIED)
+	surface->blit_premultiplied = TRUE;
+
+    _cairo_surface_init (&surface->base,
+                         &_cairo_directfb_surface_backend,
+			 surface->content);
 
     return &surface->base;
 }
-
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -44,17 +44,17 @@
  *      if found, enables using ARGB fonts instead of A8
  */
 
 #ifndef CAIRO_DIRECTFB_H
 #define CAIRO_DIRECTFB_H
 
 #include "cairo.h"
 
-#ifdef  CAIRO_HAS_DIRECTFB_SURFACE
+#if  CAIRO_HAS_DIRECTFB_SURFACE
 
 #include <directfb.h>
 
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
 cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface);
 
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-features-win32.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#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
-
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin-data.c
@@ -0,0 +1,1030 @@
+/* See cairo-font-face-twin.c for copyright info */
+
+#include "cairoint.h"
+
+const int8_t _cairo_twin_outlines[] = {
+/* 0x0 '\0'  offset 0 */
+    0, 24, 42, 0, 2, 4,
+    0, 24, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 24, -42,
+    'l', 24, 0,
+    'l', 0, 0,
+    'e',
+/* 0x20 ' '  offset 28 */
+    0, 4, 0, 0, 2, 3,
+    -128, 0, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'e',
+/* 0x21 '!'  offset 40 */
+    0, 4, 42, 0, 3, 3,
+    0, 2, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 2, -42,
+    'l', 2, -14,
+    'm', 2, -4,
+    'c', 1, -4, 0, -3, 0, -2,
+    'c', 0, -1, 1, 0, 2, 0,
+    'c', 3, 0, 4, -1, 4, -2,
+    'c', 4, -3, 3, -4, 2, -4,
+    'e',
+/* 0x22 '"'  offset 90 */
+    0, 16, 42, -28, 2, 3,
+    0, 16, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, -28,
+    'm', 16, -42,
+    'l', 16, -28,
+    'e',
+/* 0x23 '#'  offset 114 */
+    0, 30, 50, 14, 2, 5,
+    0, 30, /* snap_x */
+    -24, -21, -15, -12, 0, /* snap_y */
+    'm', 16, -50,
+    'l', 2, 14,
+    'm', 28, -50,
+    'l', 14, 14,
+    'm', 2, -24,
+    'l', 30, -24,
+    'm', 0, -12,
+    'l', 28, -12,
+    'e',
+/* 0x24 '$'  offset 152 */
+    0, 28, 50, 8, 4, 4,
+    0, 10, 18, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 10, -50,
+    'l', 10, 8,
+    'm', 18, -50,
+    'l', 18, 8,
+    'm', 28, -36,
+    'c', 24, -42, 18, -42, 14, -42,
+    'c', 10, -42, 0, -42, 0, -34,
+    'c', 0, -25, 8, -24, 14, -22,
+    'c', 20, -20, 28, -19, 28, -9,
+    'c', 28, 0, 18, 0, 14, 0,
+    'c', 10, 0, 4, 0, 0, -6,
+    'e',
+/* 0x25 '%'  offset 224 */
+    0, 36, 42, 0, 4, 7,
+    0, 14, 22, 36, /* snap_x */
+    -42, -38, -28, -21, -15, -14, 0, /* snap_y */
+    'm', 10, -42,
+    'c', 12, -41, 14, -40, 14, -36,
+    'c', 14, -30, 11, -28, 6, -28,
+    'c', 2, -28, 0, -30, 0, -34,
+    'c', 0, -39, 3, -42, 8, -42,
+    'l', 10, -42,
+    'c', 18, -37, 28, -37, 36, -42,
+    'l', 0, 0,
+    'm', 28, -14,
+    'c', 24, -14, 22, -11, 22, -6,
+    'c', 22, -2, 24, 0, 28, 0,
+    'c', 33, 0, 36, -2, 36, -8,
+    'c', 36, -12, 34, -14, 30, -14,
+    'l', 28, -14,
+    'e',
+    'X', 'X', 'X',
+/* 0x26 '&'  offset 323 */
+    0, 40, 42, 0, 4, 4,
+    0, 10, 22, 40, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 40, -24,
+    'c', 40, -27, 39, -28, 37, -28,
+    'c', 29, -28, 32, 0, 12, 0,
+    'c', 0, 0, 0, -8, 0, -10,
+    'c', 0, -24, 22, -20, 22, -34,
+    'c', 22, -45, 10, -45, 10, -34,
+    'c', 10, -27, 25, 0, 36, 0,
+    'c', 39, 0, 40, -1, 40, -4,
+    'e',
+/* 0x27 '''  offset 390 */
+    0, 4, 42, -30, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 2, -38,
+    'c', -1, -38, -1, -42, 2, -42,
+    'c', 6, -42, 5, -33, 0, -30,
+    'e',
+/* 0x28 '('  offset 419 */
+    0, 14, 50, 14, 2, 3,
+    0, 14, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 14, -50,
+    'c', -5, -32, -5, -5, 14, 14,
+    'e',
+/* 0x29 ')'  offset 441 */
+    0, 14, 50, 14, 2, 3,
+    0, 14, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -50,
+    'c', 19, -34, 19, -2, 0, 14,
+    'e',
+/* 0x2a '*'  offset 463 */
+    0, 20, 30, -6, 3, 3,
+    0, 10, 20, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 10, -30,
+    'l', 10, -6,
+    'm', 0, -24,
+    'l', 20, -12,
+    'm', 20, -24,
+    'l', 0, -12,
+    'e',
+/* 0x2b '+'  offset 494 */
+    0, 36, 36, 0, 3, 4,
+    0, 18, 36, /* snap_x */
+    -21, -18, -15, 0, /* snap_y */
+    'm', 18, -36,
+    'l', 18, 0,
+    'm', 0, -18,
+    'l', 36, -18,
+    'e',
+/* 0x2c ','  offset 520 */
+    0, 4, 4, 8, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 4, -2,
+    'c', 4, 1, 0, 1, 0, -2,
+    'c', 0, -5, 4, -5, 4, -2,
+    'c', 4, 4, 2, 6, 0, 8,
+    'e',
+/* 0x2d '-'  offset 556 */
+    0, 36, 18, -18, 2, 4,
+    0, 36, /* snap_x */
+    -21, -18, -15, 0, /* snap_y */
+    'm', 0, -18,
+    'l', 36, -18,
+    'e',
+/* 0x2e '.'  offset 575 */
+    0, 4, 4, 0, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 2, -4,
+    'c', -1, -4, -1, 0, 2, 0,
+    'c', 5, 0, 5, -4, 2, -4,
+    'e',
+/* 0x2f '/'  offset 604 */
+    0, 36, 50, 14, 2, 3,
+    0, 36, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 36, -50,
+    'l', 0, 14,
+    'e',
+/* 0x30 '0'  offset 622 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 14, -42,
+    'c', 9, -42, 0, -42, 0, -21,
+    'c', 0, 0, 9, 0, 14, 0,
+    'c', 19, 0, 28, 0, 28, -21,
+    'c', 28, -42, 19, -42, 14, -42,
+    'E',
+/* 0x31 '1'  offset 666 */
+    0, 28, 42, 0, 2, 3,
+    0, 17, 28 /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 7, -34,
+    'c', 11, -35, 15, -38, 17, -42,
+    'l', 17, 0,
+    'e',
+/* 0x32 '2'  offset 691 */
+    0, 28, 42, 0, 4, 4,
+    0, 2, 26, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 2, -32,
+    'c', 2, -34, 2, -42, 14, -42,
+    'c', 26, -42, 26, -34, 26, -32,
+    'c', 26, -30, 25, -25, 10, -10,
+    'l', 0, 0,
+    'l', 28, 0,
+    'e',
+/* 0x33 '3'  offset 736 */
+    0, 28, 42, 0, 2, 5,
+    0, 28, /* snap_x */
+    -42, -26, -21, -15, 0, /* snap_y */
+    'm', 4, -42,
+    'l', 26, -42,
+    'l', 14, -26,
+    'c', 21, -26, 28, -26, 28, -14,
+    'c', 28, 0, 17, 0, 13, 0,
+    'c', 8, 0, 3, -1, 0, -8,
+    'e',
+/* 0x34 '4'  offset 780 */
+    0, 28, 42, 0, 3, 4,
+    0, 20, 30, /* snap_x */
+    -21, -15, -14, 0, /* snap_y */
+    'm', 20, 0,
+    'l', 20, -42,
+    'l', 0, -14,
+    'l', 30, -14,
+    'e',
+    'X', 'X', 'X',
+/* 0x35 '5'  offset 809 */
+    0, 28, 42, 0, 2, 5,
+    0, 28, /* snap_x */
+    -42, -28, -21, -15, 0, /* snap_y */
+    'm', 24, -42,
+    'l', 4, -42,
+    'l', 2, -24,
+    'c', 5, -27, 10, -28, 13, -28,
+    'c', 16, -28, 28, -28, 28, -14,
+    'c', 28, 0, 16, 0, 13, 0,
+    'c', 10, 0, 3, 0, 0, -8,
+    'e',
+/* 0x36 '6'  offset 860 */
+    0, 28, 42, 0, 2, 5,
+    0, 26, /* snap_x */
+    -42, -26, -21, -15, 0, /* snap_y */
+    'm', 24, -36,
+    'c', 22, -41, 19, -42, 14, -42,
+    'c', 9, -42, 0, -41, 0, -19,
+    'c', 0, -1, 9, 0, 13, 0,
+    'c', 18, 0, 26, -3, 26, -13,
+    'c', 26, -18, 23, -26, 13, -26,
+    'c', 10, -26, 1, -24, 0, -14,
+    'e',
+/* 0x37 '7'  offset 919 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 28, -42,
+    'l', 8, 0,
+    'e',
+    'X', 'X', 'X',
+/* 0x38 '8'  offset 944 */
+    0, 28, 42, 0, 4, 4,
+    0, 2, 26, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 14, -42,
+    'c', 5, -42, 2, -40, 2, -34,
+    'c', 2, -18, 28, -32, 28, -11,
+    'c', 28, 0, 18, 0, 14, 0,
+    'c', 10, 0, 0, 0, 0, -11,
+    'c', 0, -32, 26, -18, 26, -34,
+    'c', 26, -40, 23, -42, 14, -42,
+    'E',
+/* 0x39 '9'  offset 1004 */
+    0, 28, 42, 0, 2, 5,
+    0, 26, /* snap_x */
+    -42, -21, -16, -15, 0, /* snap_y */
+    'm', 26, -28,
+    'c', 25, -16, 13, -16, 13, -16,
+    'c', 8, -16, 0, -19, 0, -29,
+    'c', 0, -34, 3, -42, 13, -42,
+    'c', 24, -42, 26, -32, 26, -23,
+    'c', 26, -14, 24, 0, 12, 0,
+    'c', 7, 0, 4, -2, 2, -6,
+    'e',
+/* 0x3a ':'  offset 1063 */
+    0, 4, 28, 0, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 2, -28,
+    'c', -1, -28, -1, -24, 2, -24,
+    'c', 5, -24, 5, -28, 2, -28,
+    'm', 2, -4,
+    'c', -1, -4, -1, 0, 2, 0,
+    'c', 5, 0, 5, -4, 2, -4,
+    'e',
+/* 0x3b ';'  offset 1109 */
+    0, 4, 28, 8, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 2, -28,
+    'c', -1, -28, -1, -24, 2, -24,
+    'c', 5, -24, 5, -28, 2, -28,
+    'm', 4, -2,
+    'c', 4, 1, 0, 1, 0, -2,
+    'c', 0, -5, 4, -5, 4, -2,
+    'c', 4, 3, 2, 6, 0, 8,
+    'e',
+/* 0x3c '<'  offset 1162 */
+    0, 32, 36, 0, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 32, -36,
+    'l', 0, -18,
+    'l', 32, 0,
+    'e',
+/* 0x3d '='  offset 1183 */
+    0, 36, 24, -12, 2, 5,
+    0, 36, /* snap_x */
+    -24, -21, -15, -12, 0, /* snap_y */
+    'm', 0, -24,
+    'l', 36, -24,
+    'm', 0, -12,
+    'l', 36, -12,
+    'e',
+/* 0x3e '>'  offset 1209 */
+    0, 32, 36, 0, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -36,
+    'l', 32, -18,
+    'l', 0, 0,
+    'e',
+/* 0x3f '?'  offset 1230 */
+    0, 24, 42, 0, 3, 4,
+    0, 12, 24, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 0, -32,
+    'c', 0, -34, 0, -42, 12, -42,
+    'c', 24, -42, 24, -34, 24, -32,
+    'c', 24, -29, 24, -24, 12, -20,
+    'l', 12, -14,
+    'm', 12, -4,
+    'c', 9, -4, 9, 0, 12, 0,
+    'c', 15, 0, 15, -4, 12, -4,
+    'e',
+/* 0x40 '@'  offset 1288 */
+    0, 42, 42, 0, 1, 6,
+    30, /* snap_x */
+    -42, -32, -21, -15, -10, 0, /* snap_y */
+    'm', 30, -26,
+    'c', 28, -31, 24, -32, 21, -32,
+    'c', 10, -32, 10, -23, 10, -19,
+    'c', 10, -13, 11, -10, 19, -10,
+    'c', 30, -10, 28, -21, 30, -32,
+    'c', 27, -10, 30, -10, 34, -10,
+    'c', 41, -10, 42, -19, 42, -22,
+    'c', 42, -34, 34, -42, 21, -42,
+    'c', 9, -42, 0, -34, 0, -21,
+    'c', 0, -9, 8, 0, 21, 0,
+    'c', 30, 0, 34, -3, 36, -6,
+    'e',
+/* 0x41 'A'  offset 1375 */
+    0, 32, 42, 0, 2, 4,
+    0, 32, /* snap_x */
+    -21, -15, -14, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 16, -42,
+    'l', 32, 0,
+    'm', 6, -14,
+    'l', 26, -14,
+    'e',
+    'X', 'X', 'X',
+/* 0x42 'B'  offset 1406 */
+    0, 28, 42, 0, 2, 5,
+    0, 28, /* snap_x */
+    -42, -22, -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 18, -42,
+    'c', 32, -42, 32, -22, 18, -22,
+    'l', 0, -22,
+    'l', 18, -22,
+    'c', 32, -22, 32, 0, 18, 0,
+    'E',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x43 'C'  offset 1455 */
+    0, 30, 42, 0, 2, 4,
+    0, 30, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 30, -32,
+    'c', 26, -42, 21, -42, 16, -42,
+    'c', 2, -42, 0, -29, 0, -21,
+    'c', 0, -13, 2, 0, 16, 0,
+    'c', 21, 0, 26, 0, 30, -10,
+    'e',
+/* 0x44 'D'  offset 1499 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 14, -42,
+    'c', 33, -42, 33, 0, 14, 0,
+    'E',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x45 'E'  offset 1534 */
+    0, 26, 42, 0, 2, 5,
+    0, 26, /* snap_x */
+    -42, -22, -21, -15, 0, /* snap_y */
+    'm', 26, -42,
+    'l', 0, -42,
+    'l', 0, 0,
+    'l', 26, 0,
+    'm', 0, -22,
+    'l', 16, -22,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x46 'F'  offset 1572 */
+    0, 26, 42, 0, 2, 5,
+    0, 26, /* snap_x */
+    -42, -22, -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 26, -42,
+    'm', 0, -22,
+    'l', 16, -22,
+    'e',
+    'X', 'X', 'X',
+/* 0x47 'G'  offset 1604 */
+    0, 30, 42, 0, 2, 5,
+    0, 30, /* snap_x */
+    -42, -21, -16, -15, 0, /* snap_y */
+    'm', 30, -32,
+    'c', 26, -42, 21, -42, 16, -42,
+    'c', 2, -42, 0, -29, 0, -21,
+    'c', 0, -13, 2, 0, 16, 0,
+    'c', 28, 0, 30, -7, 30, -16,
+    'l', 20, -16,
+    'e',
+    'X', 'X', 'X',
+/* 0x48 'H'  offset 1655 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -22, -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'm', 28, -42,
+    'l', 28, 0,
+    'm', 0, -22,
+    'l', 28, -22,
+    'e',
+/* 0x49 'I'  offset 1686 */
+    0, 0, 42, 0, 1, 3,
+    0, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'e',
+/* 0x4a 'J'  offset 1703 */
+    0, 20, 42, 0, 2, 3,
+    0, 20, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 20, -42,
+    'l', 20, -10,
+    'c', 20, 3, 0, 3, 0, -10,
+    'l', 0, -14,
+    'e',
+/* 0x4b 'K'  offset 1731 */
+    0, 28, 42, 0, 2, 3,
+    0, 28, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'm', 28, -42,
+    'l', 0, -14,
+    'm', 10, -24,
+    'l', 28, 0,
+    'e',
+/* 0x4c 'L'  offset 1761 */
+    0, 24, 42, 0, 2, 3,
+    0, 24, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'l', 24, 0,
+    'e',
+    'X', 'X', 'X',
+/* 0x4d 'M'  offset 1785 */
+    0, 32, 42, 0, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 16, 0,
+    'l', 32, -42,
+    'l', 32, 0,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x4e 'N'  offset 1821 */
+    0, 28, 42, 0, 2, 3,
+    0, 28, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 28, 0,
+    'l', 28, -42,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x4f 'O'  offset 1851 */
+    0, 32, 42, 0, 2, 4,
+    0, 32, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 16, -42,
+    'c', 2, -42, 0, -29, 0, -21,
+    'c', 0, -13, 2, 0, 16, 0,
+    'c', 30, 0, 32, -13, 32, -21,
+    'c', 32, -29, 30, -42, 16, -42,
+    'E',
+/* 0x50 'P'  offset 1895 */
+    0, 28, 42, 0, 2, 5,
+    0, 28, /* snap_x */
+    -42, -21, -20, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 18, -42,
+    'c', 32, -42, 32, -20, 18, -20,
+    'l', 0, -20,
+    'e',
+    'X', 'X', 'X',
+/* 0x51 'Q'  offset 1931 */
+    0, 32, 42, 4, 2, 4,
+    0, 32, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 16, -42,
+    'c', 2, -42, 0, -29, 0, -21,
+    'c', 0, -13, 2, 0, 16, 0,
+    'c', 30, 0, 32, -13, 32, -21,
+    'c', 32, -29, 30, -42, 16, -42,
+    'm', 18, -8,
+    'l', 30, 4,
+    'e',
+/* 0x52 'R'  offset 1981 */
+    0, 28, 42, 0, 2, 5,
+    0, 28, /* snap_x */
+    -42, -22, -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 0, -42,
+    'l', 18, -42,
+    'c', 32, -42, 31, -22, 18, -22,
+    'l', 0, -22,
+    'm', 14, -22,
+    'l', 28, 0,
+    'e',
+    'X', 'X', 'X',
+/* 0x53 'S'  offset 2023 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 28, -36,
+    'c', 25, -41, 21, -42, 14, -42,
+    'c', 10, -42, 0, -42, 0, -34,
+    'c', 0, -17, 28, -28, 28, -9,
+    'c', 28, 0, 19, 0, 14, 0,
+    'c', 7, 0, 3, -1, 0, -6,
+    'e',
+/* 0x54 'T'  offset 2074 */
+    0, 28, 42, 0, 3, 4,
+    0, 14, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 14, -42,
+    'l', 14, 0,
+    'm', 0, -42,
+    'l', 28, -42,
+    'e',
+/* 0x55 'U'  offset 2100 */
+    0, 28, 42, 0, 2, 3,
+    0, 28, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, -12,
+    'c', 0, 4, 28, 4, 28, -12,
+    'l', 28, -42,
+    'e',
+/* 0x56 'V'  offset 2128 */
+    0, 32, 42, 0, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 16, 0,
+    'l', 32, -42,
+    'e',
+    'X', 'X', 'X',
+/* 0x57 'W'  offset 2152 */
+    0, 40, 42, 0, 2, 3,
+    0, 40, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 10, 0,
+    'l', 20, -42,
+    'l', 30, 0,
+    'l', 40, -42,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x58 'X'  offset 2188 */
+    0, 28, 42, 0, 2, 3,
+    0, 28, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 28, 0,
+    'm', 28, -42,
+    'l', 0, 0,
+    'e',
+/* 0x59 'Y'  offset 2212 */
+    0, 32, 42, 0, 3, 3,
+    0, 16, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 16, -22,
+    'l', 16, 0,
+    'm', 32, -42,
+    'l', 16, -22,
+    'e',
+/* 0x5a 'Z'  offset 2240 */
+    0, 28, 42, 0, 2, 4,
+    0, 28, /* snap_x */
+    -42, -21, -15, 0, /* snap_y */
+    'm', 28, 0,
+    'l', 0, 0,
+    'l', 28, -42,
+    'l', 0, -42,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x5b '['  offset 2271 */
+    0, 14, 44, 0, 2, 4,
+    0, 14, /* snap_x */
+    -44, -21, -15, 0, /* snap_y */
+    'm', 14, -44,
+    'l', 0, -44,
+    'l', 0, 0,
+    'l', 14, 0,
+    'e',
+/* 0x5c '\'  offset 2296 */
+    0, 36, 50, 14, 2, 3,
+    0, 36, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -50,
+    'l', 36, 14,
+    'e',
+/* 0x5d ']'  offset 2314 */
+    0, 14, 44, 0, 2, 4,
+    0, 14, /* snap_x */
+    -44, -21, -15, 0, /* snap_y */
+    'm', 0, -44,
+    'l', 14, -44,
+    'l', 14, 0,
+    'l', 0, 0,
+    'e',
+/* 0x5e '^'  offset 2339 */
+    0, 32, 46, -18, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -18,
+    'l', 16, -46,
+    'l', 32, -18,
+    'e',
+    'X', 'X', 'X',
+/* 0x5f '_'  offset 2363 */
+    0, 36, 0, 0, 2, 3,
+    0, 36, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, 0,
+    'l', 36, 0,
+    'e',
+/* 0x60 '`'  offset 2381 */
+    0, 4, 42, -30, 2, 3,
+    0, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 4, -42,
+    'c', 2, -40, 0, -39, 0, -32,
+    'c', 0, -31, 1, -30, 2, -30,
+    'c', 5, -30, 5, -34, 2, -34,
+    'e',
+/* 0x61 'a'  offset 2417 */
+    0, 24, 28, 0, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 24, -28,
+    'l', 24, 0,
+    'm', 24, -22,
+    'c', 21, -27, 18, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -1, 24, -6,
+    'e',
+/* 0x62 'b'  offset 2467 */
+    0, 24, 42, 0, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'm', 0, -22,
+    'c', 3, -26, 6, -28, 11, -28,
+    'c', 22, -28, 24, -19, 24, -14,
+    'c', 24, -9, 22, 0, 11, 0,
+    'c', 6, 0, 3, -2, 0, -6,
+    'e',
+/* 0x63 'c'  offset 2517 */
+    0, 24, 28, 0, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 24, -22,
+    'c', 21, -26, 18, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -2, 24, -6,
+    'e',
+/* 0x64 'd'  offset 2561 */
+    0, 24, 42, 0, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 24, -42,
+    'l', 24, 0,
+    'm', 24, -22,
+    'c', 21, -26, 18, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -2, 24, -6,
+    'e',
+/* 0x65 'e'  offset 2611 */
+    0, 24, 28, 0, 2, 5,
+    0, 24, /* snap_x */
+    -28, -21, -16, -15, 0, /* snap_y */
+    'm', 0, -16,
+    'l', 24, -16,
+    'c', 24, -20, 24, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -2, 24, -6,
+    'e',
+/* 0x66 'f'  offset 2659 */
+    0, 16, 42, 0, 3, 5,
+    0, 6, 16, /* snap_x */
+    -42, -28, -21, -15, 0, /* snap_y */
+    'm', 16, -42,
+    'c', 8, -42, 6, -40, 6, -34,
+    'l', 6, 0,
+    'm', 0, -28,
+    'l', 14, -28,
+    'e',
+/* 0x67 'g'  offset 2693 */
+    0, 24, 28, 14, 2, 5,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, 14, /* snap_y */
+    'm', 24, -28,
+    'l', 24, 4,
+    'c', 23, 14, 16, 14, 13, 14,
+    'c', 10, 14, 8, 14, 6, 12,
+    'm', 24, -22,
+    'c', 21, -26, 18, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -2, 24, -6,
+    'e',
+/* 0x68 'h'  offset 2758 */
+    0, 22, 42, 0, 2, 4,
+    0, 22, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'm', 0, -20,
+    'c', 8, -32, 22, -31, 22, -20,
+    'l', 22, 0,
+    'e',
+/* 0x69 'i'  offset 2790 */
+    0, 4, 44, 0, 3, 3,
+    0, 2, 4, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'c', 0, -39, 4, -39, 4, -42,
+    'c', 4, -45, 0, -45, 0, -42,
+    'm', 2, -28,
+    'l', 2, 0,
+    'e',
+/* 0x6a 'j'  offset 2826 */
+    -8, 4, 44, 14, 3, 4,
+    0, 2, 4, /* snap_x */
+    -21, -15, 0, 14, /* snap_y */
+    'm', 0, -42,
+    'c', 0, -39, 4, -39, 4, -42,
+    'c', 4, -45, 0, -45, 0, -42,
+    'm', 2, -28,
+    'l', 2, 6,
+    'c', 2, 13, -1, 14, -8, 14,
+    'e',
+/* 0x6b 'k'  offset 2870 */
+    0, 22, 42, 0, 2, 3,
+    0, 22, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'm', 20, -28,
+    'l', 0, -8,
+    'm', 8, -16,
+    'l', 22, 0,
+    'e',
+/* 0x6c 'l'  offset 2900 */
+    0, 0, 42, 0, 1, 3,
+    0, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -42,
+    'l', 0, 0,
+    'e',
+/* 0x6d 'm'  offset 2917 */
+    0, 44, 28, 0, 3, 4,
+    0, 22, 44, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 0, 0,
+    'm', 0, -20,
+    'c', 5, -29, 22, -33, 22, -20,
+    'l', 22, 0,
+    'm', 22, -20,
+    'c', 27, -29, 44, -33, 44, -20,
+    'l', 44, 0,
+    'e',
+/* 0x6e 'n'  offset 2963 */
+    0, 22, 28, 0, 2, 4,
+    0, 22, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 0, 0,
+    'm', 0, -20,
+    'c', 4, -28, 22, -34, 22, -20,
+    'l', 22, 0,
+    'e',
+/* 0x6f 'o'  offset 2995 */
+    0, 26, 28, 0, 2, 4,
+    0, 26, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 24, 0, 26, -9, 26, -14,
+    'c', 26, -19, 24, -28, 13, -28,
+    'e',
+/* 0x70 'p'  offset 3039 */
+    0, 24, 28, 14, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 0, 14,
+    'm', 0, -22,
+    'c', 3, -26, 6, -28, 11, -28,
+    'c', 22, -28, 24, -19, 24, -14,
+    'c', 24, -9, 22, 0, 11, 0,
+    'c', 6, 0, 3, -2, 0, -6,
+    'e',
+/* 0x71 'q'  offset 3089 */
+    0, 24, 28, 14, 2, 4,
+    0, 24, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 24, -28,
+    'l', 24, 14,
+    'm', 24, -22,
+    'c', 21, -26, 18, -28, 13, -28,
+    'c', 2, -28, 0, -19, 0, -14,
+    'c', 0, -9, 2, 0, 13, 0,
+    'c', 18, 0, 21, -2, 24, -6,
+    'e',
+/* 0x72 'r'  offset 3139 */
+    0, 16, 28, 0, 2, 4,
+    0, 16, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 0, 0,
+    'm', 0, -16,
+    'c', 2, -27, 7, -28, 16, -28,
+    'e',
+/* 0x73 's'  offset 3168 */
+    0, 22, 28, 0, 2, 4,
+    0, 22, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 22, -22,
+    'c', 22, -27, 16, -28, 11, -28,
+    'c', 4, -28, 0, -26, 0, -22,
+    'c', 0, -11, 22, -20, 22, -7,
+    'c', 22, 0, 17, 0, 11, 0,
+    'c', 6, 0, 0, -1, 0, -6,
+    'e',
+/* 0x74 't'  offset 3219 */
+    0, 16, 42, 0, 3, 4,
+    0, 6, 16, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 6, -42,
+    'l', 6, -8,
+    'c', 6, -2, 8, 0, 16, 0,
+    'm', 0, -28,
+    'l', 14, -28,
+    'e',
+/* 0x75 'u'  offset 3252 */
+    0, 22, 28, 0, 2, 3,
+    0, 22, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 0, -8,
+    'c', 0, 6, 18, 0, 22, -8,
+    'm', 22, -28,
+    'l', 22, 0,
+    'e',
+/* 0x76 'v'  offset 3283 */
+    0, 24, 28, 0, 2, 3,
+    0, 24, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 12, 0,
+    'l', 24, -28,
+    'e',
+    'X', 'X', 'X',
+/* 0x77 'w'  offset 3307 */
+    0, 32, 28, 0, 2, 3,
+    0, 32, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 8, 0,
+    'l', 16, -28,
+    'l', 24, 0,
+    'l', 32, -28,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x78 'x'  offset 3343 */
+    0, 22, 28, 0, 2, 3,
+    0, 22, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -28,
+    'l', 22, 0,
+    'm', 22, -28,
+    'l', 0, 0,
+    'e',
+/* 0x79 'y'  offset 3367 */
+    -2, 24, 28, 14, 2, 4,
+    0, 24, /* snap_x */
+    -21, -15, 0, 14, /* snap_y */
+    'm', 0, -28,
+    'l', 12, 0,
+    'm', 24, -28,
+    'l', 12, 0,
+    'c', 6, 13, 0, 14, -2, 14,
+    'e',
+/* 0x7a 'z'  offset 3399 */
+    0, 22, 28, 0, 2, 4,
+    0, 22, /* snap_x */
+    -28, -21, -15, 0, /* snap_y */
+    'm', 22, 0,
+    'l', 0, 0,
+    'l', 22, -28,
+    'l', 0, -28,
+    'e',
+    'X', 'X', 'X',
+    'X', 'X', 'X',
+/* 0x7b '{'  offset 3430 */
+    0, 16, 44, 0, 3, 5,
+    0, 6, 16, /* snap_x */
+    -44, -24, -21, -15, 0, /* snap_y */
+    'm', 16, -44,
+    'c', 10, -44, 6, -42, 6, -36,
+    'l', 6, -24,
+    'l', 0, -24,
+    'l', 6, -24,
+    'l', 6, -8,
+    'c', 6, -2, 10, 0, 16, 0,
+    'e',
+/* 0x7c '|'  offset 3474 */
+    0, 0, 50, 14, 1, 3,
+    0, /* snap_x */
+    -21, -15, 0, /* snap_y */
+    'm', 0, -50,
+    'l', 0, 14,
+    'e',
+/* 0x7d '}'  offset 3491 */
+    0, 16, 44, 0, 3, 5,
+    0, 10, 16, /* snap_x */
+    -44, -24, -21, -15, 0, /* snap_y */
+    'm', 0, -44,
+    'c', 6, -44, 10, -42, 10, -36,
+    'l', 10, -24,
+    'l', 16, -24,
+    'l', 10, -24,
+    'l', 10, -8,
+    'c', 10, -2, 6, 0, 0, 0,
+    'e',
+/* 0x7e '~'  offset 3535 */
+    0, 36, 24, -12, 2, 5,
+    0, 36, /* snap_x */
+    -24, -21, -15, -12, 0, /* snap_y */
+    'm', 0, -14,
+    'c', 1, -21, 4, -24, 8, -24,
+    'c', 18, -24, 18, -12, 28, -12,
+    'c', 32, -12, 35, -15, 36, -22,
+    'e',
+};
+
+const uint16_t _cairo_twin_charmap[128] = {
+    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,
+    28,   40,   90,  114,  152,  224,  323,  390,
+    419,  441,  463,  494,  520,  556,  575,  604,
+    622,  666,  691,  736,  780,  809,  860,  919,
+    944, 1004, 1063, 1109, 1162, 1183, 1209, 1230,
+    1288, 1375, 1406, 1455, 1499, 1534, 1572, 1604,
+    1655, 1686, 1703, 1731, 1761, 1785, 1821, 1851,
+    1895, 1931, 1981, 2023, 2074, 2100, 2128, 2152,
+    2188, 2212, 2240, 2271, 2296, 2314, 2339, 2363,
+    2381, 2417, 2467, 2517, 2561, 2611, 2659, 2693,
+    2758, 2790, 2826, 2870, 2900, 2917, 2963, 2995,
+    3039, 3089, 3139, 3168, 3219, 3252, 3283, 3307,
+    3343, 3367, 3399, 3430, 3474, 3491, 3535,    0,
+};
+
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2004 Keith Packard
+ * Copyright © 2008 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 Keith Packard
+ *
+ * Contributor(s):
+ *      Keith Packard <keithp@keithp.com>
+ *      Behdad Esfahbod <behdad@behdad.org>
+ */
+
+#include "cairoint.h"
+
+/*
+ * This file implements a user-font rendering the decendant of the Hershey
+ * font coded by Keith Packard for use in the Twin window system.
+ * The actual font data is in cairo-font-face-twin-data.c
+ *
+ * Ported to cairo user font by Behdad Esfahbod.
+ */
+
+
+#define twin_glyph_left(g)      ((g)[0])
+#define twin_glyph_right(g)     ((g)[1])
+#define twin_glyph_ascent(g)    ((g)[2])
+#define twin_glyph_descent(g)   ((g)[3])
+
+#define twin_glyph_n_snap_x(g)  ((g)[4])
+#define twin_glyph_n_snap_y(g)  ((g)[5])
+#define twin_glyph_snap_x(g)    (&g[6])
+#define twin_glyph_snap_y(g)    (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
+#define twin_glyph_draw(g)      (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
+
+#define SNAPI(p)	(p)
+#define SNAPH(p)	(p)
+
+#define FX(g)		((g) / 64.)
+#define FY(g)		((g) / 64.)
+
+
+static cairo_status_t
+twin_scaled_font_init (cairo_scaled_font_t  *scaled_font,
+		       cairo_t              *cr,
+		       cairo_font_extents_t *metrics)
+{
+  metrics->ascent  = FY (50);
+  metrics->descent = FY (14);
+  return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
+				   unsigned long        unicode,
+				   unsigned long       *glyph)
+{
+    /* We use an identity charmap.  Which means we could live
+     * with no unicode_to_glyph method too.  But we define this
+     * to map all unknown chars to a single unknown glyph to
+     * reduce pressure on cache. */
+
+    if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
+	*glyph = unicode;
+    else
+	*glyph = 0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+#define SNAPX(p)	_twin_snap (p, info.snap_x, info.n_snap_x)
+#define SNAPY(p)	_twin_snap (p, info.snap_y, info.n_snap_y)
+
+static double
+_twin_snap (double v, int a, int b)
+{
+    return v; /* XXX */
+}
+
+static cairo_status_t
+twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
+			       unsigned long         glyph,
+			       cairo_t              *cr,
+			       cairo_text_extents_t *metrics)
+{
+    double x1, y1, x2, y2, x3, y3;
+    const int8_t *b = _cairo_twin_outlines +
+		      _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
+    const int8_t *g = twin_glyph_draw(b);
+
+    struct {
+      cairo_bool_t snap;
+      int snap_x;
+      int snap_y;
+      int n_snap_x;
+      int n_snap_y;
+    } info = {FALSE};
+
+    cairo_set_line_width (cr, 0.06);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+    for (;;) {
+	switch (*g++) {
+	case 'M':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'm':
+	    x1 = FX(*g++);
+	    y1 = FY(*g++);
+	    if (info.snap)
+	    {
+		x1 = SNAPX (x1);
+		y1 = SNAPY (y1);
+	    }
+	    cairo_move_to (cr, x1, y1);
+	    continue;
+	case 'L':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'l':
+	    x1 = FX(*g++);
+	    y1 = FY(*g++);
+	    if (info.snap)
+	    {
+		x1 = SNAPX (x1);
+		y1 = SNAPY (y1);
+	    }
+	    cairo_line_to (cr, x1, y1);
+	    continue;
+	case 'C':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'c':
+	    x1 = FX(*g++);
+	    y1 = FY(*g++);
+	    x2 = FX(*g++);
+	    y2 = FY(*g++);
+	    x3 = FX(*g++);
+	    y3 = FY(*g++);
+	    if (info.snap)
+	    {
+		x1 = SNAPX (x1);
+		y1 = SNAPY (y1);
+		x2 = SNAPX (x2);
+		y2 = SNAPY (y2);
+		x3 = SNAPX (x3);
+		y3 = SNAPY (y3);
+	    }
+	    cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
+	    continue;
+	case 'E':
+	    cairo_close_path (cr);
+	    /* fall through */
+	case 'e':
+	    cairo_stroke (cr);
+	    break;
+	case 'X':
+	    /* filler */
+	    continue;
+	}
+	break;
+    }
+
+    metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
+    metrics->x_advance +=  cairo_get_line_width (cr)/* XXX 2*x.margin */;
+    if (info.snap)
+	metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
+
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_font_face_t *
+_cairo_font_face_twin_create (cairo_font_slant_t slant,
+			      cairo_font_weight_t weight)
+{
+    cairo_font_face_t *twin_font_face;
+
+    twin_font_face = cairo_user_font_face_create ();
+    cairo_user_font_face_set_init_func             (twin_font_face, twin_scaled_font_init);
+    cairo_user_font_face_set_render_glyph_func     (twin_font_face, twin_scaled_font_render_glyph);
+    cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
+
+    return twin_font_face;
+}
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -277,16 +277,17 @@ cairo_font_face_status (cairo_font_face_
  **/
 void *
 cairo_font_face_get_user_data (cairo_font_face_t	   *font_face,
 			       const cairo_user_data_key_t *key)
 {
     return _cairo_user_data_array_get_data (&font_face->user_data,
 					    key);
 }
+slim_hidden_def (cairo_font_face_get_user_data);
 
 /**
  * cairo_font_face_set_user_data:
  * @font_face: a #cairo_font_face_t
  * @key: the address of a #cairo_user_data_key_t to attach the user data to
  * @user_data: the user data to attach to the font face
  * @destroy: a #cairo_destroy_func_t which will be called when the
  * font face is destroyed or when new user data is attached using the
@@ -301,21 +302,22 @@ cairo_font_face_get_user_data (cairo_fon
  **/
 cairo_status_t
 cairo_font_face_set_user_data (cairo_font_face_t	   *font_face,
 			       const cairo_user_data_key_t *key,
 			       void			   *user_data,
 			       cairo_destroy_func_t	    destroy)
 {
     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return font_face->status;
 
     return _cairo_user_data_array_set_data (&font_face->user_data,
 					    key, user_data, destroy);
 }
+slim_hidden_def (cairo_font_face_set_user_data);
 
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
 
 static int
 _cairo_toy_font_face_keys_equal (const void *key_a,
 				 const void *key_b);
 
 /* We maintain a hash table from family/weight/slant =>
@@ -562,39 +564,89 @@ static void
 	_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
 
     _cairo_toy_font_face_hash_table_unlock ();
 
     _cairo_toy_font_face_fini (font_face);
 }
 
 static cairo_status_t
+_cairo_toy_font_face_scaled_font_get_implementation (void                *abstract_font_face,
+						     cairo_font_face_t **font_face_out)
+{
+    cairo_toy_font_face_t *font_face = abstract_font_face;
+    cairo_status_t status;
+
+    if (font_face->base.status)
+	return font_face->base.status;
+
+    if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
+    {
+	const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
+
+	if (backend->get_implementation == NULL) {
+	    *font_face_out = &font_face->base;
+	    return CAIRO_STATUS_SUCCESS;
+	}
+
+	status = backend->get_implementation (font_face,
+					      font_face_out);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return _cairo_font_face_set_error (&font_face->base, status);
+    }
+
+    status = _cairo_user_scaled_font_backend.get_implementation (font_face,
+								 font_face_out);
+
+    return _cairo_font_face_set_error (&font_face->base, status);
+}
+
+static cairo_status_t
 _cairo_toy_font_face_scaled_font_create (void                *abstract_font_face,
 					 const cairo_matrix_t       *font_matrix,
 					 const cairo_matrix_t       *ctm,
 					 const cairo_font_options_t *options,
 					 cairo_scaled_font_t	   **scaled_font)
 {
     cairo_toy_font_face_t *font_face = abstract_font_face;
-    const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
     cairo_status_t status;
 
     if (font_face->base.status)
 	return font_face->base.status;
 
     status = cairo_font_options_status ((cairo_font_options_t *) options);
     if (status)
 	return status;
 
-    return _cairo_font_face_set_error (&font_face->base,
-	                               backend->create_toy (font_face,
-				                            font_matrix,
-							    ctm,
-							    options,
-							    scaled_font));
+    if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
+    {
+	const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
+
+	*scaled_font = NULL;
+	status =  backend->create_toy (font_face,
+				       font_matrix,
+				       ctm,
+				       options,
+				       scaled_font);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return _cairo_font_face_set_error (&font_face->base, status);
+
+	if (*scaled_font)
+	    cairo_scaled_font_destroy (*scaled_font);
+    }
+
+    status = _cairo_user_scaled_font_backend.create_toy (font_face,
+							 font_matrix,
+							 ctm,
+							 options,
+							 scaled_font);
+
+    return _cairo_font_face_set_error (&font_face->base, status);
 }
 
 static cairo_bool_t
 _cairo_font_face_is_toy (cairo_font_face_t *font_face)
 {
     return font_face->backend == &_cairo_toy_font_face_backend;
 }
 
@@ -636,16 +688,17 @@ cairo_toy_font_face_get_slant (cairo_fon
 {
     cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
     if (! _cairo_font_face_is_toy (font_face)) {
 	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
 	    return CAIRO_FONT_SLANT_DEFAULT;
     }
     return toy_font_face->slant;
 }
+slim_hidden_def (cairo_toy_font_face_get_slant);
 
 /**
  * cairo_toy_font_face_get_weight:
  * @font_face: A toy font face
  *
  * Gets the weight a toy font.
  *
  * Return value: The weight value
@@ -657,20 +710,22 @@ cairo_toy_font_face_get_weight (cairo_fo
 {
     cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
     if (! _cairo_font_face_is_toy (font_face)) {
 	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
 	    return CAIRO_FONT_WEIGHT_DEFAULT;
     }
     return toy_font_face->weight;
 }
+slim_hidden_def (cairo_toy_font_face_get_weight);
 
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
     CAIRO_FONT_TYPE_TOY,
     _cairo_toy_font_face_destroy,
+    _cairo_toy_font_face_scaled_font_get_implementation,
     _cairo_toy_font_face_scaled_font_create
 };
 
 void
 _cairo_unscaled_font_init (cairo_unscaled_font_t               *unscaled_font,
 			   const cairo_unscaled_font_backend_t *backend)
 {
     CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
--- a/gfx/cairo/cairo/src/cairo-font-options.c
+++ b/gfx/cairo/cairo/src/cairo-font-options.c
@@ -34,44 +34,41 @@
  *      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
@@ -187,18 +184,16 @@ 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);
 
 /**
@@ -221,17 +216,16 @@ 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
@@ -247,18 +241,17 @@ 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->lcd_filter << 8) |
-	    (options->hint_style << 12) |
+	    (options->hint_style << 8) |
 	    (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
@@ -330,59 +323,16 @@ 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-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -52,40 +52,16 @@
 #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
@@ -762,309 +738,46 @@ static cairo_status_t
 					unscaled->face->available_sizes[best_i].height);
 	if (error)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-/* 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) ;
+/* 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 },
 #endif
-		    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;
-		}
-	    }
-	}
-    }
-}
-
+    {    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 },
+};
 
 /* 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_image_surface_t *image;
+    cairo_bool_t subpixel = FALSE;
 
     width = bitmap->width;
     height = bitmap->rows;
 
     if (width == 0 || height == 0) {
 	*surface = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	return (*surface)->base.status;
@@ -1111,63 +824,154 @@ static cairo_status_t
 	}
 #endif
 	format = CAIRO_FORMAT_A1;
 	break;
 
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
     case FT_PIXEL_MODE_GRAY:
-        if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
+	switch (font_options->antialias) {
+	case CAIRO_ANTIALIAS_DEFAULT:
+	case CAIRO_ANTIALIAS_GRAY:
+	case CAIRO_ANTIALIAS_NONE:
+	default:
 	    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;
-	} 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;
+	    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;
 	    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);
     }
 
-    /* XXX */
-    *surface = image = (cairo_image_surface_t *)
+    *surface = (cairo_image_surface_t *)
 	cairo_image_surface_create_for_data (data,
 					     format,
 					     width, height, stride);
-    if (image->base.status) {
+    if ((*surface)->base.status) {
 	free (data);
 	return (*surface)->base.status;
     }
 
-    if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
-	pixman_image_set_component_alpha (image->pixman_image, TRUE);
-
-    _cairo_image_surface_assume_ownership_of_data (image);
+    if (subpixel)
+	pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
+
+    _cairo_image_surface_assume_ownership_of_data ((*surface));
 
     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
@@ -1182,173 +986,129 @@ 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;
-    unsigned int width, height;
+    FT_Matrix matrix;
+    int hmul = 1;
+    int vmul = 1;
+    unsigned int width, height, stride;
+    cairo_bool_t subpixel = FALSE;
     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 (render_mode) {
-	case FT_RENDER_MODE_MONO:
+	switch (font_options->antialias) {
+	case CAIRO_ANTIALIAS_NONE:
 	    format = CAIRO_FORMAT_A1;
 	    break;
-	case FT_RENDER_MODE_LCD:
-	case FT_RENDER_MODE_LCD_V:
+	case CAIRO_ANTIALIAS_SUBPIXEL:
 	    format= CAIRO_FORMAT_ARGB32;
 	    break;
-	case FT_RENDER_MODE_LIGHT:
-	case FT_RENDER_MODE_NORMAL:
-	case FT_RENDER_MODE_MAX:
+	case CAIRO_ANTIALIAS_DEFAULT:
+	case CAIRO_ANTIALIAS_GRAY:
 	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  {
 
-	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;
-	    }
+	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;
 	    break;
-	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:
+	case CAIRO_ANTIALIAS_DEFAULT:
+	case CAIRO_ANTIALIAS_GRAY:
+	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
+	    bitmap.num_grays  = 256;
+	    stride = (width + 3) & -4;
 	    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;
 	}
 
-#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);
+	bitmap.pitch = stride;
+	bitmap.width = width * hmul;
+	bitmap.rows = height * vmul;
+	bitmap.buffer = calloc (stride, bitmap.rows);
 	if (bitmap.buffer == NULL)
 	    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
-	 */
+	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
+
+	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
+	    free (bitmap.buffer);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+
 	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
 	if (status)
 	    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)
@@ -1557,17 +1317,16 @@ 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)
@@ -1593,35 +1352,16 @@ 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;
 
@@ -1712,22 +1452,16 @@ 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) {
@@ -1741,21 +1475,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;
@@ -2478,16 +2212,17 @@ static cairo_int_status_t
 
     _cairo_ft_unscaled_font_unlock_face (unscaled);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
+    NULL,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
     NULL,			/* text_to_glyphs */
     _cairo_ft_ucs4_to_index,
     NULL, 			/* show_glyphs */
     _cairo_ft_load_truetype_table,
     _cairo_ft_index_to_ucs4
@@ -2584,16 +2319,17 @@ static cairo_status_t
 					  font_matrix, ctm,
 					  options, ft_options,
 					  scaled_font);
 }
 
 static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_font_face_destroy,
+    NULL, /* direct implementation */
     _cairo_ft_font_face_scaled_font_create
 };
 
 static cairo_font_face_t *
 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 			    cairo_ft_options_t	     *ft_options)
 {
     cairo_ft_font_face_t *font_face, **prev_font_face;
@@ -2688,44 +2424,16 @@ 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);
@@ -2856,20 +2564,24 @@ cairo_ft_font_face_create_for_pattern (F
  *   are useful. You should not pass any of the flags affecting
  *   the load target, such as %FT_LOAD_TARGET_LIGHT.
  *
  * Creates a new font face for the FreeType font backend from a
  * pre-opened FreeType face. This font can then be used with
  * cairo_set_font_face() or cairo_scaled_font_create(). The
  * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
  * also for the FreeType backend and can be used with functions such
- * as cairo_ft_scaled_font_lock_face().
+ * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
+ * to the FT_Face alive in a font-cache and the exact lifetime of the reference
+ * depends highly upon the exact usage pattern and is subject to external
+ * factors. You must not call FT_Done_Face() before the last reference to the
+ * #cairo_font_face_t has been dropped.
  *
- * As an example, here is how one might correctly couple the lifetime of
- * the FreeType face object to the #cairo_font_face_t:
+ * As an example, below is how one might correctly couple the lifetime of
+ * the FreeType face object to the #cairo_font_face_t.
  *
  * <informalexample><programlisting>
  * static const cairo_user_data_key_t key;
  *
  * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
  * status = cairo_font_face_set_user_data (font_face, &key,
  *                                ft_face, (cairo_destroy_func_t) FT_Done_Face);
  * if (status) {
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -506,27 +506,31 @@ static void
 
 static cairo_status_t
 _cairo_glitz_surface_clone_similar (void	    *abstract_surface,
 				    cairo_surface_t *src,
 				    int              src_x,
 				    int              src_y,
 				    int              width,
 				    int              height,
+				    int             *clone_offset_x,
+				    int             *clone_offset_y,
 				    cairo_surface_t **clone_out)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
     cairo_glitz_surface_t *clone;
     cairo_status_t status;
 
     if (surface->base.status)
 	return surface->base.status;
 
     if (src->backend == surface->base.backend)
     {
+	*clone_offset_x = 0;
+	*clone_offset_y = 0;
 	*clone_out = cairo_surface_reference (src);
 
 	return CAIRO_STATUS_SUCCESS;
     }
     else if (_cairo_surface_is_image (src))
     {
 	cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
 	cairo_content_t	      content;
@@ -534,16 +538,18 @@ static cairo_status_t
 	cairo_rectangle_int_t extent;
 
 	content = _cairo_content_from_format (image_src->format);
 
 	clone = (cairo_glitz_surface_t *)
 	    _cairo_glitz_surface_create_similar (surface, content,
 						 image_src->width,
 						 image_src->height);
+	if (clone == NULL)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	if (clone->base.status)
 	    return clone->base.status;
 
 	image_extent.x = 0;
 	image_extent.y = 0;
 	image_extent.width = image_src->width;
 	image_extent.height = image_src->height;
 	extent.x = src_x;
@@ -797,18 +803,17 @@ static cairo_int_status_t
 	    free (data);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
 
 	src = (cairo_glitz_surface_t *)
 	    _cairo_surface_create_similar_scratch (&dst->base,
 						   CAIRO_CONTENT_COLOR_ALPHA,
 						   gradient->n_stops, 1);
-	if (src->base.status)
-	{
+	if (src->base.status) {
 	    glitz_buffer_destroy (buffer);
 	    free (data);
 	    return src->base.status;
 	}
 
 	for (i = 0; i < gradient->n_stops; i++)
 	{
 	    pixels[i] =
@@ -1271,18 +1276,23 @@ static cairo_int_status_t
 	format.vertex.mask.type = GLITZ_DATA_TYPE_FLOAT;
 	format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X;
 	format.vertex.mask.offset = 2 * sizeof (glitz_float_t);
 
 	mask = (cairo_glitz_surface_t *)
 	    _cairo_glitz_surface_create_similar (&dst->base,
 						 CAIRO_CONTENT_ALPHA,
 						 2, 1);
-	if (mask->base.status)
-	{
+	if (mask == NULL) {
+	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+	    if (src_pattern == &tmp_src_pattern.base)
+		_cairo_pattern_fini (&tmp_src_pattern.base);
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+	if (mask->base.status) {
 	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
 	    if (src_pattern == &tmp_src_pattern.base)
 		_cairo_pattern_fini (&tmp_src_pattern.base);
 
 	    return mask->base.status;
 	}
 
 	color.red = color.green = color.blue = color.alpha = 0xffff;
@@ -1380,18 +1390,17 @@ static cairo_int_status_t
 
 	pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
                                n_traps, (pixman_trapezoid_t *) traps);
 
 	mask = (cairo_glitz_surface_t *)
 	    _cairo_surface_create_similar_scratch (&dst->base,
 						   CAIRO_CONTENT_ALPHA,
 						   width, height);
-	if (mask->base.status)
-	{
+	if (mask->base.status) {
 	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
 	    free (data);
 	    cairo_surface_destroy (&image->base);
 	    return mask->base.status;
 	}
 
 	status = _cairo_glitz_surface_set_image (mask, image,
 		                                 0, 0, width, height, 0, 0);
@@ -2006,17 +2015,17 @@ static cairo_status_t
 	glyph_private->area   = NULL;
 	glyph_private->locked = FALSE;
 
 	scaled_glyph->surface_private = (void *) glyph_private;
     }
 
     if (glyph_surface->width  > GLYPH_CACHE_MAX_WIDTH ||
 	glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
-	return CAIRO_STATUS_SUCCESS;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (scaled_font->surface_private == NULL)
     {
 	status = _cairo_glitz_surface_font_init (surface, scaled_font,
 						 glyph_surface->format);
 	if (status)
 	    return status;
     }
@@ -2239,32 +2248,38 @@ static cairo_int_status_t
 	cairo_glitz_surface_t *clone;
 
 	for (i = 0; i < num_glyphs; i++)
 	{
 	    glyph_private = scaled_glyphs[i]->surface_private;
 	    if (!glyph_private || !glyph_private->area)
 	    {
 		int glyph_width, glyph_height;
+		int clone_offset_x, clone_offset_y;
 
 		image = &scaled_glyphs[i]->surface->base;
 		glyph_width = scaled_glyphs[i]->surface->width;
 		glyph_height = scaled_glyphs[i]->surface->height;
 		status =
 		    _cairo_glitz_surface_clone_similar (abstract_surface,
 							image,
 							0,
 							0,
 							glyph_width,
 							glyph_height,
+							&clone_offset_x,
+							&clone_offset_y,
 							(cairo_surface_t **)
 							&clone);
 		if (status)
 		    goto UNLOCK;
 
+		assert (clone_offset_x == 0);
+		assert (clone_offset_y == 0);
+
 		x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
 		y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
 		x1 = _cairo_lround (glyphs[i].x - x_offset);
 		y1 = _cairo_lround (glyphs[i].y - y_offset);
 
 		glitz_composite (_glitz_operator (op),
 				 src->surface,
 				 clone->surface,
@@ -2366,16 +2381,23 @@ static cairo_bool_t
 				 cairo_content_t content)
 {
     cairo_glitz_surface_t *a = (cairo_glitz_surface_t *) surface_a;
     cairo_glitz_surface_t *b = (cairo_glitz_surface_t *) surface_b;
 
     glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
     glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
 
+    /* XXX Disable caching of glitz surfaces by the solid pattern cache.
+     * Until glitz has a mechanism for releasing resources on connection
+     * closure, we will attempt to access invalid pointers when evicting
+     * old surfaces from the solid pattern cache.
+     */
+    return FALSE;
+
     return drawable_a == drawable_b;
 }
 
 static cairo_status_t
 _cairo_glitz_surface_reset (void *abstract_surface)
 {
     cairo_glitz_surface_t *surface = abstract_surface;
     cairo_status_t status;
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -55,17 +55,17 @@ static cairo_status_t
 _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
 
 static cairo_status_t
 _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
 
 static void
 _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
 
-static void
+static cairo_status_t
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
                                            cairo_glyph_t       *transformed_glyphs,
 					   int		       *num_transformed_glyphs);
 
 cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
@@ -309,16 +309,18 @@ cairo_status_t
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * _cairo_gstate_is_redirected
  * @gstate: a #cairo_gstate_t
  *
+ * This space left intentionally blank.
+ *
  * Return value: %TRUE if the gstate is redirected to a target
  * different than the original, %FALSE otherwise.
  **/
 cairo_bool_t
 _cairo_gstate_is_redirected (cairo_gstate_t *gstate)
 {
     return (gstate->target != gstate->original_target);
 }
@@ -367,16 +369,18 @@ cairo_surface_t *
 {
     return gstate->original_target;
 }
 
 /**
  * _cairo_gstate_get_clip:
  * @gstate: a #cairo_gstate_t
  *
+ * This space left intentionally blank.
+ *
  * Return value: a pointer to the gstate's #cairo_clip_t structure.
  */
 cairo_clip_t *
 _cairo_gstate_get_clip (cairo_gstate_t *gstate)
 {
     return &gstate->clip;
 }
 
@@ -940,26 +944,33 @@ cairo_status_t
 cairo_status_t
 _cairo_gstate_in_stroke (cairo_gstate_t	    *gstate,
 			 cairo_path_fixed_t *path,
 			 double		     x,
 			 double		     y,
 			 cairo_bool_t	    *inside_ret)
 {
     cairo_status_t status;
+    cairo_box_t limit;
     cairo_traps_t traps;
 
     if (gstate->stroke_style.line_width <= 0.0) {
 	*inside_ret = FALSE;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     _cairo_gstate_user_to_backend (gstate, &x, &y);
 
+    limit.p1.x = _cairo_fixed_from_double (x) - 1;
+    limit.p1.y = _cairo_fixed_from_double (y) - 1;
+    limit.p2.x = limit.p1.x + 2;
+    limit.p2.y = limit.p1.y + 2;
+
     _cairo_traps_init (&traps);
+    _cairo_traps_limit (&traps, &limit);
 
     status = _cairo_path_fixed_stroke_to_traps (path,
 						&gstate->stroke_style,
 						&gstate->ctm,
 						&gstate->ctm_inverse,
 						gstate->tolerance,
 						&traps);
     if (status)
@@ -1006,21 +1017,28 @@ cairo_status_t
 cairo_status_t
 _cairo_gstate_in_fill (cairo_gstate_t	  *gstate,
 		       cairo_path_fixed_t *path,
 		       double		   x,
 		       double		   y,
 		       cairo_bool_t	  *inside_ret)
 {
     cairo_status_t status;
+    cairo_box_t limit;
     cairo_traps_t traps;
 
     _cairo_gstate_user_to_backend (gstate, &x, &y);
 
+    limit.p1.x = _cairo_fixed_from_double (x) - 1;
+    limit.p1.y = _cairo_fixed_from_double (y) - 1;
+    limit.p2.x = limit.p1.x + 2;
+    limit.p2.y = limit.p1.y + 2;
+
     _cairo_traps_init (&traps);
+    _cairo_traps_limit (&traps, &limit);
 
     status = _cairo_path_fixed_fill_to_traps (path,
 					      gstate->fill_rule,
 					      gstate->tolerance,
 					      &traps);
     if (status)
 	goto BAIL;
 
@@ -1456,38 +1474,38 @@ 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,
-			      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_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_text_cluster_flags_t *cluster_flags)
 {
     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, utf8_len,
 					     glyphs, num_glyphs,
 					     clusters, num_clusters,
-					     backward);
+					     cluster_flags);
 }
 
 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;
@@ -1517,31 +1535,25 @@ cairo_status_t
 
     cairo_scaled_font_glyph_extents (gstate->scaled_font,
 				     glyphs, num_glyphs,
 				     extents);
 
     return cairo_scaled_font_status (gstate->scaled_font);
 }
 
-cairo_bool_t
-_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
-{
-    return cairo_surface_has_show_text_glyphs (gstate->target);
-}
-
 cairo_status_t
 _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				const char		   *utf8,
 				int			    utf8_len,
 				const cairo_glyph_t	   *glyphs,
 				int			    num_glyphs,
 				const cairo_text_cluster_t *clusters,
 				int			    num_clusters,
-				cairo_bool_t		    backward)
+				cairo_text_cluster_flags_t  cluster_flags)
 {
     cairo_status_t status;
     cairo_pattern_union_t source_pattern;
     cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1557,20 +1569,22 @@ cairo_status_t
     if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
 	transformed_glyphs = stack_transformed_glyphs;
     } else {
 	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);
+    status = _cairo_gstate_transform_glyphs_to_backend (gstate,
+							glyphs, num_glyphs,
+							transformed_glyphs,
+							&num_glyphs);
 
-    if (!num_glyphs)
+    if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
 
     status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
     if (status)
 	goto CLEANUP_GLYPHS;
 
     /* Just in case */
     if (!clusters)
@@ -1581,36 +1595,34 @@ cairo_status_t
      * and moreover, not all components below us correctly handle huge font
      * sizes.  I wanted to set the limit at 256.  But alas, seems like cairo's
      * rasterizer is something like ten times slower than freetype's for huge
      * sizes.  So, no win just yet.  For now, do it for insanely-huge sizes,
      * just to make sure we don't make anyone unhappy.  When we get a really
      * fast rasterizer in cairo, we may want to readjust this.
      *
      * Needless to say, do this only if show_text_glyphs is not available. */
-    if (_cairo_gstate_has_show_text_glyphs (gstate) ||
+    if (cairo_surface_has_show_text_glyphs (gstate->target) ||
 	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
 	status = _cairo_surface_show_text_glyphs (gstate->target,
 						  gstate->op,
 						  &source_pattern.base,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
 						  clusters, num_clusters,
-						  backward,
+						  cluster_flags,
 						  gstate->scaled_font);
     } else {
 	cairo_path_fixed_t path;
 
 	_cairo_path_fixed_init (&path);
 
-	CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
 	status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 						transformed_glyphs, num_glyphs,
 						&path);
-	CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
 
 	if (status == CAIRO_STATUS_SUCCESS)
 	  status = _cairo_surface_fill (gstate->target,
 					gstate->op,
 					&source_pattern.base,
 					&path,
 					CAIRO_FILL_RULE_WINDING,
 					gstate->tolerance,
@@ -1644,25 +1656,28 @@ cairo_status_t
 
     if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs))
       transformed_glyphs = stack_transformed_glyphs;
     else
       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);
+    status = _cairo_gstate_transform_glyphs_to_backend (gstate,
+							glyphs, num_glyphs,
+							transformed_glyphs,
+							NULL);
+    if (status)
+	goto CLEANUP_GLYPHS;
 
-    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);
 
+  CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       cairo_glyph_free (transformed_glyphs);
 
     return status;
 }
 
 cairo_status_t
 _cairo_gstate_set_antialias (cairo_gstate_t *gstate,
@@ -1692,43 +1707,47 @@ cairo_antialias_t
  *
  * Transform an array of glyphs to backend space by first adding the offset
  * of the font matrix, then transforming from user space to backend space.
  * The result of the transformation is placed in @transformed_glyphs.
  *
  * This also uses information from the scaled font and the surface to
  * cull/drop glyphs that will not be visible.
  **/
-static void
+static cairo_status_t
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
                                            cairo_glyph_t       *transformed_glyphs,
 					   int		       *num_transformed_glyphs)
 {
     int i, j;
     cairo_matrix_t *ctm = &gstate->ctm;
     cairo_matrix_t *font_matrix = &gstate->font_matrix;
     cairo_matrix_t *device_transform = &gstate->target->device_transform;
     cairo_bool_t drop = FALSE;
     double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+    cairo_status_t status;
 
     if (num_transformed_glyphs != NULL) {
 	cairo_rectangle_int_t surface_extents;
 	double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
 
 	drop = TRUE;
+	status = _cairo_gstate_int_clip_extents (gstate, &surface_extents);
+	if (_cairo_status_is_error (status))
+	    return status;
 
-	if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 	    drop = FALSE; /* unbounded surface */
-	else {
+	} else {
 	    if (surface_extents.width == 0 || surface_extents.height == 0) {
 	      /* No visible area.  Don't draw anything */
 	      *num_transformed_glyphs = 0;
-	      return;
+	      return CAIRO_STATUS_SUCCESS;
 	    }
 	    /* XXX We currently drop any glyphs that has its position outside
 	     * of the surface boundaries by a safety margin depending on the
 	     * font scale.  This however can fail in extreme cases where the
 	     * font has really long swashes for example...  We can correctly
 	     * handle that by looking the glyph up and using its device bbox
 	     * to device if it's going to be visible, but I'm not inclined to
 	     * do that now.
@@ -1798,9 +1817,11 @@ static void
             cairo_matrix_transform_point (&aggregate_transform,
                                           &transformed_glyphs[j].x,
                                           &transformed_glyphs[j].y);
 	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
 		j++;
         }
 	*num_transformed_glyphs = j;
     }
+
+    return CAIRO_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-hull.c
+++ b/gfx/cairo/cairo/src/cairo-hull.c
@@ -73,40 +73,47 @@ static void
         hull[i].discard = 0;
 
 	/* Discard all points coincident with the extremal point */
 	if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0)
 	    hull[i].discard = 1;
     }
 }
 
+static inline cairo_int64_t
+_slope_length (cairo_slope_t *slope)
+{
+    return _cairo_int64_add (_cairo_int32x32_64_mul (slope->dx, slope->dx),
+			     _cairo_int32x32_64_mul (slope->dy, slope->dy));
+}
+
 static int
 _cairo_hull_vertex_compare (const void *av, const void *bv)
 {
     cairo_hull_t *a = (cairo_hull_t *) av;
     cairo_hull_t *b = (cairo_hull_t *) bv;
     int ret;
 
     ret = _cairo_slope_compare (&a->slope, &b->slope);
 
-    /* In the case of two vertices with identical slope from the
-       extremal point discard the nearer point. */
-
+    /*
+     * In the case of two vertices with identical slope from the
+     * extremal point discard the nearer point.
+     */
     if (ret == 0) {
-	cairo_fixed_48_16_t a_dist, b_dist;
-	a_dist = ((cairo_fixed_48_16_t) a->slope.dx * a->slope.dx +
-		  (cairo_fixed_48_16_t) a->slope.dy * a->slope.dy);
-	b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx +
-		  (cairo_fixed_48_16_t) b->slope.dy * b->slope.dy);
+	int cmp;
+
+	cmp = _cairo_int64_cmp (_slope_length (&a->slope),
+				_slope_length (&b->slope));
+
 	/*
-	 * Use the point's ids to ensure a total ordering.
-	 * a well-defined ordering, and avoid setting discard on
-	 * both points.
+	 * Use the points' ids to ensure a well-defined ordering,
+	 * and avoid setting discard on both points.
 	 */
-	if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) {
+	if (cmp < 0 || (cmp == 0 && a->id < b->id)) {
 	    a->discard = 1;
 	    ret = -1;
 	} else {
 	    b->discard = 1;
 	    ret = 1;
 	}
     }
 
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -55,16 +55,20 @@ static cairo_format_t
     case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
     case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
     case PIXMAN_b2g3r3:   case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2:
     case PIXMAN_c8:       case PIXMAN_g8:       case PIXMAN_x4a4:
     case PIXMAN_a4:       case PIXMAN_r1g2b1:   case PIXMAN_b1g2r1:
     case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
     case PIXMAN_g4:       case PIXMAN_g1:
     case PIXMAN_yuy2:     case PIXMAN_yv12:
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
+    case PIXMAN_x2b10g10r10:
+    case PIXMAN_a2b10g10r10:
+#endif
     default:
 	return CAIRO_FORMAT_INVALID;
     }
 
     return CAIRO_FORMAT_INVALID;
 }
 
 static cairo_content_t
@@ -76,16 +80,19 @@ static cairo_content_t
     case PIXMAN_a1r5g5b5:
     case PIXMAN_a1b5g5r5:
     case PIXMAN_a4r4g4b4:
     case PIXMAN_a4b4g4r4:
     case PIXMAN_a2r2g2b2:
     case PIXMAN_a2b2g2r2:
     case PIXMAN_a1r1g1b1:
     case PIXMAN_a1b1g1r1:
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
+    case PIXMAN_a2b10g10r10:
+#endif
 	return CAIRO_CONTENT_COLOR_ALPHA;
     case PIXMAN_x8r8g8b8:
     case PIXMAN_x8b8g8r8:
     case PIXMAN_r8g8b8:
     case PIXMAN_b8g8r8:
     case PIXMAN_r5g6b5:
     case PIXMAN_b5g6r5:
     case PIXMAN_x1r5g5b5:
@@ -98,16 +105,19 @@ static cairo_content_t
     case PIXMAN_g8:
     case PIXMAN_r1g2b1:
     case PIXMAN_b1g2r1:
     case PIXMAN_c4:
     case PIXMAN_g4:
     case PIXMAN_g1:
     case PIXMAN_yuy2:
     case PIXMAN_yv12:
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
+    case PIXMAN_x2b10g10r10:
+#endif
 	return CAIRO_CONTENT_COLOR;
     case PIXMAN_a8:
     case PIXMAN_a1:
     case PIXMAN_x4a4:
     case PIXMAN_a4:
 	return CAIRO_CONTENT_ALPHA;
     }
 
@@ -139,17 +149,17 @@ cairo_surface_t *
     surface->width = pixman_image_get_width (pixman_image);
     surface->height = pixman_image_get_height (pixman_image);
     surface->stride = pixman_image_get_stride (pixman_image);
     surface->depth = pixman_image_get_depth (pixman_image);
 
     return &surface->base;
 }
 
-cairo_int_status_t
+cairo_bool_t
 _pixman_format_from_masks (cairo_format_masks_t *masks,
 			   pixman_format_code_t *format_ret)
 {
     pixman_format_code_t format;
     int format_type;
     int a, r, g, b;
     cairo_format_masks_t format_masks;
 
@@ -161,40 +171,40 @@ cairo_int_status_t
     if (masks->red_mask) {
 	if (masks->red_mask > masks->blue_mask)
 	    format_type = PIXMAN_TYPE_ARGB;
 	else
 	    format_type = PIXMAN_TYPE_ABGR;
     } else if (masks->alpha_mask) {
 	format_type = PIXMAN_TYPE_A;
     } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return FALSE;
     }
 
     format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
 
     if (! pixman_format_supported_destination (format))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return FALSE;
 
     /* Sanity check that we got out of PIXMAN_FORMAT exactly what we
      * expected. This avoid any problems from something bizarre like
      * alpha in the least-significant bits, or insane channel order,
      * or whatever. */
      _pixman_format_to_masks (format, &format_masks);
 
      if (masks->bpp        != format_masks.bpp        ||
 	 masks->red_mask   != format_masks.red_mask   ||
 	 masks->green_mask != format_masks.green_mask ||
 	 masks->blue_mask  != format_masks.blue_mask)
      {
-	 return CAIRO_INT_STATUS_UNSUPPORTED;
+	 return FALSE;
      }
 
     *format_ret = format;
-    return CAIRO_STATUS_SUCCESS;
+    return TRUE;
 }
 
 /* A mask consisting of N bits set to 1. */
 #define MASK(N) ((1 << (N))-1)
 
 void
 _pixman_format_to_masks (pixman_format_code_t	 format,
 			 cairo_format_masks_t	*masks)
@@ -248,30 +258,31 @@ void
  * that accepts a #cairo_internal_format_t rather than mask values. */
 cairo_surface_t *
 _cairo_image_surface_create_with_masks (unsigned char	       *data,
 					cairo_format_masks_t   *masks,
 					int			width,
 					int			height,
 					int			stride)
 {
-    cairo_int_status_t status;
     pixman_format_code_t pixman_format;
 
-    status = _pixman_format_from_masks (masks, &pixman_format);
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+    if (! _pixman_format_from_masks (masks, &pixman_format)) {
 	fprintf (stderr,
 		 "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"
+#ifdef PACKAGE_BUGGREPORT
 		 "Please file an enhancement request (quoting the above) at:\n"
-		 PACKAGE_BUGREPORT "\n",
+		 PACKAGE_BUGREPORT"\n"
+#endif
+		 ,
 		 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,
@@ -468,23 +479,35 @@ slim_hidden_def (cairo_format_stride_for
 cairo_surface_t *
 cairo_image_surface_create_for_data (unsigned char     *data,
 				     cairo_format_t	format,
 				     int		width,
 				     int		height,
 				     int		stride)
 {
     pixman_format_code_t pixman_format;
+    int minstride;
 
     if (! CAIRO_FORMAT_VALID (format))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
 
     if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
 
+    minstride = cairo_format_stride_for_width (format, width);
+    if (stride < 0) {
+	if (stride > -minstride) {
+	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
+	}
+    } else {
+	if (stride < minstride) {
+	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
+	}
+    }
+
     pixman_format = _cairo_format_to_pixman_format_code (format);
 
     return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
 							   width, height, stride);
 }
 slim_hidden_def (cairo_image_surface_create_for_data);
 
 cairo_surface_t *
@@ -505,17 +528,18 @@ cairo_surface_t *
 /**
  * cairo_image_surface_get_data:
  * @surface: a #cairo_image_surface_t
  *
  * Get a pointer to the data of the image surface, for direct
  * inspection or modification.
  *
  * Return value: a pointer to the image data of this surface or %NULL
- * if @surface is not an image surface.
+ * if @surface is not an image surface, or if cairo_surface_finish()
+ * has been called.
  *
  * Since: 1.2
  **/
 unsigned char *
 cairo_image_surface_get_data (cairo_surface_t *surface)
 {
     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
 
@@ -543,18 +567,16 @@ cairo_image_surface_get_format (cairo_su
 {
     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
 
     if (! _cairo_surface_is_image (surface)) {
 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return 0;
     }
 
-    assert (CAIRO_FORMAT_VALID (image_surface->format));
-
     return image_surface->format;
 }
 
 /**
  * cairo_image_surface_get_width:
  * @surface: a #cairo_image_surface_t
  *
  * Get the width of the image surface in pixels.
@@ -761,21 +783,24 @@ static void
 
 static cairo_status_t
 _cairo_image_surface_clone_similar (void		*abstract_surface,
 				    cairo_surface_t	*src,
 				    int                  src_x,
 				    int                  src_y,
 				    int                  width,
 				    int                  height,
+				    int                 *clone_offset_x,
+				    int                 *clone_offset_y,
 				    cairo_surface_t    **clone_out)
 {
     cairo_image_surface_t *surface = abstract_surface;
 
     if (src->backend == surface->base.backend) {
+	*clone_offset_x = *clone_offset_y = 0;
 	*clone_out = cairo_surface_reference (src);
 
 	return CAIRO_STATUS_SUCCESS;
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
--- a/gfx/cairo/cairo/src/cairo-matrix.c
+++ b/gfx/cairo/cairo/src/cairo-matrix.c
@@ -619,16 +619,45 @@ cairo_bool_t
 
             return TRUE;
         }
     }
 
     return FALSE;
 }
 
+/* By pixel exact here, we mean a matrix that is composed only of
+ * 90 degree rotations, flips, and integer translations and produces a 1:1
+ * mapping between source and destination pixels. If we transform an image
+ * with a pixel-exact matrix, filtering is not useful.
+ */
+cairo_private cairo_bool_t
+_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
+{
+    cairo_fixed_t x0_fixed, y0_fixed;
+
+    if (matrix->xy == 0.0 && matrix->yx == 0.0) {
+	if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
+	    return FALSE;
+	if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
+	    return FALSE;
+    } else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
+	if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
+	    return FALSE;
+	if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
+	    return FALSE;
+    } else
+	return FALSE;
+
+    x0_fixed = _cairo_fixed_from_double (matrix->x0);
+    y0_fixed = _cairo_fixed_from_double (matrix->y0);
+
+    return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
+}
+
 /*
   A circle in user space is transformed into an ellipse in device space.
 
   The following is a derivation of a formula to calculate the length of the
   major axis for this ellipse; this is useful for error bounds calculations.
 
   Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this derivation:
 
--- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h
@@ -109,17 +109,17 @@ typedef struct _cairo_command_show_text_
     cairo_operator_t		 op;
     cairo_pattern_union_t	 source;
     char			*utf8;
     int				 utf8_len;
     cairo_glyph_t		*glyphs;
     unsigned int		 num_glyphs;
     cairo_text_cluster_t	*clusters;
     int				 num_clusters;
-    cairo_bool_t		 backward;
+    cairo_text_cluster_flags_t   cluster_flags;
     cairo_scaled_font_t		*scaled_font;
 } cairo_command_show_text_glyphs_t;
 
 typedef struct _cairo_command_intersect_clip_path {
     cairo_command_header_t      header;
     cairo_path_fixed_t	       *path_pointer;
     cairo_path_fixed_t		path;
     cairo_fill_rule_t		fill_rule;
--- a/gfx/cairo/cairo/src/cairo-meta-surface.c
+++ b/gfx/cairo/cairo/src/cairo-meta-surface.c
@@ -211,42 +211,16 @@ static cairo_status_t
 static void
 _cairo_meta_surface_release_source_image (void			*abstract_surface,
 					  cairo_image_surface_t	*image,
 					  void			*image_extra)
 {
     cairo_surface_destroy (&image->base);
 }
 
-static cairo_status_t
-_init_pattern_with_snapshot (cairo_pattern_t       *pattern,
-			     const cairo_pattern_t *other)
-{
-    cairo_status_t status;
-
-    status = _cairo_pattern_init_copy (pattern, other);
-    if (status)
-	return status;
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern =
-	    (cairo_surface_pattern_t *) pattern;
-	cairo_surface_t *surface = surface_pattern->surface;
-
-	surface_pattern->surface = _cairo_surface_snapshot (surface);
-
-	cairo_surface_destroy (surface);
-
-	if (surface_pattern->surface->status)
-	    return surface_pattern->surface->status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_int_status_t
 _cairo_meta_surface_paint (void			*abstract_surface,
 			   cairo_operator_t	 op,
 			   cairo_pattern_t	*source)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_paint_t *command;
@@ -254,17 +228,17 @@ static cairo_int_status_t
     command = malloc (sizeof (cairo_command_paint_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     command->header.type = CAIRO_COMMAND_PAINT;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
-    status = _init_pattern_with_snapshot (&command->source.base, source);
+    status = _cairo_pattern_init_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_array_append (&meta->commands, &command);
     if (status)
 	goto CLEANUP_SOURCE;
 
     /* An optimisation that takes care to not replay what was done
@@ -295,21 +269,21 @@ static cairo_int_status_t
     command = malloc (sizeof (cairo_command_mask_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     command->header.type = CAIRO_COMMAND_MASK;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
-    status = _init_pattern_with_snapshot (&command->source.base, source);
+    status = _cairo_pattern_init_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
-    status = _init_pattern_with_snapshot (&command->mask.base, mask);
+    status = _cairo_pattern_init_snapshot (&command->mask.base, mask);
     if (status)
 	goto CLEANUP_SOURCE;
 
     status = _cairo_array_append (&meta->commands, &command);
     if (status)
 	goto CLEANUP_MASK;
 
     return CAIRO_STATUS_SUCCESS;
@@ -341,17 +315,17 @@ static cairo_int_status_t
     command = malloc (sizeof (cairo_command_stroke_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     command->header.type = CAIRO_COMMAND_STROKE;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
-    status = _init_pattern_with_snapshot (&command->source.base, source);
+    status = _cairo_pattern_init_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_path_fixed_init_copy (&command->path, path);
     if (status)
 	goto CLEANUP_SOURCE;
 
     status = _cairo_stroke_style_init_copy (&command->style, style);
@@ -396,17 +370,17 @@ static cairo_int_status_t
     command = malloc (sizeof (cairo_command_fill_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     command->header.type = CAIRO_COMMAND_FILL;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
-    status = _init_pattern_with_snapshot (&command->source.base, source);
+    status = _cairo_pattern_init_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     status = _cairo_path_fixed_init_copy (&command->path, path);
     if (status)
 	goto CLEANUP_SOURCE;
 
     command->fill_rule = fill_rule;
@@ -439,32 +413,32 @@ static cairo_int_status_t
 				      cairo_operator_t		     op,
 				      cairo_pattern_t		    *source,
 				      const char		    *utf8,
 				      int			     utf8_len,
 				      cairo_glyph_t		    *glyphs,
 				      int			     num_glyphs,
 				      const cairo_text_cluster_t    *clusters,
 				      int			     num_clusters,
-				      cairo_bool_t		     backward,
+				      cairo_text_cluster_flags_t     cluster_flags,
 				      cairo_scaled_font_t	    *scaled_font)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
     cairo_command_show_text_glyphs_t *command;
 
     command = malloc (sizeof (cairo_command_show_text_glyphs_t));
     if (command == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
     command->header.region = CAIRO_META_REGION_ALL;
     command->op = op;
 
-    status = _init_pattern_with_snapshot (&command->source.base, source);
+    status = _cairo_pattern_init_snapshot (&command->source.base, source);
     if (status)
 	goto CLEANUP_COMMAND;
 
     command->utf8 = NULL;
     command->utf8_len = utf8_len;
     command->glyphs = NULL;
     command->num_glyphs = num_glyphs;
     command->clusters = NULL;
@@ -490,17 +464,17 @@ static cairo_int_status_t
 	command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0]));
 	if (command->clusters == NULL) {
 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    goto CLEANUP_ARRAYS;
 	}
 	memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
     }
 
-    command->backward = backward;
+    command->cluster_flags = cluster_flags;
 
     command->scaled_font = cairo_scaled_font_reference (scaled_font);
 
     status = _cairo_array_append (&meta->commands, &command);
     if (status)
 	goto CLEANUP_SCALED_FONT;
 
     return CAIRO_STATUS_SUCCESS;
@@ -843,17 +817,17 @@ static cairo_status_t
 	case CAIRO_COMMAND_STROKE:
 	{
 	    cairo_matrix_t dev_ctm = command->stroke.ctm;
 	    cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;
 
 	    if (has_device_transform) {
 		cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
 		cairo_matrix_multiply (&dev_ctm_inverse,
-				       &surface->device_transform_inverse,
+				       &target->device_transform_inverse,
 				       &dev_ctm_inverse);
 	    }
 
 	    status = _cairo_surface_stroke (target,
 					    command->stroke.op,
 					    &command->stroke.source.base,
 					    dev_path,
 					    &command->stroke.style,
@@ -947,17 +921,17 @@ static cairo_status_t
 	    }
 
 	    status = _cairo_surface_show_text_glyphs	(target,
 							 command->show_text_glyphs.op,
 							 &command->show_text_glyphs.source.base,
 							 command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
 							 dev_glyphs, num_glyphs,
 							 command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
-							 command->show_text_glyphs.backward,
+							 command->show_text_glyphs.cluster_flags,
 							 command->show_text_glyphs.scaled_font);
 
 	    free (dev_glyphs);
 	    break;
 	}
 	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
 	    /* XXX Meta surface clipping is broken and requires some
 	     * cairo-gstate.c rewriting.  Work around it for now. */
--- a/gfx/cairo/cairo/src/cairo-misc.c
+++ b/gfx/cairo/cairo/src/cairo-misc.c
@@ -235,34 +235,34 @@ slim_hidden_def (cairo_text_cluster_free
 /**
  * _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
+ * @cluster_flags: cluster flags
  *
  * 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_text_cluster_flags_t   cluster_flags)
 {
     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;
--- a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h
@@ -36,20 +36,25 @@
  *	Carl D. Worth <cworth@cworth.org>
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  *	Behdad Esfahbod <behdad@behdad.org>
  */
 
 #ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
 #define CAIRO_MUTEX_IMPL_PRIVATE_H
 
+#include "cairo.h"
+
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#if HAVE_LOCKDEP
+#include <lockdep.h>
+#endif
 
 /* 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:
@@ -67,16 +72,19 @@
  *   implementation supports.  No trailing semicolon needed.
  *   You should be able to compile the following snippet (don't try
  *   running it):
  *
  *   <programlisting>
  *	cairo_mutex_impl_t _cairo_some_mutex;
  *   </programlisting>
  *
+ * - #define %CAIRO_MUTEX_IMPL_<NAME> 1 with suitable name for your platform.  You
+ *   can later use this symbol in cairo-system.c.
+ *
  * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
  *   proper statement to lock/unlock the mutex object passed in.
  *   You can (and should) assume that the mutex is already
  *   initialized, and is-not-already-locked/is-locked,
  *   respectively.  Use the "do { ... } while (0)" idiom if necessary.
  *   No trailing semicolons are needed (in any macro you define here).
  *   You should be able to compile the following snippet:
  *
@@ -142,73 +150,84 @@
  *   </programlisting>
  *
  * - That is all.  If for any reason you think the above API is
  *   not enough to implement #cairo_mutex_impl_t on your system, please
  *   stop and write to the cairo mailing list about it.  DO NOT
  *   poke around cairo-mutex-private.h for possible solutions.
  */
 
-#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
-#error "Do not include cairo-mutex-impl-private.h directly.  Include cairo-mutex-type-private.h instead."
-#endif
-
 #if CAIRO_NO_MUTEX
 
 /* No mutexes */
 
   typedef int cairo_mutex_impl_t;
 
+# define CAIRO_MUTEX_IMPL_NO 1
 # define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
 # define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
 # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
 # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
 
 #elif HAVE_PTHREAD_H /*******************************************************/
 
 # include <pthread.h>
 
   typedef pthread_mutex_t cairo_mutex_impl_t;
 
+# define CAIRO_MUTEX_IMPL_PTHREAD 1
+#if HAVE_LOCKDEP
+/* expose all mutexes to the validator */
+# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL)
+#endif
 # define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
 # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
+#if HAVE_LOCKDEP
+# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex))
+# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex))
+#endif
 # define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
+#if ! HAVE_LOCKDEP
 # define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+#endif
 # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
 
-#elif HAVE_WINDOWS_H /*******************************************************/
+#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/
 
 # include <windows.h>
 
   typedef CRITICAL_SECTION cairo_mutex_impl_t;
 
+# define CAIRO_MUTEX_IMPL_WIN32 1
 # define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
 # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
 # define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
 # define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
 # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
 
 #elif defined __OS2__ /******************************************************/
 
 # define INCL_BASE
 # define INCL_PM
 # include <os2.h>
 
   typedef HMTX cairo_mutex_impl_t;
 
+# define CAIRO_MUTEX_IMPL_OS2 1
 # define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
 # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
 # define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
 # define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex)
 # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
 
 #elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
 
   typedef BLocker* cairo_mutex_impl_t;
 
+# define CAIRO_MUTEX_IMPL_BEOS 1
 # define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
 # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
 # define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
 # define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex)
 # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL
 
 #else /**********************************************************************/
 
--- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h
@@ -26,30 +26,34 @@
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * Contributor(s):
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  */
 
-
-CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock);
-CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock);
+#ifndef CAIRO_FEATURES_H
+/* This block is to just make this header file standalone */
+#define CAIRO_MUTEX_DECLARE(mutex)
+#endif
 
-CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
-CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
-CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex);
+CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock)
+CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
+
+CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex)
+CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
+CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
 
 #if CAIRO_HAS_FT_FONT
-CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
+CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
 #endif
 
 #if CAIRO_HAS_XLIB_SURFACE
-CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex);
+CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
 #endif
 
-#if !defined (CAIRO_HAS_ATOMIC_OPS) || defined (CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER)
-CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex);
+#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER)
+CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex)
 #endif
 
 /* Undefine, to err on unintended inclusion */
 #undef   CAIRO_MUTEX_DECLARE
--- a/gfx/cairo/cairo/src/cairo-mutex-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-private.h
@@ -36,20 +36,16 @@
  *	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
@@ -57,15 +53,15 @@ cairo_private void _cairo_mutex_finalize
 #endif
 /* only if using static initializer and/or finalizer define the boolean */
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
   cairo_private extern cairo_bool_t _cairo_mutex_initialized;
 #endif
 
 /* Finally, extern the static mutexes and undef */
 
-#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
+#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex;
 #include "cairo-mutex-list-private.h"
 #undef CAIRO_MUTEX_DECLARE
 
 CAIRO_END_DECLS
 
 #endif
--- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h
@@ -85,17 +85,16 @@
 /* and dynamic ones can be initialized using the static initializer. */
 # define CAIRO_MUTEX_IMPL_INIT(mutex) do {				\
       cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;	\
       memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex));	\
   } while (0)
 
 #endif /* CAIRO_MUTEX_IMPL_INIT */
 
-
 #ifdef CAIRO_MUTEX_IMPL_FINI
 
 /* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
  * static mutex'es. */
 # ifndef CAIRO_MUTEX_IMPL_FINALIZE
 #  define CAIRO_MUTEX_IMPL_FINALIZE() do {	\
        if (_cairo_mutex_initialized)	\
            _cairo_mutex_finalize ();	\
@@ -164,16 +163,22 @@ typedef cairo_mutex_impl_t cairo_mutex_t
 #define CAIRO_MUTEX_INITIALIZE		CAIRO_MUTEX_IMPL_INITIALIZE
 #define CAIRO_MUTEX_FINALIZE		CAIRO_MUTEX_IMPL_FINALIZE
 #define CAIRO_MUTEX_LOCK		CAIRO_MUTEX_IMPL_LOCK
 #define CAIRO_MUTEX_UNLOCK		CAIRO_MUTEX_IMPL_UNLOCK
 #define CAIRO_MUTEX_INIT		CAIRO_MUTEX_IMPL_INIT
 #define CAIRO_MUTEX_FINI		CAIRO_MUTEX_IMPL_FINI
 #define CAIRO_MUTEX_NIL_INITIALIZER	CAIRO_MUTEX_IMPL_NIL_INITIALIZER
 
+#ifndef CAIRO_MUTEX_IS_LOCKED
+# define CAIRO_MUTEX_IS_LOCKED(name) 1
+#endif
+#ifndef CAIRO_MUTEX_IS_UNLOCKED
+# define CAIRO_MUTEX_IS_UNLOCKED(name) 1
+#endif
 
 
 /* Debugging support */
 
 #ifdef CAIRO_MUTEX_DEBUG
 
 /* TODO add mutex debugging facilities here (eg deadlock detection) */
 
--- a/gfx/cairo/cairo/src/cairo-mutex.c
+++ b/gfx/cairo/cairo/src/cairo-mutex.c
@@ -30,17 +30,17 @@
  * Contributor(s):
  *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
  */
 
 #include "cairoint.h"
 
 #include "cairo-mutex-private.h"
 
-#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
+#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER;
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 
 # if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
 #  define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE
 # else
@@ -56,27 +56,27 @@ cairo_bool_t _cairo_mutex_initialized = 
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
 void _cairo_mutex_initialize (void)
 {
     if (_cairo_mutex_initialized)
         return;
 
     _cairo_mutex_initialized = TRUE;
 
-#define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex)
+#define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex);
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 }
 #endif
 
 #if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 void _cairo_mutex_finalize (void)
 {
     if (!_cairo_mutex_initialized)
         return;
 
     _cairo_mutex_initialized = FALSE;
 
-#define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex)
+#define  CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex);
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 }
 #endif
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-no-features.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* 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-os2-private.h
+++ b/gfx/cairo/cairo/src/cairo-os2-private.h
@@ -33,30 +33,30 @@
  *
  * Contributor(s):
  *     Peter Weilbacher <mozilla@Weilbacher.org>
  */
 
 #ifndef CAIRO_OS2_PRIVATE_H
 #define CAIRO_OS2_PRIVATE_H
 
+#include "cairo-os2.h"
+#include "cairoint.h"
+
 #define INCL_DOS
 #define INCL_DOSSEMAPHORES
 #define INCL_DOSERRORS
 #define INCL_WIN
 #define INCL_GPI
 #ifdef __WATCOMC__
 # include <os2.h>
 #else
 # include <os2emx.h>
 #endif
 
-#include "cairo-os2.h"
-#include "cairoint.h"
-
 typedef struct _cairo_os2_surface
 {
     cairo_surface_t        base;
 
     /* Mutex semaphore to protect private fields from concurrent access */
     HMTX                   hmtx_use_private_fields;
     /* Private fields: */
     HPS                    hps_client_window;
--- a/gfx/cairo/cairo/src/cairo-os2-surface.c
+++ b/gfx/cairo/cairo/src/cairo-os2-surface.c
@@ -227,16 +227,22 @@ void _buffer_free (void *buffer)
 {
 #ifdef OS2_USE_PLATFORM_ALLOC
     DosFreeMem (buffer);
 #else
     free (buffer);
 #endif
 }
 
+/* XXX
+ * The cairo_os2_ini() and cairo_os2_fini() functions should be removed and
+ * the LibMain code moved to cairo-system.c.  It should also call
+ * cairo_debug_reset_static_data() instead of duplicating its logic...
+ */
+
 #ifdef BUILD_CAIRO_DLL
 /* The main DLL entry for DLL initialization and uninitialization */
 /* Only include this code if we're about to build a DLL.          */
 
 #ifdef __WATCOMC__
 unsigned _System
 LibMain (unsigned hmod,
          unsigned termination)
@@ -1197,16 +1203,18 @@ cairo_os2_surface_set_manual_window_refr
 
     local_os2_surface->blit_as_changes = !manual_refresh;
 }
 
 /**
  * cairo_os2_surface_get_manual_window_refresh:
  * @surface: the cairo surface to query the refresh mode from
  *
+ * This space left intentionally blank.
+ *
  * Return value: current refresh mode of the surface (true by default)
  *
  * Since: 1.4
  **/
 cairo_bool_t
 cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface)
 {
     cairo_os2_surface_t *local_os2_surface;
--- a/gfx/cairo/cairo/src/cairo-output-stream-private.h
+++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h
@@ -156,17 +156,21 @@ cairo_private cairo_output_stream_t *
 
 cairo_private void
 _cairo_memory_stream_copy (cairo_output_stream_t *base,
 			   cairo_output_stream_t *dest);
 
 cairo_private int
 _cairo_memory_stream_length (cairo_output_stream_t *stream);
 
+cairo_private cairo_output_stream_t *
+_cairo_null_stream_create (void);
+
 /* cairo-base85-stream.c */
 cairo_private cairo_output_stream_t *
 _cairo_base85_stream_create (cairo_output_stream_t *output);
 
 /* cairo-deflate-stream.c */
 cairo_private cairo_output_stream_t *
 _cairo_deflate_stream_create (cairo_output_stream_t *output);
 
+
 #endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-output-stream.c
+++ b/gfx/cairo/cairo/src/cairo-output-stream.c
@@ -111,16 +111,19 @@ typedef struct _cairo_output_stream_with
 
 static cairo_status_t
 closure_write (cairo_output_stream_t *stream,
 	       const unsigned char *data, unsigned int length)
 {
     cairo_output_stream_with_closure_t *stream_with_closure =
 	(cairo_output_stream_with_closure_t *) stream;
 
+    if (stream_with_closure->write_func == NULL)
+	return CAIRO_STATUS_SUCCESS;
+
     return stream_with_closure->write_func (stream_with_closure->closure,
 					    data, length);
 }
 
 static cairo_status_t
 closure_close (cairo_output_stream_t *stream)
 {
     cairo_output_stream_with_closure_t *stream_with_closure =
@@ -578,16 +581,19 @@ cairo_output_stream_t *
 }
 
 cairo_output_stream_t *
 _cairo_output_stream_create_for_filename (const char *filename)
 {
     stdio_stream_t *stream;
     FILE *file;
 
+    if (filename == NULL)
+	return _cairo_null_stream_create ();
+
     file = fopen (filename, "wb");
     if (file == NULL) {
 	switch (errno) {
 	case ENOMEM:
 	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	    return (cairo_output_stream_t *) &_cairo_output_stream_nil;
 	default:
 	    _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
@@ -671,8 +677,31 @@ void
 
 int
 _cairo_memory_stream_length (cairo_output_stream_t *base)
 {
     memory_stream_t *stream = (memory_stream_t *) base;
 
     return _cairo_array_num_elements (&stream->array);
 }
+
+static cairo_status_t
+null_write (cairo_output_stream_t *base,
+	    const unsigned char *data, unsigned int length)
+{
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_output_stream_t *
+_cairo_null_stream_create (void)
+{
+    cairo_output_stream_t *stream;
+
+    stream = malloc (sizeof *stream);
+    if (stream == NULL) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
+    }
+
+    _cairo_output_stream_init (stream, null_write, NULL);
+
+    return stream;
+}
--- a/gfx/cairo/cairo/src/cairo-paginated-private.h
+++ b/gfx/cairo/cairo/src/cairo-paginated-private.h
@@ -60,26 +60,29 @@ struct _cairo_paginated_surface_backend 
     (*set_paginated_mode)	(void			*surface,
 				 cairo_paginated_mode_t	 mode);
 
     /* Optional. Specifies the smallest box that encloses all objects
      * on the page. Will be called at the end of the ANALYZE phase but
      * before the mode is changed to RENDER.
      */
     cairo_warn cairo_int_status_t
-    (*set_bounding_box)	(void	   	*surface,
+    (*set_bounding_box)	(void		*surface,
 			 cairo_box_t	*bbox);
 
     /* Optional. Indicates whether the page requires fallback images.
      * Will be called at the end of the ANALYZE phase but before the
      * mode is changed to RENDER.
      */
     cairo_warn cairo_int_status_t
-    (*set_fallback_images_required)(void   	  *surface,
-				    cairo_bool_t   fallbacks_required);
+    (*set_fallback_images_required) (void	    *surface,
+				     cairo_bool_t    fallbacks_required);
+
+    cairo_bool_t
+    (*supports_fine_grained_fallbacks) (void		    *surface);
 };
 
 /* A #cairo_paginated_surface_t provides a very convenient wrapper that
  * is well-suited for doing the analysis common to most surfaces that
  * have paginated output, (that is, things directed at printers, or
  * for saving content in files such as PostScript or PDF files).
  *
  * To use the paginated surface, you'll first need to create your
--- a/gfx/cairo/cairo/src/cairo-paginated-surface.c
+++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c
@@ -103,16 +103,17 @@ cairo_surface_t *
 	goto FAIL_CLEANUP_SURFACE;
 
     surface->page_num = 1;
     surface->page_is_blank = TRUE;
 
     return &surface->base;
 
   FAIL_CLEANUP_SURFACE:
+    cairo_surface_destroy (target);
     free (surface);
   FAIL:
     return _cairo_surface_create_in_error (status);
 }
 
 cairo_bool_t
 _cairo_surface_is_paginated (cairo_surface_t *surface)
 {
@@ -294,18 +295,20 @@ static cairo_int_status_t
     if (surface->target->status)
 	return surface->target->status;
 
     analysis = _cairo_analysis_surface_create (surface->target,
 					       surface->width, surface->height);
     if (analysis->status)
 	return _cairo_surface_set_error (surface->target, analysis->status);
 
-    surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
-    status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
+    surface->backend->set_paginated_mode (surface->target,
+	                                  CAIRO_PAGINATED_MODE_ANALYZE);
+    status = _cairo_meta_surface_replay_and_create_regions (surface->meta,
+	                                                    analysis);
     if (status || analysis->status) {
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = analysis->status;
 	goto FAIL;
     }
 
      if (surface->backend->set_bounding_box) {
 	 cairo_box_t bbox;
@@ -320,81 +323,71 @@ static cairo_int_status_t
 	cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis);
 
 	status = surface->backend->set_fallback_images_required (surface->target,
 								 has_fallbacks);
 	if (status)
 	    goto FAIL;
     }
 
-    surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
-
     /* Finer grained fallbacks are currently only supported for some
      * surface types */
-    switch (surface->target->type) {
-        case CAIRO_SURFACE_TYPE_PDF:
-        case CAIRO_SURFACE_TYPE_PS:
-        case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
-            has_supported = _cairo_analysis_surface_has_supported (analysis);
-            has_page_fallback = FALSE;
-            has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
-            break;
-
-	case CAIRO_SURFACE_TYPE_IMAGE:
-	case CAIRO_SURFACE_TYPE_XLIB:
-	case CAIRO_SURFACE_TYPE_XCB:
-	case CAIRO_SURFACE_TYPE_GLITZ:
-	case CAIRO_SURFACE_TYPE_QUARTZ:
-	case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
-	case CAIRO_SURFACE_TYPE_WIN32:
-	case CAIRO_SURFACE_TYPE_BEOS:
-	case CAIRO_SURFACE_TYPE_DIRECTFB:
-	case CAIRO_SURFACE_TYPE_SVG:
-	case CAIRO_SURFACE_TYPE_OS2:
-        default:
-            if (_cairo_analysis_surface_has_unsupported (analysis)) {
-                has_supported = FALSE;
-                has_page_fallback = TRUE;
-            } else {
-                has_supported = TRUE;
-                has_page_fallback = FALSE;
-            }
-            has_finegrained_fallback = FALSE;
-            break;
+    if (surface->backend->supports_fine_grained_fallbacks != NULL &&
+	surface->backend->supports_fine_grained_fallbacks (surface->target))
+    {
+	has_supported = _cairo_analysis_surface_has_supported (analysis);
+	has_page_fallback = FALSE;
+	has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
+    }
+    else
+    {
+	if (_cairo_analysis_surface_has_unsupported (analysis)) {
+	    has_supported = FALSE;
+	    has_page_fallback = TRUE;
+	} else {
+	    has_supported = TRUE;
+	    has_page_fallback = FALSE;
+	}
+	has_finegrained_fallback = FALSE;
     }
 
     if (has_supported) {
+	surface->backend->set_paginated_mode (surface->target,
+		                              CAIRO_PAGINATED_MODE_RENDER);
+
 	status = _cairo_meta_surface_replay_region (surface->meta,
 						    surface->target,
 						    CAIRO_META_REGION_NATIVE);
 	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 	if (status)
 	    goto FAIL;
     }
 
-    if (has_page_fallback)
-    {
+    if (has_page_fallback) {
 	cairo_box_int_t box;
 
+	surface->backend->set_paginated_mode (surface->target,
+		                              CAIRO_PAGINATED_MODE_FALLBACK);
+
 	box.p1.x = 0;
 	box.p1.y = 0;
 	box.p2.x = surface->width;
 	box.p2.y = surface->height;
 	status = _paint_fallback_image (surface, &box);
 	if (status)
 	    goto FAIL;
     }
 
-    if (has_finegrained_fallback)
-    {
+    if (has_finegrained_fallback) {
         cairo_region_t *region;
         cairo_box_int_t *boxes;
         int num_boxes, i;
 
-	surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
+	surface->backend->set_paginated_mode (surface->target,
+		                              CAIRO_PAGINATED_MODE_FALLBACK);
 
     /* Reset clip region before drawing the fall back images */
 	status = _cairo_surface_intersect_clip_path (surface->target,
 						     NULL,
 						     CAIRO_FILL_RULE_WINDING,
 						     CAIRO_GSTATE_TOLERANCE_DEFAULT,
 						     CAIRO_ANTIALIAS_DEFAULT);
 	if (status)
@@ -617,17 +610,17 @@ static cairo_int_status_t
 					  cairo_operator_t	     op,
 					  cairo_pattern_t	    *source,
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
 					  int			     num_glyphs,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
-					  cairo_bool_t		     backward,
+					  cairo_text_cluster_flags_t cluster_flags,
 					  cairo_scaled_font_t	    *scaled_font)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
 
     /* Optimize away erasing of nothing. */
     if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
 	return CAIRO_STATUS_SUCCESS;
@@ -639,24 +632,22 @@ static cairo_int_status_t
      * Since _cairo_surface_show_text_glyphs acquires a mutex, we release
      * and re-acquire the mutex around this nested call.
      *
      * Yes, this is ugly, but we consider it pragmatic as compared to
      * adding locking code to all 18 surface-backend-specific
      * show_glyphs functions, (which would get less testing and likely
      * lead to bugs).
      */
-    CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
     status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
 					      utf8, utf8_len,
 					      glyphs, num_glyphs,
 					      clusters, num_clusters,
-					      backward,
+					      cluster_flags,
 					      scaled_font);
-    CAIRO_MUTEX_LOCK (scaled_font->mutex);
 
     return status;
 }
 
 static cairo_surface_t *
 _cairo_paginated_surface_snapshot (void *abstract_other)
 {
     cairo_paginated_surface_t *other = abstract_other;
--- a/gfx/cairo/cairo/src/cairo-path-fill.c
+++ b/gfx/cairo/cairo/src/cairo-path-fill.c
@@ -210,14 +210,30 @@ BAIL:
  * If the path described anything but a device-axis aligned rectangle,
  * this function will return %CAIRO_INT_STATUS_UNSUPPORTED.
  */
 static cairo_int_status_t
 _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
 				  cairo_traps_t		*traps)
 {
     if (_cairo_path_fixed_is_box (path, NULL)) {
-	return _cairo_traps_tessellate_convex_quad (traps,
-                                                    path->buf_head.base.points);
+	cairo_point_t *p = path->buf_head.base.points;
+	cairo_point_t *top_left, *bot_right;
+
+	top_left = &p[0];
+	bot_right = &p[2];
+	if (top_left->x > bot_right->x || top_left->y > bot_right->y) {
+	    int n;
+
+	    /* not a simple cairo_rectangle() */
+	    for (n = 0; n < 4; n++) {
+		if (p[n].x <= top_left->x && p[n].y <= top_left->y)
+		    top_left = &p[n];
+		if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
+		    bot_right = &p[n];
+	    }
+	}
+
+	return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
--- a/gfx/cairo/cairo/src/cairo-path-stroke.c
+++ b/gfx/cairo/cairo/src/cairo-path-stroke.c
@@ -824,126 +824,147 @@ static cairo_status_t
 }
 
 /*
  * Dashed lines.  Cap each dash end, join around turns when on
  */
 static cairo_status_t
 _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_stroker_t *stroker = closure;
     double mag, remain, step_length = 0;
     double slope_dx, slope_dy;
     double dx2, dy2;
     cairo_stroke_face_t sub_start, sub_end;
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
     cairo_slope_t dev_slope;
-    cairo_bool_t fully_in_bounds = TRUE;
     cairo_line_t segment;
+    cairo_bool_t fully_in_bounds;
+    cairo_status_t status;
 
     stroker->has_initial_sub_path = stroker->dash_starts_on;
 
     if (p1->x == p2->x && p1->y == p2->y)
 	return CAIRO_STATUS_SUCCESS;
 
+    fully_in_bounds = TRUE;
     if (stroker->has_bounds &&
-	(!_cairo_box_contains_point (&stroker->bounds, p1) ||
-	 !_cairo_box_contains_point (&stroker->bounds, p2)))
+	(! _cairo_box_contains_point (&stroker->bounds, p1) ||
+	 ! _cairo_box_contains_point (&stroker->bounds, p2)))
     {
 	fully_in_bounds = FALSE;
     }
 
     _cairo_slope_init (&dev_slope, p1, p2);
 
     slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
     slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
 
-    if (!_compute_normalized_device_slope (&slope_dx, &slope_dy, stroker->ctm_inverse, &mag))
+    if (! _compute_normalized_device_slope (&slope_dx, &slope_dy,
+					   stroker->ctm_inverse, &mag))
+    {
 	return CAIRO_STATUS_SUCCESS;
+    }
 
     remain = mag;
     segment.p1 = *p1;
     while (remain) {
 	step_length = MIN (stroker->dash_remain, remain);
 	remain -= step_length;
 	dx2 = slope_dx * (mag - remain);
 	dy2 = slope_dy * (mag - remain);
 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
 	segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
 	segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
 
-	if (fully_in_bounds ||
-	    _cairo_box_intersects_line_segment (&stroker->bounds, &segment))
+	if (stroker->dash_on &&
+	    (fully_in_bounds ||
+	     (! stroker->has_first_face && stroker->dash_starts_on) ||
+	     _cairo_box_intersects_line_segment (&stroker->bounds, &segment)))
 	{
-	    if (stroker->dash_on) {
-		status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, &dev_slope, slope_dx, slope_dy, &sub_start, &sub_end);
+	    status = _cairo_stroker_add_sub_edge (stroker,
+						  &segment.p1, &segment.p2,
+						  &dev_slope,
+						  slope_dx, slope_dy,
+						  &sub_start, &sub_end);
+	    if (status)
+		return status;
+
+	    if (stroker->has_current_face) {
+		/* Join with final face from previous segment */
+		status = _cairo_stroker_join (stroker,
+					      &stroker->current_face,
+					      &sub_start);
 		if (status)
 		    return status;
 
-		if (stroker->has_current_face) {
-		    /* Join with final face from previous segment */
-		    status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
-		    stroker->has_current_face = FALSE;
-		    if (status)
-			return status;
-		} else if (!stroker->has_first_face && stroker->dash_starts_on) {
-		    /* Save sub path's first face in case needed for closing join */
-		    stroker->first_face = sub_start;
-		    stroker->has_first_face = TRUE;
-		} else {
-		    /* Cap dash start if not connecting to a previous segment */
-		    status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
-		    if (status)
-			return status;
-		}
+		stroker->has_current_face = FALSE;
+	    } else if (! stroker->has_first_face && stroker->dash_starts_on) {
+		/* Save sub path's first face in case needed for closing join */
+		stroker->first_face = sub_start;
+		stroker->has_first_face = TRUE;
+	    } else {
+		/* Cap dash start if not connecting to a previous segment */
+		status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
+		if (status)
+		    return status;
+	    }
 
-		if (remain) {
-		    /* Cap dash end if not at end of segment */
-		    status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
-		    if (status)
-			return status;
-		} else {
-		    stroker->current_face = sub_end;
-		    stroker->has_current_face = TRUE;
-		}
+	    if (remain) {
+		/* Cap dash end if not at end of segment */
+		status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
+		if (status)
+		    return status;
 	    } else {
-		if (stroker->has_current_face) {
-		    /* Cap final face from previous segment */
-		    status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
-		    if (status)
-			return status;
-		    stroker->has_current_face = FALSE;
-		}
+		stroker->current_face = sub_end;
+		stroker->has_current_face = TRUE;
+	    }
+	} else {
+	    if (stroker->has_current_face) {
+		/* Cap final face from previous segment */
+		status = _cairo_stroker_add_trailing_cap (stroker,
+							  &stroker->current_face);
+		if (status)
+		    return status;
+
+		stroker->has_current_face = FALSE;
 	    }
 	}
 
 	_cairo_stroker_step_dash (stroker, step_length);
 	segment.p1 = segment.p2;
     }
 
-    if (stroker->dash_on && !stroker->has_current_face) {
+    if (stroker->dash_on && ! stroker->has_current_face) {
 	/* This segment ends on a transition to dash_on, compute a new face
-	 * and add cap for the begining of the next dash_on step.
+	 * and add cap for the beginning of the next dash_on step.
 	 *
 	 * Note: this will create a degenerate cap if this is not the last line
 	 * in the path. Whether this behaviour is desirable or not is debatable.
-	 * On one side these degnerate caps can not be reproduced with regular path stroking.
-	 * On the other side Acroread 7 also produces the degenerate caps. */
-	_compute_face (point, &dev_slope, slope_dx, slope_dy, stroker, &stroker->current_face);
-	stroker->has_current_face = TRUE;
-	status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
+	 * On one side these degenerate caps can not be reproduced with regular
+	 * path stroking.
+	 * On the other hand, Acroread 7 also produces the degenerate caps.
+	 */
+	_compute_face (point, &dev_slope,
+		       slope_dx, slope_dy,
+		       stroker,
+		       &stroker->current_face);
+
+	status = _cairo_stroker_add_leading_cap (stroker,
+						 &stroker->current_face);
 	if (status)
 	    return status;
+
+	stroker->has_current_face = TRUE;
     }
 
     stroker->current_point = *point;
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_stroker_curve_to (void *closure,
 			 cairo_point_t *b,
 			 cairo_point_t *c,
 			 cairo_point_t *d)
 {
@@ -1252,22 +1273,22 @@ static cairo_status_t
 }
 
 static cairo_status_t
 _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
 {
     cairo_status_t status;
     cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
     cairo_fixed_t half_line_width = stroker->half_line_width;
-    cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
-    cairo_point_t *a, *b;
-    cairo_point_t r[4];
     int i;
 
     for (i = 0; i < stroker->num_segments; i++) {
+	cairo_point_t *a, *b;
+	cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
+
 	a = &stroker->segments[i].p1;
 	b = &stroker->segments[i].p2;
 
 	/* For each segment we generate a single rectangular
 	 * trapezoid. This rectangle is based on a perpendicular
 	 * extension (by half the line width) of the segment endpoints
 	 * after some adjustments of the endpoints to account for caps
 	 * and joins.
@@ -1310,53 +1331,61 @@ static cairo_status_t
 	    } else {
 		if (lengthen_initial)
 		    a->x += half_line_width;
 		if (shorten_final)
 		    b->x += half_line_width;
 		else if (lengthen_final)
 		    b->x -= half_line_width;
 	    }
+
+	    if (a->x > b->x) {
+		cairo_point_t *t;
+
+		t = a;
+		a = b;
+		b = t;
+	    }
 	} else {
 	    if (a->y < b->y) {
 		if (lengthen_initial)
 		    a->y -= half_line_width;
 		if (shorten_final)
 		    b->y -= half_line_width;
 		else if (lengthen_final)
 		    b->y += half_line_width;
 	    } else {
 		if (lengthen_initial)
 		    a->y += half_line_width;
 		if (shorten_final)
 		    b->y += half_line_width;
 		else if (lengthen_final)
 		    b->y -= half_line_width;
 	    }
+
+	    if (a->y > b->y) {
+		cairo_point_t *t;
+
+		t = a;
+		a = b;
+		b = t;
+	    }
 	}
 
 	/* Form the rectangle by expanding by half the line width in
-	 * either perdendicular direction. */
-	r[0] = *a;
-	r[1] = *b;
-	r[2] = *b;
-	r[3] = *a;
+	 * either perpendicular direction. */
 	if (a->y == b->y) {
-	    r[0].y -= half_line_width;
-	    r[1].y -= half_line_width;
-	    r[2].y += half_line_width;
-	    r[3].y += half_line_width;
+	    a->y -= half_line_width;
+	    b->y += half_line_width;
 	} else {
-	    r[0].x -= half_line_width;
-	    r[1].x -= half_line_width;
-	    r[2].x += half_line_width;
-	    r[3].x += half_line_width;
+	    a->x -= half_line_width;
+	    b->x += half_line_width;
 	}
 
-	status = _cairo_traps_tessellate_convex_quad (stroker->traps, r);
+	status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
 	if (status)
 	    return status;
     }
 
     stroker->num_segments = 0;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1434,17 +1463,17 @@ static cairo_int_status_t
 				      cairo_traps_t		*traps)
 {
     cairo_rectilinear_stroker_t rectilinear_stroker;
     cairo_int_status_t status;
 
     /* This special-case rectilinear stroker only supports
      * miter-joined lines (not curves) and no dashing and a
      * translation-only matrix (though it could probably be extended
-     * to support a matrix with uniform, integer sacling).
+     * to support a matrix with uniform, integer scaling).
      *
      * It also only supports horizontal and vertical line_to
      * elements. But we don't catch that here, but instead return
      * UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any
      * non-rectilinear line_to is encountered.
      */
     if (path->has_curve_to)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1479,16 +1508,15 @@ static cairo_int_status_t
 					  _cairo_rectilinear_stroker_close_path,
 					  &rectilinear_stroker);
     if (status)
 	goto BAIL;
 
     status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
 
 BAIL:
-
     _cairo_rectilinear_stroker_fini (&rectilinear_stroker);
 
     if (status)
-	_cairo_traps_fini (traps);
+	_cairo_traps_clear (traps);
 
     return status;
 }
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -187,16 +187,46 @@ cairo_status_t
 
     /* The reference count and user_data array are unique to the copy. */
     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
     _cairo_user_data_array_init (&pattern->user_data);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+cairo_status_t
+_cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
+			      const cairo_pattern_t *other)
+{
+    cairo_status_t status;
+
+    /* We don't bother doing any fancy copy-on-write implementation
+     * for the pattern's data. It's generally quite tiny. */
+    status = _cairo_pattern_init_copy (pattern, other);
+    if (status)
+	return status;
+
+    /* But we do let the surface snapshot stuff be as fancy as it
+     * would like to be. */
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern =
+	    (cairo_surface_pattern_t *) pattern;
+	cairo_surface_t *surface = surface_pattern->surface;
+
+	surface_pattern->surface = _cairo_surface_snapshot (surface);
+
+	cairo_surface_destroy (surface);
+
+	if (surface_pattern->surface->status)
+	    return surface_pattern->surface->status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 void
 _cairo_pattern_fini (cairo_pattern_t *pattern)
 {
     _cairo_user_data_array_fini (&pattern->user_data);
 
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
 	break;
@@ -779,17 +809,17 @@ cairo_pattern_get_user_data (cairo_patte
  **/
 cairo_status_t
 cairo_pattern_set_user_data (cairo_pattern_t		 *pattern,
 			     const cairo_user_data_key_t *key,
 			     void			 *user_data,
 			     cairo_destroy_func_t	  destroy)
 {
     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return pattern->status;
 
     return _cairo_user_data_array_set_data (&pattern->user_data,
 					    key, user_data, destroy);
 }
 
 /* make room for at least one more color stop */
 static cairo_status_t
 _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
@@ -1212,16 +1242,18 @@ static cairo_int_status_t
     pixman_image_t	  *pixman_image;
     pixman_transform_t	  pixman_transform;
     cairo_status_t	  status;
     cairo_bool_t	  repeat = FALSE;
 
     pixman_gradient_stop_t pixman_stops_static[2];
     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
     unsigned int i;
+    int clone_offset_x, clone_offset_y;
+    cairo_matrix_t matrix = pattern->base.matrix;
 
     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
 	pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
 	if (pixman_stops == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     for (i = 0; i < pattern->n_stops; i++) {
@@ -1231,21 +1263,56 @@ static cairo_int_status_t
 	pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
 	pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
     }
 
     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
     {
 	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
 	pixman_point_fixed_t p1, p2;
+	cairo_fixed_t xdim, ydim;
 
-	p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
-	p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
-	p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
-	p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
+	xdim = linear->p2.x - linear->p1.x;
+	ydim = linear->p2.y - linear->p1.y;
+
+	/*
+	 * Transform the matrix to avoid overflow when converting between
+	 * cairo_fixed_t and pixman_fixed_t (without incurring performance
+	 * loss when the transformation is unnecessary).
+	 *
+	 * XXX: Consider converting out-of-range co-ordinates and transforms.
+	 * Having a function to compute the required transformation to
+	 * "normalize" a given bounding box would be generally useful -
+	 * cf linear patterns, gradient patterns, surface patterns...
+	 */
+#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
+	if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
+	    _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
+	{
+	    double sf;
+
+	    if (xdim > ydim)
+		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
+	    else
+		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
+
+	    p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
+	    p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
+	    p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
+	    p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
+
+	    cairo_matrix_scale (&matrix, sf, sf);
+	}
+	else
+	{
+	    p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
+	    p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
+	    p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
+	    p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
+	}
 
 	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
 							    pixman_stops,
 							    pattern->n_stops);
     }
     else
     {
 	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
@@ -1279,17 +1346,17 @@ static cairo_int_status_t
 							  PIXMAN_a8r8g8b8);
 	if (image->base.status)
 	{
 	    pixman_image_unref (pixman_image);
 	    return image->base.status;
 	}
 
 	attr->x_offset = attr->y_offset = 0;
-	attr->matrix = pattern->base.matrix;
+	attr->matrix = matrix;
 	attr->extend = pattern->base.extend;
 	attr->filter = CAIRO_FILTER_NEAREST;
 	attr->acquired = FALSE;
 
 	*out = &image->base;
 
 	return CAIRO_STATUS_SUCCESS;
     }
@@ -1327,17 +1394,17 @@ static cairo_int_status_t
 
     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;
     }
 
-    _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
+    _cairo_matrix_to_pixman_matrix (&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) {
     case CAIRO_EXTEND_NONE:
@@ -1361,17 +1428,20 @@ static cairo_int_status_t
 			    x, y,
 			    0, 0,
 			    0, 0,
 			    width, height);
 
     pixman_image_unref (pixman_image);
 
     status = _cairo_surface_clone_similar (dst, &image->base,
-					   0, 0, width, height, out);
+					   0, 0, width, height,
+					   &clone_offset_x,
+					   &clone_offset_y,
+					   out);
 
     cairo_surface_destroy (&image->base);
 
     attr->x_offset = -x;
     attr->y_offset = -y;
     cairo_matrix_init_identity (&attr->matrix);
     attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
     attr->filter = CAIRO_FILTER_NEAREST;
@@ -1623,40 +1693,131 @@ cairo_bool_t
     case CAIRO_PATTERN_TYPE_RADIAL:
 	return _gradient_is_opaque (&pattern->gradient.base);
     }
 
     ASSERT_NOT_REACHED;
     return FALSE;
 }
 
+/**
+ * _cairo_pattern_analyze_filter:
+ * @pattern: surface pattern
+ * @pad_out: location to store necessary padding in the source image, or %NULL
+ * Returns: the optimized #cairo_filter_t to use with @pattern.
+ *
+ * Analyze the filter to determine how much extra needs to be sampled
+ * from the source image to account for the filter radius and whether
+ * we can optimize the filter to a simpler value.
+ *
+ * XXX: We don't actually have any way of querying the backend for
+ *      the filter radius, so we just guess base on what we know that
+ *      backends do currently (see bug #10508)
+ */
+static cairo_filter_t
+_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern,
+			       double                  *pad_out)
+{
+    double pad;
+    cairo_filter_t optimized_filter;
+
+    switch (pattern->base.filter) {
+    case CAIRO_FILTER_GOOD:
+    case CAIRO_FILTER_BEST:
+    case CAIRO_FILTER_BILINEAR:
+	/* If source pixels map 1:1 onto destination pixels, we do
+	 * not need to filter (and do not want to filter, since it
+	 * will cause blurriness)
+	 */
+	if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) {
+	    pad = 0.;
+	    optimized_filter = CAIRO_FILTER_NEAREST;
+	} else {
+	    /* 0.5 is enough for a bilinear filter. It's possible we
+	     * should defensively use more for CAIRO_FILTER_BEST, but
+	     * without a single example, it's hard to know how much
+	     * more would be defensive...
+	     */
+	    pad = 0.5;
+	    optimized_filter = pattern->base.filter;
+	}
+	break;
+
+    case CAIRO_FILTER_FAST:
+    case CAIRO_FILTER_NEAREST:
+    case CAIRO_FILTER_GAUSSIAN:
+    default:
+	pad = 0.;
+	optimized_filter = pattern->base.filter;
+	break;
+    }
+
+    if (pad_out)
+	*pad_out = pad;
+
+    return optimized_filter;
+}
+
+
+static double
+_pixman_nearest_sample (double d)
+{
+    return ceil (d - .5);
+}
+
 static cairo_int_status_t
 _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 					    cairo_surface_t	       *dst,
 					    int			       x,
 					    int			       y,
 					    unsigned int	       width,
 					    unsigned int	       height,
 					    cairo_surface_t	       **out,
 					    cairo_surface_attributes_t *attr)
 {
     cairo_int_status_t status;
     int tx, ty;
+    double pad;
 
     attr->acquired = FALSE;
 
     attr->extend = pattern->base.extend;
-    attr->filter = pattern->base.filter;
+    attr->filter = _cairo_pattern_analyze_filter (pattern, &pad);
+
     if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
 					      &tx, &ty))
     {
 	cairo_matrix_init_identity (&attr->matrix);
 	attr->x_offset = tx;
 	attr->y_offset = ty;
-	attr->filter = CAIRO_FILTER_NEAREST;
+    }
+    else if (attr->filter == CAIRO_FILTER_NEAREST)
+    {
+	/*
+	 * For NEAREST, we can remove the fractional translation component
+	 * from the transformation - this ensures that the pattern will always
+	 * hit fast-paths in the backends for simple transformations that
+	 * become (almost) identity, without loss of quality.
+	 */
+	attr->matrix = pattern->base.matrix;
+	attr->matrix.x0 = 0;
+	attr->matrix.y0 = 0;
+	if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
+	    /* The rounding here is rather peculiar as it needs to match the
+	     * rounding performed on the sample coordinate used by pixman.
+	     */
+	    attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
+	    attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
+	} else {
+	    attr->matrix.x0 = pattern->base.matrix.x0;
+	    attr->matrix.y0 = pattern->base.matrix.y0;
+	}
+
+	attr->x_offset = attr->y_offset = 0;
+	tx = ty = 0;
     }
     else
     {
 	attr->matrix = pattern->base.matrix;
 	attr->x_offset = attr->y_offset = 0;
 	tx = 0;
 	ty = 0;
     }
@@ -1729,82 +1890,94 @@ static cairo_int_status_t
 	if (status) {
 	    cairo_surface_destroy (*out);
 	    *out = NULL;
 	}
 
 	return status;
     }
 
-    if (_cairo_surface_is_image (dst))
-    {
+    if (_cairo_surface_is_image (dst)) {
 	cairo_image_surface_t *image;
 
 	status = _cairo_surface_acquire_source_image (pattern->surface,
 						      &image,
 						      &attr->extra);
 	if (status)
 	    return status;
 
 	*out = &image->base;
 	attr->acquired = TRUE;
-    }
-    else
-    {
+    } else {
 	cairo_rectangle_int_t extents;
+
 	status = _cairo_surface_get_extents (pattern->surface, &extents);
 	if (status)
 	    return status;
 
-	/* If we're repeating, we just play it safe and clone the entire surface. */
-	/* If requested width and height are -1, clone the entire surface.
-	 * This is relied on in the svg backend. */
-	if (attr->extend == CAIRO_EXTEND_REPEAT ||
-	    (width == (unsigned int) -1 && height == (unsigned int) -1)) {
-	    x = extents.x;
-	    y = extents.y;
-	    width = extents.width;
-	    height = extents.height;
-	} else {
+	/* If we're repeating, we just play it safe and clone the
+	 * entire surface - i.e. we use the existing extents.
+	 */
+	if (attr->extend != CAIRO_EXTEND_REPEAT) {
+	    cairo_rectangle_int_t sampled_area;
+
 	    /* Otherwise, we first transform the rectangle to the
 	     * coordinate space of the source surface so that we can
 	     * clone only that portion of the surface that will be
-	     * read. */
-	    if (! _cairo_matrix_is_identity (&attr->matrix)) {
+	     * read.
+	     */
+	    if (_cairo_matrix_is_identity (&attr->matrix)) {
+		sampled_area.x = x;
+		sampled_area.y = y;
+		sampled_area.width  = width;
+		sampled_area.height = height;
+	    } else {
 		double x1 = x;
 		double y1 = y;
 		double x2 = x + width;
 		double y2 = y + height;
-		cairo_bool_t is_tight;
 
 		_cairo_matrix_transform_bounding_box  (&attr->matrix,
 						       &x1, &y1, &x2, &y2,
-						       &is_tight);
+						       NULL);
+
+		sampled_area.x = floor (x1 - pad);
+		sampled_area.y = floor (y1 - pad);
+		sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
+		sampled_area.height = ceil (y2 + pad) - sampled_area.y;
 
-		/* The transform_bounding_box call may have resulted
-		 * in a region larger than the surface, but we never
-		 * want to clone more than the surface itself, (we
-		 * know we're not repeating at this point due to the
-		 * above.
-		 *
-		 * XXX: The one padding here is to account for filter
-		 * radius.  It's a workaround right now, until we get a
-		 * proper fix. (see bug #10508)
-		 */
-		x = MAX (0, floor (x1) - 1);
-		y = MAX (0, floor (y1) - 1);
-		width = MIN (extents.width, ceil (x2) + 1) - x;
-		height = MIN (extents.height, ceil (y2) + 1) - y;
 	    }
-	    x += tx;
-	    y += ty;
+
+	    sampled_area.x += tx;
+	    sampled_area.y += ty;
+
+	    /* Never acquire a larger area than the source itself */
+	    _cairo_rectangle_intersect (&extents, &sampled_area);
 	}
 
 	status = _cairo_surface_clone_similar (dst, pattern->surface,
-					       x, y, width, height, out);
+					       extents.x, extents.y,
+					       extents.width, extents.height,
+					       &x, &y, out);
+	if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) {
+	    if (_cairo_matrix_is_identity (&attr->matrix)) {
+		attr->x_offset -= x;
+		attr->y_offset -= y;
+	    } else {
+		cairo_matrix_t m;
+
+		x -= attr->x_offset;
+		y -= attr->y_offset;
+		attr->x_offset = 0;
+		attr->y_offset = 0;
+
+		cairo_matrix_init_translate (&m, -x, -y);
+		cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
+	    }
+	}
     }
 
     return status;
 }
 
 /**
  * _cairo_pattern_acquire_surface:
  * @pattern: a #cairo_pattern_t
@@ -1815,16 +1988,19 @@ static cairo_int_status_t
  * @height: height of destination area
  * @surface_out: location to store a pointer to a surface
  * @attributes: surface attributes that destination backend should apply to
  * the returned surface
  *
  * A convenience function to obtain a surface to use as the source for
  * drawing on @dst.
  *
+ * Note that this function is only suitable for use when the destination
+ * surface is pixel based and 1 device unit maps to one pixel.
+ *
  * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
  **/
 cairo_int_status_t
 _cairo_pattern_acquire_surface (cairo_pattern_t		   *pattern,
 				cairo_surface_t		   *dst,
 				int			   x,
 				int			   y,
 				unsigned int		   width,
@@ -2044,25 +2220,30 @@ cairo_status_t
     {
 	cairo_status_t status;
 	cairo_rectangle_int_t surface_extents;
 	cairo_surface_pattern_t *surface_pattern =
 	    (cairo_surface_pattern_t *) pattern;
 	cairo_surface_t *surface = surface_pattern->surface;
 	cairo_matrix_t imatrix;
 	double x1, y1, x2, y2;
+	double pad;
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
 	if (status)
 	    return status;
 
-	x1 = surface_extents.x;
-	y1 = surface_extents.y;
-	x2 = x1 + surface_extents.width;
-	y2 = y1 + surface_extents.height;
+	/* The filter can effectively enlarge the extents of the
+	 * pattern, so extend as necessary.
+	 */
+	_cairo_pattern_analyze_filter (surface_pattern, &pad);
+	x1 = surface_extents.x - pad;
+	y1 = surface_extents.y - pad;
+	x2 = surface_extents.x + surface_extents.width + pad;