merge backout
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 08 Apr 2010 22:59:43 +0900
changeset 40593 fb1f77986768349f563cb9b9ce1dbd2577a52f2f
parent 40592 85454945336e2c5bac27ff125e2ae27200cb416c (current diff)
parent 40591 5b8f688d42442e06a609ceeec80a1b0f84d1001c (diff)
child 40594 c4733ab603efcba8afff349ed80d81b8afc344fc
push idunknown
push userunknown
push dateunknown
milestone1.9.3a5pre
merge backout
gfx/cairo/add-a-stash-of-cairo_t-s.patch
gfx/cairo/bgr.patch
gfx/cairo/cairo/src/cairo-base64-stream.c
gfx/cairo/cairo/src/cairo-bentley-ottmann-rectangular.c
gfx/cairo/cairo/src/cairo-bentley-ottmann-rectilinear.c
gfx/cairo/cairo/src/cairo-drm.h
gfx/cairo/cairo/src/cairo-eagle-context.c
gfx/cairo/cairo/src/cairo-features-win32.h
gfx/cairo/cairo/src/cairo-gl-glyphs.c
gfx/cairo/cairo/src/cairo-gl-private.h
gfx/cairo/cairo/src/cairo-gl-shaders.c
gfx/cairo/cairo/src/cairo-gl-surface.c
gfx/cairo/cairo/src/cairo-gl.h
gfx/cairo/cairo/src/cairo-glx-context.c
gfx/cairo/cairo/src/cairo-no-features.h
gfx/cairo/cairo/src/cairo-qt.h
gfx/cairo/cairo/src/cairo-recording-surface-private.h
gfx/cairo/cairo/src/cairo-recording-surface.c
gfx/cairo/cairo/src/cairo-rtree-private.h
gfx/cairo/cairo/src/cairo-rtree.c
gfx/cairo/cairo/src/cairo-script-surface.c
gfx/cairo/cairo/src/cairo-script.h
gfx/cairo/cairo/src/cairo-skia.h
gfx/cairo/cairo/src/cairo-slope-private.h
gfx/cairo/cairo/src/cairo-supported-features.h
gfx/cairo/cairo/src/cairo-surface-clipper-private.h
gfx/cairo/cairo/src/cairo-surface-clipper.c
gfx/cairo/cairo/src/cairo-surface-wrapper-private.h
gfx/cairo/cairo/src/cairo-surface-wrapper.c
gfx/cairo/cairo/src/cairo-tee-surface-private.h
gfx/cairo/cairo/src/cairo-tee-surface.c
gfx/cairo/cairo/src/cairo-vg-surface.c
gfx/cairo/cairo/src/cairo-vg.h
gfx/cairo/cairo/src/cairo-xml-surface.c
gfx/cairo/cairo/src/cairo-xml.h
gfx/cairo/clip-invariant.patch
gfx/cairo/d2d.patch
gfx/cairo/disable-server-gradients.patch
gfx/cairo/fix-clip-copy.patch
gfx/cairo/fix-clip-region-simplification.patch
gfx/cairo/fix-unnecessary-fallback.patch
gfx/cairo/fix-zero-length-gradient.patch
gfx/cairo/handle-a1.patch
gfx/cairo/surface-clipper.patch
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -63,44 +63,16 @@ quartz-minimze-gradient-repeat.patch: re
 quartz-first-stop.patch: return the first stop for negative positions on the gradient line of a nonrepeating linear gradient
 
 quartz-glyph-extents.patch: bug 534260; work around incorrect glyph extents returned by quartz for anomalous empty glyphs
 
 premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface
 
 xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension
 
-remove-comma: remove a comma from enum
-
-d2d.patch: add d2d support
-
-fix-zero-len-graident.patch: fix zero length gradients
-
-fix-clip-copy.patch: fix clip copying
-
-fix-clip-region-simplification.patch: fixes a bug in clip region simplifications
-
-expand-in-stroke-limits.patch: expand the in-stroke limits to avoid a bug
-
-d2d-dwrite.patch: update the d2d/dwrite stuff
-
-add-a-stash-of-cairo_t-s.patch: use the stash to avoid malloc/freeing cairo_t's
-
-bgr.patch: fix image wrapping
-
-disable-server-graidents.patch: disable server-side gradients
-
-clip-invariant.patch: make rasterization closer to being clip invariant
-
-fix-unnecessary-fallback.patch: avoid unnecessary fallback
-
-handle-a1-upload.patch: handle a1 image uploads through converter
-
-surface-clipper.patch: remove an incorrect optimization
-
 ==== pixman patches ====
 
 pixman-neon.patch: add ARM NEON optimized compositing functions
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 ==== disable printing patch ====
 
deleted file mode 100644
--- a/gfx/cairo/add-a-stash-of-cairo_t-s.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-commit dfec2c249915560cedd2b49326c6629ad8a0b0f2
-Author: Jeff Muizelaar <jmuizelaar@mozilla.com>
-Date:   Tue Mar 2 16:01:41 2010 -0500
-
-    add a stash of cairo_t's
-
-diff --git a/src/cairo.c b/src/cairo.c
-index 3c9d892..4b27b83 100644
---- a/src/cairo.c
-+++ b/src/cairo.c
-@@ -119,7 +119,63 @@ _cairo_set_error (cairo_t *cr, cairo_status_t status)
-     _cairo_status_set_error (&cr->status, _cairo_error (status));
- }
- 
--#if HAS_ATOMIC_OPS
-+#if defined(_MSC_VER)
-+#pragma intrinsic(_BitScanForward)
-+static __forceinline int
-+ffs(int x)
-+{
-+    unsigned long i;
-+
-+    if (_BitScanForward(&i, x) != 0)
-+	return i + 1;
-+
-+    return 0;
-+}
-+#endif
-+
-+
-+#if CAIRO_NO_MUTEX
-+/* We keep a small stash of contexts to reduce malloc pressure */
-+#define CAIRO_STASH_SIZE 4
-+static struct {
-+    cairo_t pool[CAIRO_STASH_SIZE];
-+    int occupied;
-+} _context_stash;
-+
-+static cairo_t *
-+_context_get (void)
-+{
-+    int avail, old, new;
-+
-+    old = _context_stash.occupied;
-+    avail = ffs (~old) - 1;
-+    if (avail >= CAIRO_STASH_SIZE)
-+	return malloc (sizeof (cairo_t));
-+
-+    new = old | (1 << avail);
-+    _context_stash.occupied = new;
-+
-+    return &_context_stash.pool[avail];
-+}
-+
-+static void
-+_context_put (cairo_t *cr)
-+{
-+    int old, new, avail;
-+
-+    if (cr < &_context_stash.pool[0] ||
-+	cr >= &_context_stash.pool[CAIRO_STASH_SIZE])
-+    {
-+	free (cr);
-+	return;
-+    }
-+
-+    avail = ~(1 << (cr - &_context_stash.pool[0]));
-+    old = _context_stash.occupied;
-+    new = old & avail;
-+    _context_stash.occupied = new;
-+}
-+#elif HAS_ATOMIC_OPS
- /* We keep a small stash of contexts to reduce malloc pressure */
- #define CAIRO_STASH_SIZE 4
- static struct {
deleted file mode 100644
--- a/gfx/cairo/bgr.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-commit d2120bdb06c9aacc470bb346d6bc2071c2e0749d
-Author: Jeff Muizelaar <jmuizelaar@mozilla.com>
-Date:   Fri Mar 12 15:32:09 2010 -0500
-
-    BGR
-
-diff --git a/src/cairo-surface.c b/src/cairo-surface.c
-index 332e3ab..4a1d6a0 100644
---- a/src/cairo-surface.c
-+++ b/src/cairo-surface.c
-@@ -1501,7 +1501,9 @@ static void
- _wrap_release_source_image (void *data)
- {
-     struct acquire_source_image_data *acquire_data = data;
--    _cairo_surface_release_source_image (acquire_data->src, acquire_data->image, acquire_data->image_extra);
-+    _cairo_surface_release_source_image (acquire_data->src,
-+					 acquire_data->image,
-+					 acquire_data->image_extra);
-     free(data);
- }
- 
-@@ -1515,42 +1517,47 @@ _wrap_image (cairo_surface_t *src,
-     cairo_image_surface_t *surface;
-     cairo_status_t status;
- 
--    struct acquire_source_image_data *data = malloc(sizeof(*data));
-+    struct acquire_source_image_data *data = malloc (sizeof (*data));
-+    if (unlikely (data == NULL))
-+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-     data->src = src;
-     data->image = image;
-     data->image_extra = image_extra;
- 
--    surface = (cairo_image_surface_t*)cairo_image_surface_create_for_data (image->data,
--	    image->format,
--	    image->width,
--	    image->height,
--	    image->stride);
-+    surface = (cairo_image_surface_t*)
-+	_cairo_image_surface_create_with_pixman_format (image->data,
-+							image->pixman_format,
-+							image->width,
-+							image->height,
-+							image->stride);
-     status = surface->base.status;
--    if (status)
-+    if (status) {
-+	free (data);
- 	return status;
-+    }
- 
-     status = _cairo_user_data_array_set_data (&surface->base.user_data,
--	    &wrap_image_key,
--	    data,
--	    _wrap_release_source_image);
-+					      &wrap_image_key,
-+					      data,
-+					      _wrap_release_source_image);
-     if (status) {
- 	cairo_surface_destroy (&surface->base);
-+	free (data);
- 	return status;
-     }
--/*
--    pixman_image_set_component_alpha (surface->pixman_image,
--            pixman_image_get_component_alpha (image->pixman_image));
--*/
-+
-+    pixman_image_set_component_alpha (
-+	surface->pixman_image,
-+	pixman_image_get_component_alpha (image->pixman_image));
-+
-     *out = surface;
-     return CAIRO_STATUS_SUCCESS;
- }
- 
--
- /**
-  * _cairo_surface_clone_similar:
-  * @surface: a #cairo_surface_t
-  * @src: the source image
-- * @content: target content mask
-  * @src_x: extent for the rectangle in src we actually care about
-  * @src_y: extent for the rectangle in src we actually care about
-  * @width: extent for the rectangle in src we actually care about
-@@ -1627,12 +1634,12 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
- 		    _cairo_surface_release_source_image (src, image, image_extra);
- 		} else {
- 		    status =
--		    surface->backend->clone_similar (surface, &image->base,
--						     src_x, src_y,
--						     width, height,
--						     clone_offset_x,
--						     clone_offset_y,
--						     clone_out);
-+			surface->backend->clone_similar (surface, &image->base,
-+							 src_x, src_y,
-+							 width, height,
-+							 clone_offset_x,
-+							 clone_offset_y,
-+							 clone_out);
- 		    cairo_surface_destroy(&image->base);
- 		}
- 	    }
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -69,20 +69,17 @@ endif
 
 CSRCS   = \
         cairo.c \
         cairo-analysis-surface.c \
         cairo-arc.c \
         cairo-array.c \
 	cairo-atomic.c \
         cairo-bentley-ottmann.c \
-	cairo-bentley-ottmann-rectilinear.c \
-	cairo-bentley-ottmann-rectangular.c \
-        cairo-base64-stream.c \
-	cairo-cache.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 \
@@ -90,43 +87,41 @@ CSRCS   = \
         cairo-freelist.c \
         cairo-gstate.c \
         cairo-hash.c \
         cairo-hull.c \
 	cairo-image-info.c \
         cairo-image-surface.c \
         cairo-lzw.c \
         cairo-matrix.c \
+        cairo-meta-surface.c \
 	cairo-misc.c \
 	cairo-mutex.c \
         cairo-output-stream.c \
         cairo-paginated-surface.c \
         cairo-path.c \
         cairo-path-bounds.c \
         cairo-path-fill.c \
         cairo-path-fixed.c \
         cairo-path-in-fill.c \
         cairo-path-stroke.c \
         cairo-pattern.c \
         cairo-pen.c \
         cairo-polygon.c \
-	cairo-recording-surface.c \
         cairo-rectangle.c \
         cairo-region.c \
         cairo-scaled-font.c \
         cairo-scaled-font-subsets.c \
+        cairo-skiplist.c \
         cairo-slope.c \
         cairo-spans.c \
         cairo-spline.c \
         cairo-stroke-style.c \
         cairo-surface.c \
-	cairo-surface-clipper.c \
         cairo-surface-fallback.c \
-	cairo-surface-wrapper.c \
-	cairo-tee-surface.c \
         cairo-tor-scan-converter.c \
         cairo-toy-font-face.c \
         cairo-traps.c \
         cairo-unicode.c \
 	cairo-user-font.c \
 	cairo-version.c \
         cairo-wideint.c \
         $(NULL)
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -33,21 +33,23 @@
  */
 
 #ifndef CAIRO_ANALYSIS_SURFACE_H
 #define CAIRO_ANALYSIS_SURFACE_H
 
 #include "cairoint.h"
 
 cairo_private cairo_surface_t *
-_cairo_analysis_surface_create (cairo_surface_t		*target);
+_cairo_analysis_surface_create (cairo_surface_t		*target,
+				int			 width,
+				int			 height);
 
 cairo_private void
 _cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
-				 const cairo_matrix_t  *ctm);
+				 cairo_matrix_t  *ctm);
 
 cairo_private void
 _cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
 				 cairo_matrix_t  *ctm);
 
 cairo_private cairo_region_t *
 _cairo_analysis_surface_get_supported (cairo_surface_t *surface);
 
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -33,30 +33,32 @@
  *      Keith Packard <keithp@keithp.com>
  *      Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
 
 #include "cairo-analysis-surface-private.h"
 #include "cairo-paginated-private.h"
-#include "cairo-recording-surface-private.h"
-#include "cairo-region-private.h"
+#include "cairo-meta-surface-private.h"
 
 typedef struct {
     cairo_surface_t base;
+    int width;
+    int height;
 
-    cairo_surface_t *target;
+    cairo_surface_t	*target;
 
     cairo_bool_t first_op;
     cairo_bool_t has_supported;
     cairo_bool_t has_unsupported;
 
     cairo_region_t supported_region;
     cairo_region_t fallback_region;
+    cairo_rectangle_int_t current_clip;
     cairo_box_t page_bbox;
 
     cairo_bool_t has_ctm;
     cairo_matrix_t ctm;
 
 } cairo_analysis_surface_t;
 
 cairo_int_status_t
@@ -71,67 +73,90 @@ cairo_int_status_t
     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_RECORDING_SURFACE_PATTERN ||
-	status_b == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
+    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
-_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
-				    const cairo_pattern_t    *pattern)
+_analyze_meta_surface_pattern (cairo_analysis_surface_t	*surface,
+			       const cairo_pattern_t *pattern)
 {
+    cairo_surface_t *analysis = &surface->base;
     const cairo_surface_pattern_t *surface_pattern;
+    cairo_status_t status;
     cairo_bool_t old_has_ctm;
     cairo_matrix_t old_ctm, p2d;
-    cairo_status_t status;
+    cairo_rectangle_int_t old_clip;
+    cairo_rectangle_int_t meta_extents;
+    int old_width;
+    int old_height;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
     surface_pattern = (const cairo_surface_pattern_t *) pattern;
-    assert (_cairo_surface_is_recording (surface_pattern->surface));
+    assert (_cairo_surface_is_meta (surface_pattern->surface));
 
+    old_width = surface->width;
+    old_height = surface->height;
+    old_clip = surface->current_clip;
+    status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    surface->width = meta_extents.width;
+    surface->height = meta_extents.height;
+    surface->current_clip.x = 0;
+    surface->current_clip.y = 0;
+    surface->current_clip.width = surface->width;
+    surface->current_clip.height = surface->height;
     old_ctm = surface->ctm;
     old_has_ctm = surface->has_ctm;
-
     p2d = pattern->matrix;
     status = cairo_matrix_invert (&p2d);
+    /* _cairo_pattern_set_matrix guarantees invertibility */
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
-    surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
 
-    status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
-							    &surface->base);
+    status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
+							    analysis);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = analysis->status;
 
     surface->ctm = old_ctm;
     surface->has_ctm = old_has_ctm;
+    surface->current_clip = old_clip;
+    surface->width = old_width;
+    surface->height = old_height;
 
     return status;
 }
 
 static cairo_int_status_t
-_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 */
@@ -144,43 +169,36 @@ static cairo_int_status_t
 	{
 	    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 	}
     }
 
     _cairo_box_from_rectangle (&bbox, rect);
 
     if (surface->has_ctm) {
-	int tx, ty;
 
-	if (_cairo_matrix_is_integer_translation (&surface->ctm, &tx, &ty)) {
-	    rect->x += tx;
-	    rect->y += ty;
-	} else {
-	    _cairo_matrix_transform_bounding_box_fixed (&surface->ctm,
-							&bbox, NULL);
+	_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
 
-	    if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
-		/* Even though the operation is not visible we must be
-		 * careful to not allow unsupported operations to be
-		 * replayed to the backend during
-		 * CAIRO_PAGINATED_MODE_RENDER */
-		if (backend_status == CAIRO_STATUS_SUCCESS ||
-		    backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
-		{
-		    return CAIRO_STATUS_SUCCESS;
-		}
-		else
-		{
-		    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
-		}
+	if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
+	    /* Even though the operation is not visible we must be
+	     * careful to not allow unsupported operations to be
+	     * replayed to the backend during
+	     * CAIRO_PAGINATED_MODE_RENDER */
+	    if (backend_status == CAIRO_STATUS_SUCCESS ||
+		backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
+	    {
+		return CAIRO_STATUS_SUCCESS;
 	    }
+	    else
+	    {
+		return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+	    }
+	}
 
-	    _cairo_box_round_to_rectangle (&bbox, rect);
-	}
+	_cairo_box_round_to_rectangle (&bbox, rect);
     }
 
     if (surface->first_op) {
 	surface->first_op = FALSE;
 	surface->page_bbox = bbox;
     } else {
 	if (bbox.p1.x < surface->page_bbox.p1.x)
 	    surface->page_bbox.p1.x = bbox.p1.x;
@@ -211,28 +229,29 @@ static cairo_int_status_t
 	    backend_status = CAIRO_STATUS_SUCCESS;
     }
 
     if (backend_status == CAIRO_STATUS_SUCCESS) {
 	/* Add the operation to the supported region. Operations in
 	 * this region will be emitted as native operations.
 	 */
 	surface->has_supported = TRUE;
-	return cairo_region_union_rectangle (&surface->supported_region, rect);
+	status = cairo_region_union_rectangle (&surface->supported_region, rect);
+	return status;
     }
 
     /* Add the operation to the unsupported region. This region will
      * be painted as an image after all native operations have been
      * emitted.
      */
     surface->has_unsupported = TRUE;
     status = cairo_region_union_rectangle (&surface->fallback_region, rect);
 
     /* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate
-     * unsupported operations to the recording surface as using
+     * unsupported operations to the meta surface as using
      * CAIRO_INT_STATUS_UNSUPPORTED would cause cairo-surface to
      * invoke the cairo-surface-fallback path then return
      * CAIRO_STATUS_SUCCESS.
      */
     if (status == CAIRO_STATUS_SUCCESS)
 	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
     else
 	return status;
@@ -246,342 +265,360 @@ static cairo_status_t
     _cairo_region_fini (&surface->supported_region);
     _cairo_region_fini (&surface->fallback_region);
 
     cairo_surface_destroy (surface->target);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_bool_t
+static cairo_int_status_t
+_cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
+					     cairo_path_fixed_t *path,
+					     cairo_fill_rule_t   fill_rule,
+					     double		 tolerance,
+					     cairo_antialias_t   antialias)
+{
+    cairo_analysis_surface_t *surface = abstract_surface;
+
+    if (path == NULL) {
+	surface->current_clip.x = 0;
+	surface->current_clip.y = 0;
+	surface->current_clip.width  = surface->width;
+	surface->current_clip.height = surface->height;
+    } else {
+	cairo_rectangle_int_t extents;
+	cairo_bool_t is_empty;
+
+	_cairo_path_fixed_approximate_clip_extents (path, &extents);
+	is_empty = _cairo_rectangle_intersect (&surface->current_clip,
+					       &extents);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
 _cairo_analysis_surface_get_extents (void			*abstract_surface,
 				     cairo_rectangle_int_t	*rectangle)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
 
     return _cairo_surface_get_extents (surface->target, rectangle);
 }
 
-static void
-_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
-{
-    const cairo_rectangle_int_t *clip_extents;
-    cairo_bool_t is_empty;
-
-    clip_extents = NULL;
-    if (clip != NULL)
-	clip_extents = _cairo_clip_get_extents (clip);
-
-    if (clip_extents != NULL)
-	is_empty = _cairo_rectangle_intersect (extents, clip_extents);
-}
-
-static void
-_cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface,
-					   cairo_operator_t op,
-					   const cairo_pattern_t *source,
-					   cairo_clip_t *clip,
-					   cairo_rectangle_int_t *extents)
-{
-    cairo_bool_t is_empty;
-
-    is_empty = _cairo_surface_get_extents (&surface->base, extents);
-
-    if (_cairo_operator_bounded_by_source (op)) {
-	cairo_rectangle_int_t source_extents;
-
-	_cairo_pattern_get_extents (source, &source_extents);
-	is_empty = _cairo_rectangle_intersect (extents, &source_extents);
-    }
-
-    _rectangle_intersect_clip (extents, clip);
-}
-
 static cairo_int_status_t
 _cairo_analysis_surface_paint (void			*abstract_surface,
 			       cairo_operator_t		op,
 			       const cairo_pattern_t	*source,
-			       cairo_clip_t		*clip)
+			       cairo_rectangle_int_t    *paint_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     backend_status;
+    cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t  extents;
+    cairo_bool_t is_empty;
 
-    if (surface->target->backend->paint == NULL) {
+    if (!surface->target->backend->paint)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    } else {
-	backend_status =
-	    surface->target->backend->paint (surface->target,
-					     op, source, clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
+    else
+	backend_status = (*surface->target->backend->paint) (surface->target, op,
+                                                             source, NULL);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _analyze_meta_surface_pattern (surface, source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	backend_status = _analyze_recording_surface_pattern (surface, source);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (paint_extents)
+	*paint_extents = extents;
 
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    status = _add_operation (surface, &extents, backend_status);
 
-    return _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_analysis_surface_mask (void		*abstract_surface,
+			      cairo_operator_t	 op,
 			      const cairo_pattern_t	*source,
 			      const cairo_pattern_t	*mask,
-			      cairo_clip_t		*clip)
+			      cairo_rectangle_int_t 	*mask_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_int_status_t	      backend_status;
+    cairo_int_status_t	      status, backend_status;
     cairo_rectangle_int_t   extents;
     cairo_bool_t is_empty;
 
-    if (surface->target->backend->mask == NULL) {
+    if (!surface->target->backend->mask)
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    } else {
-	backend_status =
-	    surface->target->backend->mask (surface->target,
-					    op, source, mask, clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
-    }
+    else
+	backend_status = (*surface->target->backend->mask) (surface->target, op,
+                                                            source, mask, NULL);
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) {
+    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) {
 	    const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source;
-	    if (_cairo_surface_is_recording (surface_pattern->surface)) {
+	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
 		backend_source_status =
-		    _analyze_recording_surface_pattern (surface, source);
+		    _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_recording (surface_pattern->surface)) {
+	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
 		backend_mask_status =
-		    _analyze_recording_surface_pattern (surface, mask);
+		    _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);
     }
 
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+    }
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	_cairo_pattern_get_extents (mask, &mask_extents);
+	status = _cairo_pattern_get_extents (mask, &mask_extents);
+	if (unlikely (status))
+	    return status;
+
 	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
-
     }
 
-    return _add_operation (surface, &extents, backend_status);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    if (mask_extents)
+	*mask_extents = extents;
+
+    status = _add_operation (surface, &extents, backend_status);
+
+    return status;
 }
 
 static cairo_int_status_t
 _cairo_analysis_surface_stroke (void			*abstract_surface,
 				cairo_operator_t	 op,
 				const cairo_pattern_t	*source,
 				cairo_path_fixed_t	*path,
 				cairo_stroke_style_t	*style,
 				cairo_matrix_t		*ctm,
 				cairo_matrix_t		*ctm_inverse,
 				double			 tolerance,
 				cairo_antialias_t	 antialias,
-				cairo_clip_t		*clip)
+				cairo_rectangle_int_t   *stroke_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     backend_status;
+    cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents;
     cairo_bool_t             is_empty;
 
-    if (surface->target->backend->stroke == NULL) {
+    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,
-					      clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
+    else
+	backend_status = (*surface->target->backend->stroke) (surface->target, op,
+							      source, path, style,
+							      ctm, ctm_inverse,
+							      tolerance, antialias, NULL);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _analyze_meta_surface_pattern (surface, source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	backend_status = _analyze_recording_surface_pattern (surface, source);
-
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	/* If the backend can handle the stroke, then mark the approximate
-	 * extents of the operation. However, if we need to fallback in order
-	 * to draw the stroke, then ensure that the fallback is as tight as
-	 * possible -- both to minimise output file size and to ensure good
-	 * quality printed output for neighbouring regions.
-	 */
-	if (backend_status == CAIRO_STATUS_SUCCESS) {
-	    _cairo_path_fixed_approximate_stroke_extents (path,
-							  style, ctm,
-							  &mask_extents);
-	} else {
-	    cairo_status_t status;
-
-	    status = _cairo_path_fixed_stroke_extents (path, style,
-						       ctm, ctm_inverse,
-						       tolerance,
-						       &mask_extents);
-	    if (unlikely (status))
-		return status;
-	}
+	_cairo_path_fixed_approximate_stroke_extents (path,
+						      style, ctm,
+						      &mask_extents);
 
 	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
+    if (stroke_extents)
+	*stroke_extents = extents;
 
-    return _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,
 			      const cairo_pattern_t	*source,
 			      cairo_path_fixed_t	*path,
 			      cairo_fill_rule_t		 fill_rule,
 			      double			 tolerance,
 			      cairo_antialias_t		 antialias,
-			      cairo_clip_t		*clip)
+			      cairo_rectangle_int_t     *fill_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     backend_status;
+    cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents;
     cairo_bool_t             is_empty;
 
-    if (surface->target->backend->fill == NULL) {
+    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,
-					    clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
+    else
+	backend_status = (*surface->target->backend->fill) (surface->target, op,
+						    source, path, fill_rule,
+							    tolerance, antialias, NULL);
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _analyze_meta_surface_pattern (surface, source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	backend_status = _analyze_recording_surface_pattern (surface, source);
-
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	/* We want speed for the likely case where the operation can be
-	 * performed natively, but accuracy if we have to resort to
-	 * using images.
-	 */
-	if (backend_status == CAIRO_STATUS_SUCCESS) {
-	    _cairo_path_fixed_approximate_fill_extents (path, &mask_extents);
-	} else {
-	     _cairo_path_fixed_fill_extents (path, fill_rule, tolerance,
-					     &mask_extents);
-	}
+	_cairo_path_fixed_approximate_fill_extents (path,
+						    &mask_extents);
+
 	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
+    if (fill_extents)
+	*fill_extents = extents;
 
-    return _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,
 				     const cairo_pattern_t *source,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
 				     cairo_scaled_font_t  *scaled_font,
-				     cairo_clip_t         *clip,
-				     int                  *remaining_glyphs)
+				     int                  *remaining_glyphs,
+				     cairo_rectangle_int_t *show_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
     cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
-    if (surface->target->backend->show_glyphs != NULL) {
-	backend_status =
-	    surface->target->backend->show_glyphs (surface->target, op,
-						   source,
-						   glyphs, num_glyphs,
-						   scaled_font,
-						   clip,
-						   remaining_glyphs);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
-    }
-    else if (surface->target->backend->show_text_glyphs != NULL)
-    {
-	backend_status =
-	    surface->target->backend->show_text_glyphs (surface->target, op,
-							source,
-							NULL, 0,
-							glyphs, num_glyphs,
-							NULL, 0,
-							FALSE,
-							scaled_font,
-							clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
-    }
+    if (surface->target->backend->show_glyphs)
+	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
+								   source,
+								   glyphs, num_glyphs,
+								   scaled_font,
+								   remaining_glyphs, NULL);
+    else if (surface->target->backend->show_text_glyphs)
+	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
+								     source,
+								     NULL, 0,
+								     glyphs, num_glyphs,
+								     NULL, 0,
+								     FALSE,
+								     scaled_font, NULL);
     else
-    {
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _analyze_meta_surface_pattern (surface, source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	backend_status = _analyze_recording_surface_pattern (surface, source);
-
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
 							  glyphs,
 							  num_glyphs,
-							  &glyph_extents,
-							  NULL);
+							  &glyph_extents);
 	if (unlikely (status))
 	    return status;
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_glyphs_extents)
+	*show_glyphs_extents = extents;
 
-    return _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;
 
     return cairo_surface_has_show_text_glyphs (surface->target);
@@ -594,78 +631,80 @@ static cairo_int_status_t
 					  const char		    *utf8,
 					  int			     utf8_len,
 					  cairo_glyph_t		    *glyphs,
 					  int			     num_glyphs,
 					  const cairo_text_cluster_t *clusters,
 					  int			     num_clusters,
 					  cairo_text_cluster_flags_t cluster_flags,
 					  cairo_scaled_font_t	    *scaled_font,
-					  cairo_clip_t		    *clip)
+					  cairo_rectangle_int_t     *show_text_glyphs_extents)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
     cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
     backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    if (surface->target->backend->show_text_glyphs != NULL) {
-	backend_status =
-	    surface->target->backend->show_text_glyphs (surface->target, op,
-							source,
-							utf8, utf8_len,
-							glyphs, num_glyphs,
-							clusters, num_clusters,
-							cluster_flags,
-							scaled_font,
-							clip);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
-    }
-    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED &&
-	surface->target->backend->show_glyphs != NULL)
-    {
+    if (surface->target->backend->show_text_glyphs)
+	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
+								     source,
+								     utf8, utf8_len,
+								     glyphs, num_glyphs,
+								     clusters, num_clusters, cluster_flags,
+								     scaled_font, NULL);
+    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
 	int remaining_glyphs = num_glyphs;
-	backend_status =
-	    surface->target->backend->show_glyphs (surface->target, op,
-						   source,
-						   glyphs, num_glyphs,
-						   scaled_font,
-						   clip,
-						   &remaining_glyphs);
-	if (_cairo_status_is_error (backend_status))
-	    return backend_status;
-
+	backend_status = surface->target->backend->show_glyphs (surface->target, op,
+								source,
+								glyphs, num_glyphs,
+								scaled_font,
+								&remaining_glyphs, NULL);
 	glyphs += num_glyphs - remaining_glyphs;
 	num_glyphs = remaining_glyphs;
 	if (remaining_glyphs == 0)
 	    backend_status = CAIRO_STATUS_SUCCESS;
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
-	backend_status = _analyze_recording_surface_pattern (surface, source);
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	backend_status = _analyze_meta_surface_pattern (surface, source);
+
+    status = _cairo_surface_get_extents (&surface->base, &extents);
+    if (_cairo_status_is_error (status))
+	return status;
 
-    _cairo_analysis_surface_operation_extents (surface,
-					       op, source, clip,
-					       &extents);
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	status = _cairo_pattern_get_extents (source, &source_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+    }
+
+    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
 							  glyphs,
 							  num_glyphs,
-							  &glyph_extents,
-							  NULL);
+							  &glyph_extents);
 	if (unlikely (status))
 	    return status;
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
+    if (show_text_glyphs_extents)
+	*show_text_glyphs_extents = extents;
 
-    return _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,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
@@ -674,39 +713,44 @@ static const cairo_surface_backend_t cai
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
     NULL, /* create_span_renderer */
     NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
+    NULL, /* set_clip_region */
+    _cairo_analysis_surface_intersect_clip_path,
     _cairo_analysis_surface_get_extents,
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
     _cairo_analysis_surface_paint,
     _cairo_analysis_surface_mask,
     _cairo_analysis_surface_stroke,
     _cairo_analysis_surface_fill,
     _cairo_analysis_surface_show_glyphs,
     NULL, /* snapshot */
     NULL, /* is_similar */
+    NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
     NULL, /* can_repaint_solid_pattern_surface */
     _cairo_analysis_surface_has_show_text_glyphs,
     _cairo_analysis_surface_show_text_glyphs
 };
 
 cairo_surface_t *
-_cairo_analysis_surface_create (cairo_surface_t		*target)
+_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 (unlikely (status))
 	return _cairo_surface_create_in_error (status);
 
@@ -714,48 +758,62 @@ cairo_surface_t *
     if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     /* I believe the content type here is truly arbitrary. I'm quite
      * sure nothing will ever use this value. */
     _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
+    surface->width = width;
+    surface->height = height;
     cairo_matrix_init_identity (&surface->ctm);
     surface->has_ctm = FALSE;
 
     surface->target = cairo_surface_reference (target);
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
     surface->has_unsupported = FALSE;
 
     _cairo_region_init (&surface->supported_region);
     _cairo_region_init (&surface->fallback_region);
 
     surface->page_bbox.p1.x = 0;
     surface->page_bbox.p1.y = 0;
     surface->page_bbox.p2.x = 0;
     surface->page_bbox.p2.y = 0;
 
+    if (width == -1 && height == -1) {
+	surface->current_clip.x      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.y      = CAIRO_RECT_INT_MIN;
+	surface->current_clip.width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+	surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
+    } else {
+	surface->current_clip.x = 0;
+	surface->current_clip.y = 0;
+	surface->current_clip.width = width;
+	surface->current_clip.height = height;
+    }
+
     return &surface->base;
 }
 
 void
 _cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
-				 const cairo_matrix_t  *ctm)
+				 cairo_matrix_t  *ctm)
 {
     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);
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
 }
 
 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;
 
@@ -809,59 +867,63 @@ void
 static cairo_int_status_t
 _return_success (void)
 {
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* These typedefs are just to silence the compiler... */
 typedef cairo_int_status_t
+(*_set_clip_region_func)	(void			*surface,
+				 cairo_region_t		*region);
+
+typedef cairo_int_status_t
 (*_paint_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
-				 cairo_clip_t		*clip);
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_mask_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
 				 const cairo_pattern_t	*mask,
-				 cairo_clip_t		*clip);
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_stroke_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_stroke_style_t	*style,
 				 cairo_matrix_t		*ctm,
 				 cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
 				 cairo_antialias_t	 antialias,
-				 cairo_clip_t		*clip);
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_fill_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
 				 cairo_path_fixed_t	*path,
 				 cairo_fill_rule_t	 fill_rule,
 				 double			 tolerance,
 				 cairo_antialias_t	 antialias,
-				 cairo_clip_t		*clip);
+				 cairo_rectangle_int_t  *extents);
 
 typedef cairo_int_status_t
 (*_show_glyphs_func)		(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
 				 cairo_scaled_font_t	*scaled_font,
-				 cairo_clip_t		*clip,
-				 int			*remaining_glyphs);
+				 int			*remaining_glyphs,
+				 cairo_rectangle_int_t  *extents);
 
 static const cairo_surface_backend_t cairo_null_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_NULL,
 
     NULL, /* create_similar */
     NULL, /* finish */
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
@@ -870,30 +932,33 @@ static const cairo_surface_backend_t cai
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
     NULL, /* create_span_renderer */
     NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
+    (_set_clip_region_func) _return_success, /* set_clip_region */
+    NULL, /* intersect_clip_path */
     NULL, /* get_extents */
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
     (_paint_func) _return_success,	    /* paint */
     (_mask_func) _return_success,	    /* mask */
     (_stroke_func) _return_success,	    /* stroke */
     (_fill_func) _return_success,	    /* fill */
     (_show_glyphs_func) _return_success,    /* show_glyphs */
     NULL, /* snapshot */
     NULL, /* is_similar */
+    NULL, /* reset */
     NULL, /* fill_stroke */
     NULL, /* create_solid_pattern_surface */
     NULL, /* can_repaint_solid_pattern_surface */
     NULL, /* has_show_text_glyphs */
     NULL  /* show_text_glyphs */
 };
 
 cairo_surface_t *
--- a/gfx/cairo/cairo/src/cairo-arc.c
+++ b/gfx/cairo/cairo/src/cairo-arc.c
@@ -111,17 +111,17 @@ static int
     double major_axis, max_angle;
 
     /* the error is amplified by at most the length of the
      * major axis of the circle; see cairo-pen.c for a more detailed analysis
      * of this. */
     major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius);
     max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis);
 
-    return ceil (fabs (angle) / max_angle);
+    return (int) ceil (angle / max_angle);
 }
 
 /* We want to draw a single spline approximating a circular arc radius
    R from angle A to angle B. Since we want a symmetric spline that
    matches the endpoints of the arc in position and slope, we know
    that the spline control points must be:
 
 	(R * cos(A), R * sin(A))
--- a/gfx/cairo/cairo/src/cairo-atomic-private.h
+++ b/gfx/cairo/cairo/src/cairo-atomic-private.h
@@ -38,33 +38,24 @@
 #define CAIRO_ATOMIC_PRIVATE_H
 
 # include "cairo-compiler-private.h"
 
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-/* The autoconf on OpenBSD 4.5 produces the malformed constant name
- * SIZEOF_VOID__ rather than SIZEOF_VOID_P.  Work around that here. */
-#if !defined(SIZEOF_VOID_P) && defined(SIZEOF_VOID__)
-# define SIZEOF_VOID_P SIZEOF_VOID__
-#endif
-
 CAIRO_BEGIN_DECLS
 
 #if HAVE_INTEL_ATOMIC_PRIMITIVES
 
 #define HAS_ATOMIC_OPS 1
 
 typedef int cairo_atomic_int_t;
 
-# define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
-
 # 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)
 
 #if SIZEOF_VOID_P==SIZEOF_INT
 typedef int cairo_atomic_intptr_t;
 #elif SIZEOF_VOID_P==SIZEOF_LONG
 typedef long cairo_atomic_intptr_t;
@@ -74,45 +65,16 @@ typedef long long cairo_atomic_intptr_t;
 #error No matching integer pointer type
 #endif
 
 # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
     (void*)__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
 
 #endif
 
-#if HAVE_LIB_ATOMIC_OPS
-#include <atomic_ops.h>
-
-#define HAS_ATOMIC_OPS 1
-
-typedef  AO_t cairo_atomic_int_t;
-
-# define _cairo_atomic_int_get(x) (AO_load_full (x))
-# define _cairo_atomic_int_set(x, value) (AO_store_full (x))
-
-# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
-# define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
-# define _cairo_atomic_int_cmpxchg(x, oldv, newv) ((cairo_atomic_int_t) AO_compare_and_swap_full(x, oldv, newv) ? oldv : *x)
-
-#if SIZEOF_VOID_P==SIZEOF_INT
-typedef unsigned int cairo_atomic_intptr_t;
-#elif SIZEOF_VOID_P==SIZEOF_LONG
-typedef unsigned long cairo_atomic_intptr_t;
-#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
-typedef unsigned long long cairo_atomic_intptr_t;
-#else
-#error No matching integer pointer type
-#endif
-
-# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
-    (void*) (cairo_atomic_intptr_t) _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
-
-#endif
-
 
 #ifndef HAS_ATOMIC_OPS
 
 typedef int cairo_atomic_int_t;
 
 cairo_private void
 _cairo_atomic_int_inc (int *x);
 
@@ -120,16 +82,19 @@ 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);
 
 cairo_private void *
 _cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
 
+#endif
+
+
 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
 
 # include "cairo-compiler-private.h"
 
 cairo_private int
 _cairo_atomic_int_get (int *x);
 
 cairo_private void
@@ -137,24 +102,22 @@ cairo_private void
 
 #else
 
 # define _cairo_atomic_int_get(x) (*x)
 # define _cairo_atomic_int_set(x, value) ((*x) = value)
 
 #endif
 
-#endif
-
 #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
 #define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \
-    _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv)
+    _cairo_atomic_int_cmpxchg((int *)x, oldv, newv)
 
 #define _cairo_status_set_error(status, err) do { \
     /* hide compiler warnings about cairo_status_t != int (gcc treats its as \
      * an unsigned integer instead, and about ignoring the return value. */  \
-    int ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
+    int ret__ = _cairo_atomic_int_cmpxchg ((int *) status, CAIRO_STATUS_SUCCESS, err); \
     (void) ret__; \
 } while (0)
 
 CAIRO_END_DECLS
 
 #endif
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-base64-stream.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005-2007 Emmanuel Pacaud <emmanuel.pacaud@free.fr>
- * Copyright © 2009 Chris Wilson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Author(s):
- *	Kristian Høgsberg <krh@redhat.com>
- *	Chris Wilson <chris@chris-wilson.co.uk>
- */
-
-#include "cairoint.h"
-#include "cairo-output-stream-private.h"
-
-typedef struct _cairo_base64_stream {
-    cairo_output_stream_t base;
-    cairo_output_stream_t *output;
-    unsigned int in_mem;
-    unsigned int trailing;
-    unsigned char src[3];
-} cairo_base64_stream_t;
-
-static char const base64_table[64] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static cairo_status_t
-_cairo_base64_stream_write (cairo_output_stream_t *base,
-			    const unsigned char	  *data,
-			    unsigned int	   length)
-{
-    cairo_base64_stream_t * stream = (cairo_base64_stream_t *) base;
-    unsigned char *src = stream->src;
-    unsigned int i;
-
-    if (stream->in_mem + length < 3) {
-	for (i = 0; i < length; i++) {
-	    src[i + stream->in_mem] = *data++;
-	}
-	stream->in_mem += length;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    do {
-	unsigned char dst[4];
-
-	for (i = stream->in_mem; i < 3; i++) {
-	    src[i] = *data++;
-	    length--;
-	}
-	stream->in_mem = 0;
-
-	dst[0] = base64_table[src[0] >> 2];
-	dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
-	dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6];
-	dst[3] = base64_table[src[2] & 0xfc >> 2];
-	/* Special case for the last missing bits */
-	switch (stream->trailing) {
-	    case 2:
-		dst[2] = '=';
-	    case 1:
-		dst[3] = '=';
-	    default:
-		break;
-	}
-	_cairo_output_stream_write (stream->output, dst, 4);
-    } while (length >= 3);
-
-    for (i = 0; i < length; i++) {
-	src[i] = *data++;
-    }
-    stream->in_mem = length;
-
-    return _cairo_output_stream_get_status (stream->output);
-}
-
-static cairo_status_t
-_cairo_base64_stream_close (cairo_output_stream_t *base)
-{
-    cairo_base64_stream_t *stream = (cairo_base64_stream_t *) base;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    if (stream->in_mem > 0) {
-	memset (stream->src + stream->in_mem, 0, 3 - stream->in_mem);
-	stream->trailing = 3 - stream->in_mem;
-	stream->in_mem = 3;
-	status = _cairo_base64_stream_write (base, NULL, 0);
-    }
-
-    return status;
-}
-
-cairo_output_stream_t *
-_cairo_base64_stream_create (cairo_output_stream_t *output)
-{
-    cairo_base64_stream_t *stream;
-
-    if (output->status)
-	return _cairo_output_stream_create_in_error (output->status);
-
-    stream = malloc (sizeof (cairo_base64_stream_t));
-    if (unlikely (stream == NULL)) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
-    }
-
-    _cairo_output_stream_init (&stream->base,
-			       _cairo_base64_stream_write,
-			       NULL,
-			       _cairo_base64_stream_close);
-
-    stream->output = output;
-    stream->in_mem = 0;
-    stream->trailing = 0;
-
-    return &stream->base;
-}
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -97,16 +97,19 @@ static cairo_status_t
     unsigned char five_tuple[5];
 
     if (stream->pending) {
 	memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
 	_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
 	_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
     }
 
+    /* Mark end of base85 data */
+    _cairo_output_stream_printf (stream->output, "~>");
+
     return _cairo_output_stream_get_status (stream->output);
 }
 
 cairo_output_stream_t *
 _cairo_base85_stream_create (cairo_output_stream_t *output)
 {
     cairo_base85_stream_t *stream;
 
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectangular.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * Copyright © 2004 Carl Worth
- * Copyright © 2006 Red Hat, Inc.
- * Copyright © 2009 Chris Wilson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Carl Worth
- *
- * Contributor(s):
- *	Carl D. Worth <cworth@cworth.org>
- *	Chris Wilson <chris@chris-wilson.co.uk>
- */
-
-/* Provide definitions for standalone compilation */
-#include "cairoint.h"
-
-#include "cairo-combsort-private.h"
-#include "cairo-list-private.h"
-
-typedef struct _cairo_bo_rectangle cairo_bo_rectangle_t;
-typedef struct _cairo_bo_edge cairo_bo_edge_t;
-
-/* A deferred trapezoid of an edge */
-typedef struct _cairo_bo_trap {
-    cairo_bo_edge_t *right;
-    int32_t top;
-} cairo_bo_trap_t;
-
-struct _cairo_bo_edge {
-    int x;
-    int dir;
-    cairo_bo_trap_t deferred_trap;
-    cairo_list_t link;
-};
-
-struct _cairo_bo_rectangle {
-    cairo_bo_edge_t left, right;
-    int top, bottom;
-};
-
-/* the parent is always given by index/2 */
-#define PQ_PARENT_INDEX(i) ((i) >> 1)
-#define PQ_FIRST_ENTRY 1
-
-/* left and right children are index * 2 and (index * 2) +1 respectively */
-#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
-
-typedef struct _pqueue {
-    int size, max_size;
-
-    cairo_bo_rectangle_t **elements;
-    cairo_bo_rectangle_t *elements_embedded[1024];
-} pqueue_t;
-
-typedef struct _cairo_bo_sweep_line {
-    cairo_bo_rectangle_t **rectangles;
-    pqueue_t stop;
-    cairo_list_t sweep;
-    cairo_list_t *current_left, *current_right;
-    int32_t current_y;
-    int32_t last_y;
-} cairo_bo_sweep_line_t;
-
-#define DEBUG_TRAPS 0
-
-#if DEBUG_TRAPS
-static void
-dump_traps (cairo_traps_t *traps, const char *filename)
-{
-    FILE *file;
-    int n;
-
-    if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
-	return;
-
-    file = fopen (filename, "a");
-    if (file != NULL) {
-	for (n = 0; n < traps->num_traps; n++) {
-	    fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
-		     traps->traps[n].top,
-		     traps->traps[n].bottom,
-		     traps->traps[n].left.p1.x,
-		     traps->traps[n].left.p1.y,
-		     traps->traps[n].left.p2.x,
-		     traps->traps[n].left.p2.y,
-		     traps->traps[n].right.p1.x,
-		     traps->traps[n].right.p1.y,
-		     traps->traps[n].right.p2.x,
-		     traps->traps[n].right.p2.y);
-	}
-	fprintf (file, "\n");
-	fclose (file);
-    }
-}
-#else
-#define dump_traps(traps, filename)
-#endif
-
-static inline int
-cairo_bo_rectangle_compare_start (const cairo_bo_rectangle_t *a,
-				  const cairo_bo_rectangle_t *b)
-{
-    return a->top - b->top;
-}
-
-static inline int
-_cairo_bo_rectangle_compare_stop (const cairo_bo_rectangle_t *a,
-				  const cairo_bo_rectangle_t *b)
-{
-    return a->bottom - b->bottom;
-}
-
-static inline void
-_pqueue_init (pqueue_t *pq)
-{
-    pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
-    pq->size = 0;
-
-    pq->elements = pq->elements_embedded;
-    pq->elements[PQ_FIRST_ENTRY] = NULL;
-}
-
-static inline void
-_pqueue_fini (pqueue_t *pq)
-{
-    if (pq->elements != pq->elements_embedded)
-	free (pq->elements);
-}
-
-static cairo_status_t
-_pqueue_grow (pqueue_t *pq)
-{
-    cairo_bo_rectangle_t **new_elements;
-    pq->max_size *= 2;
-
-    if (pq->elements == pq->elements_embedded) {
-	new_elements = _cairo_malloc_ab (pq->max_size,
-					 sizeof (cairo_bo_rectangle_t *));
-	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	memcpy (new_elements, pq->elements_embedded,
-		sizeof (pq->elements_embedded));
-    } else {
-	new_elements = _cairo_realloc_ab (pq->elements,
-					  pq->max_size,
-					  sizeof (cairo_bo_rectangle_t *));
-	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    pq->elements = new_elements;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_pqueue_push (pqueue_t *pq, cairo_bo_rectangle_t *rectangle)
-{
-    cairo_bo_rectangle_t **elements;
-    int i, parent;
-
-    if (unlikely (pq->size + 1 == pq->max_size)) {
-	cairo_status_t status;
-
-	status = _pqueue_grow (pq);
-	if (unlikely (status))
-	    return status;
-    }
-
-    elements = pq->elements;
-
-    for (i = ++pq->size;
-	 i != PQ_FIRST_ENTRY &&
-	 _cairo_bo_rectangle_compare_stop (rectangle,
-					   elements[parent = PQ_PARENT_INDEX (i)]) < 0;
-	 i = parent)
-    {
-	elements[i] = elements[parent];
-    }
-
-    elements[i] = rectangle;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline void
-_pqueue_pop (pqueue_t *pq)
-{
-    cairo_bo_rectangle_t **elements = pq->elements;
-    cairo_bo_rectangle_t *tail;
-    int child, i;
-
-    tail = elements[pq->size--];
-    if (pq->size == 0) {
-	elements[PQ_FIRST_ENTRY] = NULL;
-	return;
-    }
-
-    for (i = PQ_FIRST_ENTRY;
-	 (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
-	 i = child)
-    {
-	if (child != pq->size &&
-	    _cairo_bo_rectangle_compare_stop (elements[child+1],
-					      elements[child]) < 0)
-	{
-	    child++;
-	}
-
-	if (_cairo_bo_rectangle_compare_stop (elements[child], tail) >= 0)
-	    break;
-
-	elements[i] = elements[child];
-    }
-    elements[i] = tail;
-}
-
-static inline cairo_bo_rectangle_t *
-_cairo_bo_rectangle_pop_start (cairo_bo_sweep_line_t *sweep_line)
-{
-    return *sweep_line->rectangles++;
-}
-
-static inline cairo_bo_rectangle_t *
-_cairo_bo_rectangle_peek_stop (cairo_bo_sweep_line_t *sweep_line)
-{
-    return sweep_line->stop.elements[PQ_FIRST_ENTRY];
-}
-
-CAIRO_COMBSORT_DECLARE (_cairo_bo_rectangle_sort,
-			cairo_bo_rectangle_t *,
-			cairo_bo_rectangle_compare_start)
-
-static void
-_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line,
-			   cairo_bo_rectangle_t	**rectangles,
-			   int			  num_rectangles)
-{
-    _cairo_bo_rectangle_sort (rectangles, num_rectangles);
-    rectangles[num_rectangles] = NULL;
-    sweep_line->rectangles = rectangles;
-
-    cairo_list_init (&sweep_line->sweep);
-    sweep_line->current_left = &sweep_line->sweep;
-    sweep_line->current_right = &sweep_line->sweep;
-    sweep_line->current_y = INT32_MIN;
-    sweep_line->last_y = INT32_MIN;
-
-    _pqueue_init (&sweep_line->stop);
-}
-
-static void
-_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
-{
-    _pqueue_fini (&sweep_line->stop);
-}
-
-static inline cairo_bo_edge_t *
-link_to_edge (cairo_list_t *elt)
-{
-    return cairo_container_of (elt, cairo_bo_edge_t, link);
-}
-
-static cairo_status_t
-_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
-			 int32_t		 bot,
-			 cairo_traps_t	        *traps)
-{
-    cairo_bo_trap_t *trap = &left->deferred_trap;
-
-    /* Only emit (trivial) non-degenerate trapezoids with positive height. */
-    if (likely (trap->top < bot)) {
-	cairo_line_t _left = {
-	    { left->x, trap->top },
-	    { left->x, bot },
-	}, _right = {
-	    { trap->right->x, trap->top },
-	    { trap->right->x, bot },
-	};
-	_cairo_traps_add_trap (traps, trap->top, bot, &_left, &_right);
-    }
-
-    trap->right = NULL;
-
-    return _cairo_traps_status (traps);
-}
-
-/* Start a new trapezoid at the given top y coordinate, whose edges
- * are `edge' and `edge->next'. If `edge' already has a trapezoid,
- * then either add it to the traps in `traps', if the trapezoid's
- * right edge differs from `edge->next', or do nothing if the new
- * trapezoid would be a continuation of the existing one. */
-static inline cairo_status_t
-_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	    *left,
-				       cairo_bo_edge_t	    *right,
-				       int		     top,
-				       cairo_traps_t	    *traps)
-{
-    cairo_status_t status;
-
-    if (left->deferred_trap.right == right)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (left->deferred_trap.right != NULL) {
-	if (right != NULL && left->deferred_trap.right->x == right->x) {
-	    /* continuation on right, so just swap edges */
-	    left->deferred_trap.right = right;
-	    return CAIRO_STATUS_SUCCESS;
-	}
-
-	status = _cairo_bo_edge_end_trap (left, top, traps);
-	if (unlikely (status))
-	    return status;
-    }
-
-    if (right != NULL && left->x != right->x) {
-	left->deferred_trap.top = top;
-	left->deferred_trap.right = right;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_active_edges_to_traps (cairo_bo_sweep_line_t	*sweep,
-			cairo_fill_rule_t	 fill_rule,
-			cairo_traps_t	        *traps)
-{
-    int top = sweep->current_y;
-    cairo_list_t *pos = &sweep->sweep;
-    cairo_status_t status;
-
-    if (sweep->last_y == sweep->current_y)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-	do {
-	    cairo_bo_edge_t *left, *right;
-	    int in_out;
-
-	    pos = pos->next;
-	    if (pos == &sweep->sweep)
-		break;
-
-	    left = link_to_edge (pos);
-	    in_out = left->dir;
-
-	    /* Check if there is a co-linear edge with an existing trap */
-	    if (left->deferred_trap.right == NULL) {
-		right = link_to_edge (pos->next);
-		while (unlikely (right->x == left->x)) {
-		    if (right->deferred_trap.right != NULL) {
-			/* continuation on left */
-			left->deferred_trap = right->deferred_trap;
-			right->deferred_trap.right = NULL;
-			break;
-		    }
-
-		    if (right->link.next == &sweep->sweep)
-			break;
-		    right = link_to_edge (right->link.next);
-		}
-	    }
-
-	    /* Greedily search for the closing edge, so that we generate the
-	     * maximal span width with the minimal number of trapezoids.
-	     */
-
-	    right = link_to_edge (left->link.next);
-	    do {
-		/* End all subsumed traps */
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		in_out += right->dir;
-		if (in_out == 0) {
-		    /* skip co-linear edges */
-		    if (likely (right->link.next == &sweep->sweep ||
-				right->x != link_to_edge (right->link.next)->x))
-		    {
-			break;
-		    }
-		}
-
-		right = link_to_edge (right->link.next);
-	    } while (TRUE);
-
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-
-	    pos = &right->link;
-	} while (TRUE);
-    } else {
-	cairo_bo_edge_t *left, *right;
-	do {
-	    int in_out = 0;
-
-	    pos = pos->next;
-	    if (pos == &sweep->sweep)
-		break;
-
-	    left = link_to_edge (pos);
-
-	    pos = pos->next;
-	    do {
-		right = link_to_edge (pos);
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		if ((in_out++ & 1) == 0) {
-		    cairo_list_t *next;
-		    cairo_bool_t skip = FALSE;
-
-		    /* skip co-linear edges */
-		    next = pos->next;
-		    if (next != &sweep->sweep)
-			skip = right->x == link_to_edge (next)->x;
-
-		    if (! skip)
-			break;
-		}
-		pos = pos->next;
-	    } while (TRUE);
-
-	    right = pos == &sweep->sweep ? NULL : link_to_edge (pos);
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-	} while (right != NULL);
-    }
-
-    sweep->last_y = sweep->current_y;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_cairo_bo_sweep_line_delete_edge (cairo_bo_sweep_line_t *sweep_line,
-	                          cairo_bo_edge_t *edge,
-				  cairo_traps_t *traps)
-{
-    if (edge->deferred_trap.right != NULL) {
-	cairo_bo_edge_t *next = link_to_edge (edge->link.next);
-	if (&next->link != &sweep_line->sweep && next->x == edge->x) {
-	    next->deferred_trap = edge->deferred_trap;
-	} else {
-	    cairo_status_t status;
-
-	    status = _cairo_bo_edge_end_trap (edge,
-		                              sweep_line->current_y,
-					      traps);
-	    if (unlikely (status))
-		return status;
-	}
-    }
-
-    if (sweep_line->current_left == &edge->link)
-	sweep_line->current_left = edge->link.prev;
-
-    if (sweep_line->current_right == &edge->link)
-	sweep_line->current_right = edge->link.next;
-
-    cairo_list_del (&edge->link);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
-			     cairo_bo_rectangle_t	*rectangle,
-			     cairo_fill_rule_t		 fill_rule,
-			     cairo_traps_t		*traps)
-{
-    cairo_status_t status;
-
-    if (rectangle->bottom != sweep_line->current_y) {
-	status = _active_edges_to_traps (sweep_line, fill_rule, traps);
-	if (unlikely (status))
-	    return status;
-
-	sweep_line->current_y = rectangle->bottom;
-    }
-
-    status = _cairo_bo_sweep_line_delete_edge (sweep_line,
-	                                       &rectangle->left,
-					       traps);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_bo_sweep_line_delete_edge (sweep_line,
-	                                       &rectangle->right,
-					       traps);
-    if (unlikely (status))
-	return status;
-
-    _pqueue_pop (&sweep_line->stop);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-validate_sweep_line (cairo_bo_sweep_line_t *sweep_line)
-{
-    int32_t last_x = INT32_MIN;
-    cairo_bo_edge_t *edge;
-    cairo_list_foreach_entry (edge, cairo_bo_edge_t, &sweep_line->sweep, link) {
-	if (edge->x < last_x)
-	    return FALSE;
-	last_x = edge->x;
-    }
-    return TRUE;
-}
-static inline cairo_status_t
-_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
-			     cairo_bo_rectangle_t	*rectangle,
-			     cairo_fill_rule_t		 fill_rule,
-			     cairo_traps_t		*traps)
-{
-    cairo_list_t *pos;
-    cairo_status_t status;
-
-    if (rectangle->top != sweep_line->current_y) {
-	cairo_bo_rectangle_t *stop;
-
-	stop = _cairo_bo_rectangle_peek_stop (sweep_line);
-	while (stop != NULL && stop->bottom < rectangle->top) {
-	    status = _cairo_bo_sweep_line_delete (sweep_line, stop,
-						  fill_rule, traps);
-	    if (unlikely (status))
-		return status;
-
-	    stop = _cairo_bo_rectangle_peek_stop (sweep_line);
-	}
-
-	status = _active_edges_to_traps (sweep_line, fill_rule, traps);
-	if (unlikely (status))
-	    return status;
-
-	sweep_line->current_y = rectangle->top;
-    }
-
-    /* right edge */
-    pos = sweep_line->current_right;
-    if (pos == &sweep_line->sweep)
-	pos = sweep_line->sweep.prev;
-    if (pos != &sweep_line->sweep) {
-	int cmp;
-
-	cmp = link_to_edge (pos)->x - rectangle->right.x;
-	if (cmp < 0) {
-	    while (pos->next != &sweep_line->sweep &&
-		   link_to_edge (pos->next)->x - rectangle->right.x < 0)
-	    {
-		pos = pos->next;
-	    }
-	} else if (cmp > 0) {
-	    do {
-		pos = pos->prev;
-	    } while (pos != &sweep_line->sweep &&
-		     link_to_edge (pos)->x - rectangle->right.x > 0);
-	}
-
-	cairo_list_add (&rectangle->right.link, pos);
-    } else {
-	cairo_list_add_tail (&rectangle->right.link, pos);
-    }
-    sweep_line->current_right = &rectangle->right.link;
-    assert (validate_sweep_line (sweep_line));
-
-    /* left edge */
-    pos = sweep_line->current_left;
-    if (pos == &sweep_line->sweep)
-	pos = sweep_line->sweep.next;
-    if (pos != &sweep_line->sweep) {
-	int cmp;
-
-	if (link_to_edge (pos)->x >= rectangle->right.x) {
-	    pos = rectangle->right.link.prev;
-	    if (pos == &sweep_line->sweep)
-		goto left_done;
-	}
-
-	cmp = link_to_edge (pos)->x - rectangle->left.x;
-	if (cmp < 0) {
-	    while (pos->next != &sweep_line->sweep &&
-		   link_to_edge (pos->next)->x - rectangle->left.x < 0)
-	    {
-		pos = pos->next;
-	    }
-	} else if (cmp > 0) {
-	    do {
-		pos = pos->prev;
-	    } while (pos != &sweep_line->sweep &&
-		    link_to_edge (pos)->x - rectangle->left.x > 0);
-	}
-    }
-  left_done:
-    cairo_list_add (&rectangle->left.link, pos);
-    sweep_line->current_left = &rectangle->left.link;
-    assert (validate_sweep_line (sweep_line));
-
-    return _pqueue_push (&sweep_line->stop, rectangle);
-}
-
-static cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectangular (cairo_bo_rectangle_t	**rectangles,
-					       int			  num_rectangles,
-					       cairo_fill_rule_t	  fill_rule,
-					       cairo_traps_t		 *traps)
-{
-    cairo_bo_sweep_line_t sweep_line;
-    cairo_bo_rectangle_t *rectangle;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    _cairo_bo_sweep_line_init (&sweep_line, rectangles, num_rectangles);
-
-    while ((rectangle = _cairo_bo_rectangle_pop_start (&sweep_line)) != NULL) {
-	status = _cairo_bo_sweep_line_insert (&sweep_line, rectangle,
-					      fill_rule, traps);
-	if (unlikely (status))
-	    goto BAIL;
-    }
-
-    while ((rectangle = _cairo_bo_rectangle_peek_stop (&sweep_line)) != NULL) {
-	status = _cairo_bo_sweep_line_delete (&sweep_line, rectangle,
-					      fill_rule, traps);
-	if (unlikely (status))
-	    goto BAIL;
-    }
-
-BAIL:
-    _cairo_bo_sweep_line_fini (&sweep_line);
-    return status;
-}
-
-cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps,
-						     cairo_fill_rule_t fill_rule)
-{
-    cairo_bo_rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_rectangle_t)];
-    cairo_bo_rectangle_t *rectangles;
-    cairo_bo_rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
-    cairo_bo_rectangle_t **rectangles_ptrs;
-    cairo_status_t status;
-    int i;
-
-    if (unlikely (traps->num_traps == 0))
-	return CAIRO_STATUS_SUCCESS;
-
-    assert (traps->is_rectangular);
-
-    dump_traps (traps, "bo-rects-traps-in.txt");
-
-    rectangles = stack_rectangles;
-    rectangles_ptrs = stack_rectangles_ptrs;
-    if (traps->num_traps > ARRAY_LENGTH (stack_rectangles)) {
-	rectangles = _cairo_malloc_ab_plus_c (traps->num_traps,
-					  sizeof (cairo_bo_rectangle_t) +
-					  sizeof (cairo_bo_rectangle_t *),
-					  sizeof (cairo_bo_rectangle_t *));
-	if (unlikely (rectangles == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	rectangles_ptrs = (cairo_bo_rectangle_t **) (rectangles + traps->num_traps);
-    }
-
-    for (i = 0; i < traps->num_traps; i++) {
-	if (traps->traps[i].left.p1.x < traps->traps[i].right.p1.x) {
-	    rectangles[i].left.x = traps->traps[i].left.p1.x;
-	    rectangles[i].left.dir = 1;
-
-	    rectangles[i].right.x = traps->traps[i].right.p1.x;
-	    rectangles[i].right.dir = -1;
-	} else {
-	    rectangles[i].right.x = traps->traps[i].left.p1.x;
-	    rectangles[i].right.dir = 1;
-
-	    rectangles[i].left.x = traps->traps[i].right.p1.x;
-	    rectangles[i].left.dir = -1;
-	}
-
-	rectangles[i].left.deferred_trap.right = NULL;
-	cairo_list_init (&rectangles[i].left.link);
-
-	rectangles[i].right.deferred_trap.right = NULL;
-	cairo_list_init (&rectangles[i].right.link);
-
-	rectangles[i].top = traps->traps[i].top;
-	rectangles[i].bottom = traps->traps[i].bottom;
-
-	rectangles_ptrs[i] = &rectangles[i];
-    }
-
-    _cairo_traps_clear (traps);
-    status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs, i,
-							    fill_rule,
-							    traps);
-    traps->is_rectilinear = TRUE;
-    traps->is_rectangular = TRUE;
-
-    if (rectangles != stack_rectangles)
-	free (rectangles);
-
-    dump_traps (traps, "bo-rects-traps-out.txt");
-
-
-    return status;
-}
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectilinear.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Copyright © 2004 Carl Worth
- * Copyright © 2006 Red Hat, Inc.
- * Copyright © 2008 Chris Wilson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Carl Worth
- *
- * Contributor(s):
- *	Carl D. Worth <cworth@cworth.org>
- *	Chris Wilson <chris@chris-wilson.co.uk>
- */
-
-/* Provide definitions for standalone compilation */
-#include "cairoint.h"
-
-#include "cairo-combsort-private.h"
-
-typedef struct _cairo_bo_edge cairo_bo_edge_t;
-typedef struct _cairo_bo_trap cairo_bo_trap_t;
-
-/* A deferred trapezoid of an edge */
-struct _cairo_bo_trap {
-    cairo_bo_edge_t *right;
-    int32_t top;
-};
-
-struct _cairo_bo_edge {
-    cairo_edge_t edge;
-    cairo_bo_edge_t *prev;
-    cairo_bo_edge_t *next;
-    cairo_bo_trap_t deferred_trap;
-};
-
-typedef enum {
-    CAIRO_BO_EVENT_TYPE_START,
-    CAIRO_BO_EVENT_TYPE_STOP
-} cairo_bo_event_type_t;
-
-typedef struct _cairo_bo_event {
-    cairo_bo_event_type_t type;
-    cairo_point_t point;
-    cairo_bo_edge_t *edge;
-} cairo_bo_event_t;
-
-typedef struct _cairo_bo_sweep_line {
-    cairo_bo_event_t **events;
-    cairo_bo_edge_t *head;
-    cairo_bo_edge_t *stopped;
-    int32_t current_y;
-    cairo_bo_edge_t *current_edge;
-} cairo_bo_sweep_line_t;
-
-static inline int
-_cairo_point_compare (const cairo_point_t *a,
-		      const cairo_point_t *b)
-{
-    int cmp;
-
-    cmp = a->y - b->y;
-    if (likely (cmp))
-	return cmp;
-
-    return a->x - b->x;
-}
-
-static inline int
-_cairo_bo_edge_compare (const cairo_bo_edge_t	*a,
-			const cairo_bo_edge_t	*b)
-{
-    int cmp;
-
-    cmp = a->edge.line.p1.x - b->edge.line.p1.x;
-    if (likely (cmp))
-	return cmp;
-
-    return b->edge.bottom - a->edge.bottom;
-}
-
-static inline int
-cairo_bo_event_compare (const cairo_bo_event_t *a,
-			const cairo_bo_event_t *b)
-{
-    int cmp;
-
-    cmp = _cairo_point_compare (&a->point, &b->point);
-    if (likely (cmp))
-	return cmp;
-
-    cmp = a->type - b->type;
-    if (cmp)
-	return cmp;
-
-    return a - b;
-}
-
-static inline cairo_bo_event_t *
-_cairo_bo_event_dequeue (cairo_bo_sweep_line_t *sweep_line)
-{
-    return *sweep_line->events++;
-}
-
-CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
-			cairo_bo_event_t *,
-			cairo_bo_event_compare)
-
-static void
-_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line,
-			   cairo_bo_event_t	**events,
-			   int			  num_events)
-{
-    _cairo_bo_event_queue_sort (events, num_events);
-    events[num_events] = NULL;
-    sweep_line->events = events;
-
-    sweep_line->head = NULL;
-    sweep_line->current_y = INT32_MIN;
-    sweep_line->current_edge = NULL;
-}
-
-static void
-_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
-			     cairo_bo_edge_t		*edge)
-{
-    if (sweep_line->current_edge != NULL) {
-	cairo_bo_edge_t *prev, *next;
-	int cmp;
-
-	cmp = _cairo_bo_edge_compare (sweep_line->current_edge, edge);
-	if (cmp < 0) {
-	    prev = sweep_line->current_edge;
-	    next = prev->next;
-	    while (next != NULL && _cairo_bo_edge_compare (next, edge) < 0)
-		prev = next, next = prev->next;
-
-	    prev->next = edge;
-	    edge->prev = prev;
-	    edge->next = next;
-	    if (next != NULL)
-		next->prev = edge;
-	} else if (cmp > 0) {
-	    next = sweep_line->current_edge;
-	    prev = next->prev;
-	    while (prev != NULL && _cairo_bo_edge_compare (prev, edge) > 0)
-		next = prev, prev = next->prev;
-
-	    next->prev = edge;
-	    edge->next = next;
-	    edge->prev = prev;
-	    if (prev != NULL)
-		prev->next = edge;
-	    else
-		sweep_line->head = edge;
-	} else {
-	    prev = sweep_line->current_edge;
-	    edge->prev = prev;
-	    edge->next = prev->next;
-	    if (prev->next != NULL)
-		prev->next->prev = edge;
-	    prev->next = edge;
-	}
-    } else {
-	sweep_line->head = edge;
-    }
-
-    sweep_line->current_edge = edge;
-}
-
-static void
-_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
-			     cairo_bo_edge_t	*edge)
-{
-    if (edge->prev != NULL)
-	edge->prev->next = edge->next;
-    else
-	sweep_line->head = edge->next;
-
-    if (edge->next != NULL)
-	edge->next->prev = edge->prev;
-
-    if (sweep_line->current_edge == edge)
-	sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
-}
-
-static inline cairo_bool_t
-edges_collinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
-{
-    return a->edge.line.p1.x == b->edge.line.p1.x;
-}
-
-static cairo_status_t
-_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
-			 int32_t		 bot,
-			 cairo_traps_t	        *traps)
-{
-    cairo_bo_trap_t *trap = &left->deferred_trap;
-
-    /* Only emit (trivial) non-degenerate trapezoids with positive height. */
-    if (likely (trap->top < bot)) {
-	_cairo_traps_add_trap (traps,
-			       trap->top, bot,
-			       &left->edge.line, &trap->right->edge.line);
-    }
-
-    trap->right = NULL;
-
-    return _cairo_traps_status (traps);
-}
-
-/* Start a new trapezoid at the given top y coordinate, whose edges
- * are `edge' and `edge->next'. If `edge' already has a trapezoid,
- * then either add it to the traps in `traps', if the trapezoid's
- * right edge differs from `edge->next', or do nothing if the new
- * trapezoid would be a continuation of the existing one. */
-static inline cairo_status_t
-_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	*left,
-				       cairo_bo_edge_t  *right,
-				       int               top,
-				       cairo_traps_t	*traps)
-{
-    cairo_status_t status;
-
-    if (left->deferred_trap.right == right)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (left->deferred_trap.right != NULL) {
-	if (right != NULL && edges_collinear (left->deferred_trap.right, right))
-	{
-	    /* continuation on right, so just swap edges */
-	    left->deferred_trap.right = right;
-	    return CAIRO_STATUS_SUCCESS;
-	}
-
-	status = _cairo_bo_edge_end_trap (left, top, traps);
-	if (unlikely (status))
-	    return status;
-    }
-
-    if (right != NULL && ! edges_collinear (left, right)) {
-	left->deferred_trap.top = top;
-	left->deferred_trap.right = right;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_active_edges_to_traps (cairo_bo_edge_t		*left,
-			int32_t			 top,
-			cairo_fill_rule_t	 fill_rule,
-			cairo_traps_t	        *traps)
-{
-    cairo_bo_edge_t *right;
-    cairo_status_t status;
-
-    if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-	while (left != NULL) {
-	    int in_out;
-
-	    /* Greedily search for the closing edge, so that we generate the
-	     * maximal span width with the minimal number of trapezoids.
-	     */
-	    in_out = left->edge.dir;
-
-	    /* Check if there is a co-linear edge with an existing trap */
-	    right = left->next;
-	    if (left->deferred_trap.right == NULL) {
-		while (right != NULL && right->deferred_trap.right == NULL)
-		    right = right->next;
-
-		if (right != NULL && edges_collinear (left, right)) {
-		    /* continuation on left */
-		    left->deferred_trap = right->deferred_trap;
-		    right->deferred_trap.right = NULL;
-		}
-	    }
-
-	    /* End all subsumed traps */
-	    right = left->next;
-	    while (right != NULL) {
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		in_out += right->edge.dir;
-		if (in_out == 0) {
-		    /* skip co-linear edges */
-		    if (right->next == NULL ||
-			! edges_collinear (right, right->next))
-		    {
-			break;
-		    }
-		}
-
-		right = right->next;
-	    }
-
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-
-	    left = right;
-	    if (left != NULL)
-		left = left->next;
-	}
-    } else {
-	while (left != NULL) {
-	    int in_out = 0;
-
-	    right = left->next;
-	    while (right != NULL) {
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		if ((in_out++ & 1) == 0) {
-		    cairo_bo_edge_t *next;
-		    cairo_bool_t skip = FALSE;
-
-		    /* skip co-linear edges */
-		    next = right->next;
-		    if (next != NULL)
-			skip = edges_collinear (right, next);
-
-		    if (! skip)
-			break;
-		}
-
-		right = right->next;
-	    }
-
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-
-	    left = right;
-	    if (left != NULL)
-		left = left->next;
-	}
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t   **start_events,
-					       int			 num_events,
-					       cairo_fill_rule_t	 fill_rule,
-					       cairo_traps_t	*traps)
-{
-    cairo_bo_sweep_line_t sweep_line;
-    cairo_bo_event_t *event;
-    cairo_status_t status;
-
-    _cairo_bo_sweep_line_init (&sweep_line, start_events, num_events);
-
-    while ((event = _cairo_bo_event_dequeue (&sweep_line))) {
-	if (event->point.y != sweep_line.current_y) {
-	    status = _active_edges_to_traps (sweep_line.head,
-					     sweep_line.current_y,
-					     fill_rule, traps);
-	    if (unlikely (status))
-		return status;
-
-	    sweep_line.current_y = event->point.y;
-	}
-
-	switch (event->type) {
-	case CAIRO_BO_EVENT_TYPE_START:
-	    _cairo_bo_sweep_line_insert (&sweep_line, event->edge);
-	    break;
-
-	case CAIRO_BO_EVENT_TYPE_STOP:
-	    _cairo_bo_sweep_line_delete (&sweep_line, event->edge);
-
-	    if (event->edge->deferred_trap.right != NULL) {
-		status = _cairo_bo_edge_end_trap (event->edge,
-						  sweep_line.current_y,
-						  traps);
-		if (unlikely (status))
-		    return status;
-	    }
-
-	    break;
-	}
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t	 *traps,
-						       const cairo_polygon_t *polygon,
-						       cairo_fill_rule_t	  fill_rule)
-{
-    cairo_status_t status;
-    cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
-    cairo_bo_event_t *events;
-    cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
-    cairo_bo_event_t **event_ptrs;
-    cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
-    cairo_bo_edge_t *edges;
-    int num_events;
-    int i, j;
-
-    if (unlikely (polygon->num_edges == 0))
-	return CAIRO_STATUS_SUCCESS;
-
-    num_events = 2 * polygon->num_edges;
-
-    events = stack_events;
-    event_ptrs = stack_event_ptrs;
-    edges = stack_edges;
-    if (num_events > ARRAY_LENGTH (stack_events)) {
-	events = _cairo_malloc_ab_plus_c (num_events,
-					  sizeof (cairo_bo_event_t) +
-					  sizeof (cairo_bo_edge_t) +
-					  sizeof (cairo_bo_event_t *),
-					  sizeof (cairo_bo_event_t *));
-	if (unlikely (events == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	event_ptrs = (cairo_bo_event_t **) (events + num_events);
-	edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1);
-    }
-
-    for (i = j = 0; i < polygon->num_edges; i++) {
-	edges[i].edge = polygon->edges[i];
-	edges[i].deferred_trap.right = NULL;
-	edges[i].prev = NULL;
-	edges[i].next = NULL;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_START;
-	events[j].point.y = polygon->edges[i].top;
-	events[j].point.x = polygon->edges[i].line.p1.x;
-	events[j].edge = &edges[i];
-	j++;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
-	events[j].point.y = polygon->edges[i].bottom;
-	events[j].point.x = polygon->edges[i].line.p1.x;
-	events[j].edge = &edges[i];
-	j++;
-    }
-
-    status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
-							    fill_rule, traps);
-    if (events != stack_events)
-	free (events);
-
-    traps->is_rectilinear = TRUE;
-
-    return status;
-}
-
-cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps,
-						     cairo_fill_rule_t fill_rule)
-{
-    cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
-    cairo_bo_event_t *events;
-    cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
-    cairo_bo_event_t **event_ptrs;
-    cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
-    cairo_bo_edge_t *edges;
-    cairo_status_t status;
-    int i, j, k;
-
-    if (unlikely (traps->num_traps == 0))
-	return CAIRO_STATUS_SUCCESS;
-
-    assert (traps->is_rectilinear);
-
-    i = 4 * traps->num_traps;
-
-    events = stack_events;
-    event_ptrs = stack_event_ptrs;
-    edges = stack_edges;
-    if (i > ARRAY_LENGTH (stack_events)) {
-	events = _cairo_malloc_ab_plus_c (i,
-					  sizeof (cairo_bo_event_t) +
-					  sizeof (cairo_bo_edge_t) +
-					  sizeof (cairo_bo_event_t *),
-					  sizeof (cairo_bo_event_t *));
-	if (unlikely (events == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	event_ptrs = (cairo_bo_event_t **) (events + i);
-	edges = (cairo_bo_edge_t *) (event_ptrs + i + 1);
-    }
-
-    for (i = j = k = 0; i < traps->num_traps; i++) {
-	edges[k].edge.top = traps->traps[i].top;
-	edges[k].edge.bottom = traps->traps[i].bottom;
-	edges[k].edge.line = traps->traps[i].left;
-	edges[k].edge.dir = 1;
-	edges[k].deferred_trap.right = NULL;
-	edges[k].prev = NULL;
-	edges[k].next = NULL;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_START;
-	events[j].point.y = traps->traps[i].top;
-	events[j].point.x = traps->traps[i].left.p1.x;
-	events[j].edge = &edges[k];
-	j++;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
-	events[j].point.y = traps->traps[i].bottom;
-	events[j].point.x = traps->traps[i].left.p1.x;
-	events[j].edge = &edges[k];
-	j++;
-	k++;
-
-	edges[k].edge.top = traps->traps[i].top;
-	edges[k].edge.bottom = traps->traps[i].bottom;
-	edges[k].edge.line = traps->traps[i].right;
-	edges[k].edge.dir = -1;
-	edges[k].deferred_trap.right = NULL;
-	edges[k].prev = NULL;
-	edges[k].next = NULL;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_START;
-	events[j].point.y = traps->traps[i].top;
-	events[j].point.x = traps->traps[i].right.p1.x;
-	events[j].edge = &edges[k];
-	j++;
-
-	event_ptrs[j] = &events[j];
-	events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
-	events[j].point.y = traps->traps[i].bottom;
-	events[j].point.x = traps->traps[i].right.p1.x;
-	events[j].edge = &edges[k];
-	j++;
-	k++;
-    }
-
-    _cairo_traps_clear (traps);
-    status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
-							    fill_rule,
-							    traps);
-    traps->is_rectilinear = TRUE;
-
-    if (events != stack_events)
-	free (events);
-
-    return status;
-}
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -1,12 +1,11 @@
 /*
  * Copyright © 2004 Carl Worth
  * Copyright © 2006 Red Hat, Inc.
- * Copyright © 2008 Chris Wilson
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -27,224 +26,145 @@
  * the specific language governing rights and limitations.
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Carl Worth
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
- *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 /* Provide definitions for standalone compilation */
 #include "cairoint.h"
 
+#include "cairo-skiplist-private.h"
 #include "cairo-freelist-private.h"
 #include "cairo-combsort-private.h"
 
+#define DEBUG_VALIDATE 0
 #define DEBUG_PRINT_STATE 0
-#define DEBUG_EVENTS 0
-#define DEBUG_TRAPS 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 {
     int32_t ordinate;
     enum { EXACT, INEXACT } exactness;
 } cairo_bo_intersect_ordinate_t;
 
 typedef struct _cairo_bo_intersect_point {
     cairo_bo_intersect_ordinate_t x;
     cairo_bo_intersect_ordinate_t y;
 } cairo_bo_intersect_point_t;
 
 typedef struct _cairo_bo_edge cairo_bo_edge_t;
+typedef struct _sweep_line_elt sweep_line_elt_t;
 typedef struct _cairo_bo_trap cairo_bo_trap_t;
+typedef struct _cairo_bo_traps cairo_bo_traps_t;
 
-/* A deferred trapezoid of an edge */
+/* A deferred trapezoid of an edge. */
 struct _cairo_bo_trap {
     cairo_bo_edge_t *right;
     int32_t top;
 };
 
-struct _cairo_bo_edge {
-    cairo_edge_t edge;
-    cairo_bo_edge_t *prev;
-    cairo_bo_edge_t *next;
-    cairo_bo_trap_t deferred_trap;
+struct _cairo_bo_traps {
+    cairo_traps_t *traps;
+    cairo_freelist_t freelist;
+
+    /* These form the closed bounding box of the original input
+     * points. */
+    cairo_fixed_t xmin;
+    cairo_fixed_t ymin;
+    cairo_fixed_t xmax;
+    cairo_fixed_t ymax;
 };
 
-/* the parent is always given by index/2 */
-#define PQ_PARENT_INDEX(i) ((i) >> 1)
-#define PQ_FIRST_ENTRY 1
+struct _cairo_bo_edge {
+    cairo_bo_point32_t top;
+    cairo_bo_point32_t middle;
+    cairo_bo_point32_t bottom;
+    int dir;
+    cairo_bo_edge_t *prev;
+    cairo_bo_edge_t *next;
+    cairo_bo_trap_t *deferred_trap;
+    sweep_line_elt_t *sweep_line_elt;
+};
 
-/* left and right children are index * 2 and (index * 2) +1 respectively */
-#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
+struct _sweep_line_elt {
+    cairo_bo_edge_t *edge;
+    skip_elt_t elt;
+};
+
+#define SKIP_ELT_TO_EDGE_ELT(elt)	SKIP_LIST_ELT_TO_DATA (sweep_line_elt_t, (elt))
+#define SKIP_ELT_TO_EDGE(elt) 		(SKIP_ELT_TO_EDGE_ELT (elt)->edge)
 
 typedef enum {
+    CAIRO_BO_STATUS_INTERSECTION,
+    CAIRO_BO_STATUS_PARALLEL,
+    CAIRO_BO_STATUS_NO_INTERSECTION
+} cairo_bo_status_t;
+
+typedef enum {
+    CAIRO_BO_EVENT_TYPE_START,
     CAIRO_BO_EVENT_TYPE_STOP,
-    CAIRO_BO_EVENT_TYPE_INTERSECTION,
-    CAIRO_BO_EVENT_TYPE_START
+    CAIRO_BO_EVENT_TYPE_INTERSECTION
 } cairo_bo_event_type_t;
 
 typedef struct _cairo_bo_event {
     cairo_bo_event_type_t type;
-    cairo_point_t point;
-} cairo_bo_event_t;
-
-typedef struct _cairo_bo_start_event {
-    cairo_bo_event_type_t type;
-    cairo_point_t point;
-    cairo_bo_edge_t edge;
-} cairo_bo_start_event_t;
-
-typedef struct _cairo_bo_queue_event {
-    cairo_bo_event_type_t type;
-    cairo_point_t point;
     cairo_bo_edge_t *e1;
     cairo_bo_edge_t *e2;
-} cairo_bo_queue_event_t;
+    cairo_bo_point32_t point;
+    skip_elt_t elt;
+} cairo_bo_event_t;
 
-typedef struct _pqueue {
-    int size, max_size;
-
-    cairo_bo_event_t **elements;
-    cairo_bo_event_t *elements_embedded[1024];
-} pqueue_t;
+#define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
 
 typedef struct _cairo_bo_event_queue {
-    cairo_freepool_t pool;
-    pqueue_t pqueue;
-    cairo_bo_event_t **start_events;
+    cairo_skip_list_t intersection_queue;
+
+    cairo_bo_event_t *startstop_events;
+    cairo_bo_event_t **sorted_startstop_event_ptrs;
 } cairo_bo_event_queue_t;
 
+/* This structure extends #cairo_skip_list_t, which must come first. */
 typedef struct _cairo_bo_sweep_line {
+    cairo_skip_list_t active_edges;
     cairo_bo_edge_t *head;
-    cairo_bo_edge_t *stopped;
+    cairo_bo_edge_t *tail;
     int32_t current_y;
-    cairo_bo_edge_t *current_edge;
 } cairo_bo_sweep_line_t;
 
-#if DEBUG_TRAPS
-static void
-dump_traps (cairo_traps_t *traps, const char *filename)
-{
-    FILE *file;
-    int n;
-
-    if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
-	return;
-
-    if (traps->has_limits) {
-	printf ("%s: limits=(%d, %d, %d, %d)\n",
-		filename,
-		traps->limits.p1.x, traps->limits.p1.y,
-		traps->limits.p2.x, traps->limits.p2.y);
-    }
-    printf ("%s: extents=(%d, %d, %d, %d)\n",
-	    filename,
-	    traps->extents.p1.x, traps->extents.p1.y,
-	    traps->extents.p2.x, traps->extents.p2.y);
-
-    file = fopen (filename, "a");
-    if (file != NULL) {
-	for (n = 0; n < traps->num_traps; n++) {
-	    fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
-		     traps->traps[n].top,
-		     traps->traps[n].bottom,
-		     traps->traps[n].left.p1.x,
-		     traps->traps[n].left.p1.y,
-		     traps->traps[n].left.p2.x,
-		     traps->traps[n].left.p2.y,
-		     traps->traps[n].right.p1.x,
-		     traps->traps[n].right.p1.y,
-		     traps->traps[n].right.p2.x,
-		     traps->traps[n].right.p2.y);
-	}
-	fprintf (file, "\n");
-	fclose (file);
-    }
-}
-
-static void
-dump_edges (cairo_bo_start_event_t *events,
-	    int num_edges,
-	    const char *filename)
-{
-    FILE *file;
-    int n;
-
-    if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
-	return;
-
-    file = fopen (filename, "a");
-    if (file != NULL) {
-	for (n = 0; n < num_edges; n++) {
-	    fprintf (file, "(%d, %d), (%d, %d) %d %d %d\n",
-		     events[n].edge.edge.line.p1.x,
-		     events[n].edge.edge.line.p1.y,
-		     events[n].edge.edge.line.p2.x,
-		     events[n].edge.edge.line.p2.y,
-		     events[n].edge.edge.top,
-		     events[n].edge.edge.bottom,
-		     events[n].edge.edge.dir);
-	}
-	fprintf (file, "\n");
-	fclose (file);
-    }
-}
-#endif
-
-static cairo_fixed_t
-_line_compute_intersection_x_for_y (const cairo_line_t *line,
-				    cairo_fixed_t y)
-{
-    cairo_fixed_t x, dy;
-
-    if (y == line->p1.y)
-	return line->p1.x;
-    if (y == line->p2.y)
-	return line->p2.x;
-
-    x = line->p1.x;
-    dy = line->p2.y - line->p1.y;
-    if (dy != 0) {
-	x += _cairo_fixed_mul_div_floor (y - line->p1.y,
-					 line->p2.x - line->p1.x,
-					 dy);
-    }
-
-    return x;
-}
 
 static inline int
 _cairo_bo_point32_compare (cairo_bo_point32_t const *a,
 			   cairo_bo_point32_t const *b)
 {
-    int cmp;
-
-    cmp = a->y - b->y;
-    if (cmp)
-	return cmp;
-
+    int cmp = a->y - b->y;
+    if (cmp) return cmp;
     return a->x - b->x;
 }
 
 /* Compare the slope of a to the slope of b, returning 1, 0, -1 if the
  * slope a is respectively greater than, equal to, or less than the
  * slope of b.
  *
  * For each edge, consider the direction vector formed from:
  *
  *	top -> bottom
  *
  * which is:
  *
- *	(dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.y)
+ *	(dx, dy) = (bottom.x - top.x, bottom.y - top.y)
  *
  * We then define the slope of each edge as dx/dy, (which is the
  * inverse of the slope typically used in math instruction). We never
  * compute a slope directly as the value approaches infinity, but we
  * can derive a slope comparison without division as follows, (where
  * the ? represents our compare operator).
  *
  * 1.	   slope(a) ? slope(b)
@@ -258,27 +178,27 @@ static inline int
  * When using this slope comparison to sort edges, some care is needed
  * when interpreting the results. Since the slope compare operates on
  * distance vectors from top to bottom it gives a correct left to
  * right sort for edges that have a common top point, (such as two
  * edges with start events at the same location). On the other hand,
  * the sense of the result will be exactly reversed for two edges that
  * have a common stop point.
  */
-static inline int
-_slope_compare (const cairo_bo_edge_t *a,
-		const cairo_bo_edge_t *b)
+static int
+_slope_compare (cairo_bo_edge_t *a,
+		cairo_bo_edge_t *b)
 {
     /* 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 adx = a->edge.line.p2.x - a->edge.line.p1.x;
-    int32_t bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+    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 several common cases.
      */
 
     /* First check for vertical lines. */
     if (adx == 0)
 	return -bdx;
@@ -286,18 +206,18 @@ static inline int
 	return adx;
 
     /* Then where the two edges point in different directions wrt x. */
     if ((adx ^ bdx) < 0)
 	return adx;
 
     /* Finally we actually need to do the general comparison. */
     {
-	int32_t ady = a->edge.line.p2.y - a->edge.line.p1.y;
-	int32_t bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+	int32_t ady = a->bottom.y - a->top.y;
+	int32_t bdy = b->bottom.y - b->top.y;
 	cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
 	cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
 
 	return _cairo_int64_cmp (adx_bdy, bdx_ady);
     }
 }
 
 /*
@@ -345,56 +265,33 @@ edges_compare_x_for_y_general (const cai
        HAVE_ADX     = 0x2,
        HAVE_DX_ADX  = HAVE_DX | HAVE_ADX,
        HAVE_BDX     = 0x4,
        HAVE_DX_BDX  = HAVE_DX | HAVE_BDX,
        HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
        HAVE_ALL     = HAVE_DX | HAVE_ADX | HAVE_BDX
     } have_dx_adx_bdx = HAVE_ALL;
 
-    /* don't bother solving for abscissa if the edges' bounding boxes
-     * can be used to order them. */
-    {
-           int32_t amin, amax;
-           int32_t bmin, bmax;
-           if (a->edge.line.p1.x < a->edge.line.p2.x) {
-                   amin = a->edge.line.p1.x;
-                   amax = a->edge.line.p2.x;
-           } else {
-                   amin = a->edge.line.p2.x;
-                   amax = a->edge.line.p1.x;
-           }
-           if (b->edge.line.p1.x < b->edge.line.p2.x) {
-                   bmin = b->edge.line.p1.x;
-                   bmax = b->edge.line.p2.x;
-           } else {
-                   bmin = b->edge.line.p2.x;
-                   bmax = b->edge.line.p1.x;
-           }
-           if (amax < bmin) return -1;
-           if (amin > bmax) return +1;
-    }
-
-    ady = a->edge.line.p2.y - a->edge.line.p1.y;
-    adx = a->edge.line.p2.x - a->edge.line.p1.x;
+    ady = a->bottom.y - a->top.y;
+    adx = a->bottom.x - a->top.x;
     if (adx == 0)
 	have_dx_adx_bdx &= ~HAVE_ADX;
 
-    bdy = b->edge.line.p2.y - b->edge.line.p1.y;
-    bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+    bdy = b->bottom.y - b->top.y;
+    bdx = b->bottom.x - b->top.x;
     if (bdx == 0)
 	have_dx_adx_bdx &= ~HAVE_BDX;
 
-    dx = a->edge.line.p1.x - b->edge.line.p1.x;
+    dx = a->top.x - b->top.x;
     if (dx == 0)
 	have_dx_adx_bdx &= ~HAVE_DX;
 
 #define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
-#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
-#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->top.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->top.y)
     switch (have_dx_adx_bdx) {
     default:
     case HAVE_NONE:
 	return 0;
     case HAVE_DX:
 	/* A_dy * B_dy * (A_x - B_x) ∘ 0 */
 	return dx; /* ady * bdy is positive definite */
     case HAVE_ADX:
@@ -402,17 +299,17 @@ edges_compare_x_for_y_general (const cai
 	return adx; /* bdy * (y - a->top.y) is positive definite */
     case HAVE_BDX:
 	/* 0 ∘ (Y - B_y) * B_dx * A_dy */
 	return -bdx; /* ady * (y - b->top.y) is positive definite */
     case HAVE_ADX_BDX:
 	/*  0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
 	if ((adx ^ bdx) < 0) {
 	    return adx;
-	} else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
+	} else if (a->top.y == b->top.y) { /* common origin */
 	    cairo_int64_t adx_bdy, bdx_ady;
 
 	    /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
 
 	    adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
 	    bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
 
 	    return _cairo_int64_cmp (adx_bdy, bdx_ady);
@@ -421,34 +318,33 @@ edges_compare_x_for_y_general (const cai
     case HAVE_DX_ADX:
 	/* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
 	if ((-adx ^ dx) < 0) {
 	    return dx;
 	} else {
 	    cairo_int64_t ady_dx, dy_adx;
 
 	    ady_dx = _cairo_int32x32_64_mul (ady, dx);
-	    dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
+	    dy_adx = _cairo_int32x32_64_mul (a->top.y - y, adx);
 
 	    return _cairo_int64_cmp (ady_dx, dy_adx);
 	}
     case HAVE_DX_BDX:
 	/* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
 	if ((bdx ^ dx) < 0) {
 	    return dx;
 	} else {
 	    cairo_int64_t bdy_dx, dy_bdx;
 
 	    bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
-	    dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
+	    dy_bdx = _cairo_int32x32_64_mul (y - b->top.y, bdx);
 
 	    return _cairo_int64_cmp (bdy_dx, dy_bdx);
 	}
     case HAVE_ALL:
-	/* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
 	return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
     }
 #undef B
 #undef A
 #undef L
 }
 
 /*
@@ -476,31 +372,26 @@ 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;
 
-    if (x < a->edge.line.p1.x && x < a->edge.line.p2.x)
-	return 1;
-    if (x > a->edge.line.p1.x && x > a->edge.line.p2.x)
-	return -1;
-
-    adx = a->edge.line.p2.x - a->edge.line.p1.x;
-    dx = x - a->edge.line.p1.x;
+    adx = a->bottom.x - a->top.x;
+    dx = x - a->top.x;
 
     if (adx == 0)
 	return -dx;
-    if (dx == 0 || (adx ^ dx) < 0)
+    if ((adx ^ dx) < 0)
 	return adx;
 
-    dy = y - a->edge.line.p1.y;
-    ady = a->edge.line.p2.y - a->edge.line.p1.y;
+    dy = y - a->top.y;
+    ady = a->bottom.y - a->top.y;
 
     L = _cairo_int32x32_64_mul (dy, adx);
     R = _cairo_int32x32_64_mul (dx, ady);
 
     return _cairo_int64_cmp (L, R);
 }
 
 static int
@@ -516,125 +407,311 @@ edges_compare_x_for_y (const cairo_bo_ed
     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->edge.line.p1.y)
-	ax = a->edge.line.p1.x;
-    else if (y == a->edge.line.p2.y)
-	ax = a->edge.line.p2.x;
+    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->edge.line.p1.y)
-	bx = b->edge.line.p1.x;
-    else if (y == b->edge.line.p2.y)
-	bx = b->edge.line.p2.x;
+    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;
     }
 }
 
-static inline int
-_line_equal (const cairo_line_t *a, const cairo_line_t *b)
+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)
 {
-    return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
-           a->p2.x == b->p2.x && a->p2.y == b->p2.y;
+    int cmp;
+
+    if (a == b)
+	return 0;
+
+    /* don't bother solving for abscissa if the edges' bounding boxes
+     * can be used to order them. */
+    {
+           int32_t amin, amax;
+           int32_t bmin, bmax;
+           if (a->middle.x < a->bottom.x) {
+                   amin = a->middle.x;
+                   amax = a->bottom.x;
+           } else {
+                   amin = a->bottom.x;
+                   amax = a->middle.x;
+           }
+           if (b->middle.x < b->bottom.x) {
+                   bmin = b->middle.x;
+                   bmax = b->bottom.x;
+           } else {
+                   bmin = b->bottom.x;
+                   bmax = b->middle.x;
+           }
+           if (amax < bmin) return -1;
+           if (amin > bmax) 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)
+	return cmp;
+
+    /* We've got two collinear edges now. */
+
+    /* Since we're dealing with start events, prefer comparing top
+     * edges before bottom edges. */
+    cmp = _cairo_bo_point32_compare (&a->top, &b->top);
+    if (cmp)
+	return cmp;
+
+    cmp = _cairo_bo_point32_compare (&a->bottom, &b->bottom);
+    if (cmp)
+	return cmp;
+
+    /* Finally, we've got two identical edges. Let's finally
+     * discriminate by a simple pointer comparison, (which works only
+     * because we "know" the edges are all in a single array and don't
+     * move. */
+    if (a > b)
+	return 1;
+    else
+	return -1;
 }
 
 static int
-_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t	*sweep_line,
-				    const cairo_bo_edge_t	*a,
-				    const cairo_bo_edge_t	*b)
+_sweep_line_elt_compare (void	*list,
+			 void	*a,
+			 void	*b)
+{
+    cairo_bo_sweep_line_t *sweep_line = list;
+    sweep_line_elt_t *edge_elt_a = a;
+    sweep_line_elt_t *edge_elt_b = b;
+
+    return _cairo_bo_sweep_line_compare_edges (sweep_line,
+					       edge_elt_a->edge,
+					       edge_elt_b->edge);
+}
+
+static inline int
+cairo_bo_event_compare (cairo_bo_event_t const *a,
+			cairo_bo_event_t const *b)
 {
     int cmp;
 
-    /* compare the edges if not identical */
-    if (! _line_equal (&a->edge.line, &b->edge.line)) {
-	cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
+    /* The major motion of the sweep line is vertical (top-to-bottom),
+     * and the minor motion is horizontal (left-to-right), dues to the
+     * infinitesimal tilt rule.
+     *
+     * Our point comparison function respects these rules.
+     */
+    cmp = _cairo_bo_point32_compare (&a->point, &b->point);
+    if (cmp)
+	return cmp;
+
+    /* The events share a common point, so further discrimination is
+     * determined by the event type. Due to the infinitesimal
+     * shortening rule, stop events come first, then intersection
+     * events, then start events.
+     */
+    if (a->type != b->type) {
+	if (a->type == CAIRO_BO_EVENT_TYPE_STOP)
+	    return -1;
+	if (a->type == CAIRO_BO_EVENT_TYPE_START)
+	    return 1;
+
+	if (b->type == CAIRO_BO_EVENT_TYPE_STOP)
+	    return 1;
+	if (b->type == CAIRO_BO_EVENT_TYPE_START)
+	    return -1;
+    }
+
+    /* At this stage we are looking at two events of the same type at
+     * the same point. The final sort key is a slope comparison. We
+     * need a different sense for start and stop events based on the
+     * shortening rule.
+     *
+     * Note: Fortunately, we get to ignore errors in the relative
+     * ordering of intersection events. This means we don't even have
+     * to look at e2 here, nor worry about which sense of the slope
+     * comparison test is used for intersection events.
+     */
+    cmp = _slope_compare (a->e1, b->e1);
+    if (cmp) {
+	if (a->type == CAIRO_BO_EVENT_TYPE_START)
+	    return cmp;
+	else
+	    return - cmp;
+    }
+
+    /* Next look at the opposite point. This leaves ambiguities only
+     * for identical edges. */
+    if (a->type == CAIRO_BO_EVENT_TYPE_START) {
+	cmp = _cairo_bo_point32_compare (&b->e1->bottom,
+					 &a->e1->bottom);
 	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);
+    }
+    else if (a->type == CAIRO_BO_EVENT_TYPE_STOP) {
+	cmp = _cairo_bo_point32_compare (&a->e1->top,
+					 &b->e1->top);
 	if (cmp)
 	    return cmp;
     }
+    else { /* CAIRO_BO_EVENT_TYPE_INTERSECT */
+	/* For two intersection events at the identical point, we
+	 * don't care what order they sort in, but we do care that we
+	 * have a stable sort. In particular intersections between
+	 * different pairs of edges must never return 0. */
+	cmp = _cairo_bo_point32_compare (&a->e2->top, &b->e2->top);
+	if (cmp)
+	    return cmp;
+	cmp = _cairo_bo_point32_compare (&a->e2->bottom, &b->e2->bottom);
+	if (cmp)
+	    return cmp;
+	cmp = _cairo_bo_point32_compare (&a->e1->top, &b->e1->top);
+	if (cmp)
+	    return cmp;
+	cmp = _cairo_bo_point32_compare (&a->e1->bottom, &b->e1->bottom);
+	if (cmp)
+	    return cmp;
+     }
 
-    /* We've got two collinear edges now. */
-    return b->edge.bottom - a->edge.bottom;
+    /* Discrimination based on the edge pointers. */
+    if (a->e1 < b->e1)
+	return -1;
+    if (a->e1 > b->e1)
+	return +1;
+    if (a->e2 < b->e2)
+	return -1;
+    if (a->e2 > b->e2)
+	return +1;
+    return 0;
+}
+
+static int
+cairo_bo_event_compare_abstract (void		*list,
+				 void	*a,
+				 void	*b)
+{
+    cairo_bo_event_t *event_a = a;
+    cairo_bo_event_t *event_b = b;
+
+    return cairo_bo_event_compare (event_a, event_b);
+}
+
+static int
+cairo_bo_event_compare_pointers (const cairo_bo_event_t *a,
+				 const cairo_bo_event_t *b)
+{
+    int cmp;
+
+    if (a == b)
+	return 0;
+    cmp = cairo_bo_event_compare (a, b);
+    if (cmp)
+	return cmp;
+
+    return a - b;
 }
 
 static inline cairo_int64_t
-det32_64 (int32_t a, int32_t b,
-	  int32_t c, int32_t d)
+det32_64 (int32_t a,
+	  int32_t b,
+	  int32_t c,
+	  int32_t d)
 {
+    cairo_int64_t ad;
+    cairo_int64_t bc;
+
     /* det = a * d - b * c */
-    return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
-			     _cairo_int32x32_64_mul (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
-det64x32_128 (cairo_int64_t a, int32_t       b,
-	      cairo_int64_t c, int32_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 */
-    return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
-			      _cairo_int64x32_128_mul (c, b));
+    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
  * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
  */
-static cairo_bool_t
+static cairo_bo_status_t
 intersect_lines (cairo_bo_edge_t		*a,
 		 cairo_bo_edge_t		*b,
 		 cairo_bo_intersect_point_t	*intersection)
 {
     cairo_int64_t a_det, b_det;
 
     /* 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.
      * What we're doing to mitigate this is to perform clamping in
      * cairo_bo_tessellate_polygon().
      */
-    int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
-    int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
+    int32_t dx1 = a->top.x - a->bottom.x;
+    int32_t dy1 = a->top.y - a->bottom.y;
 
-    int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x;
-    int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y;
+    int32_t dx2 = b->top.x - b->bottom.x;
+    int32_t dy2 = b->top.y - b->bottom.y;
 
     cairo_int64_t den_det;
     cairo_int64_t R;
     cairo_quorem64_t qr;
 
     den_det = det32_64 (dx1, dy1, dx2, dy2);
+    if (_cairo_int64_is_zero (den_det))
+	return CAIRO_BO_STATUS_PARALLEL;
 
      /* Q: Can we determine that the lines do not intersect (within range)
       * much more cheaply than computing the intersection point i.e. by
       * avoiding the division?
       *
       *   X = ax + t * adx = bx + s * bdx;
       *   Y = ay + t * ady = by + s * bdy;
       *   ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
@@ -645,92 +722,68 @@ intersect_lines (cairo_bo_edge_t		*a,
       *   L^R < 0 => t < 0, or
       *   L<R => t > 1
       *
       * (where top/bottom must at least extend to the line endpoints).
       *
       * A similar substitution can be performed for s, yielding:
       *   s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
       */
-    R = det32_64 (dx2, dy2,
-		  b->edge.line.p1.x - a->edge.line.p1.x,
-		  b->edge.line.p1.y - a->edge.line.p1.y);
+    R = det32_64 (dx2, dy2, b->top.x - a->top.x, b->top.y - a->top.y);
+    if (_cairo_int64_is_zero (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
     if (_cairo_int64_negative (den_det)) {
 	if (_cairo_int64_ge (den_det, R))
-	    return FALSE;
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
     } else {
 	if (_cairo_int64_le (den_det, R))
-	    return FALSE;
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
     }
 
-    R = det32_64 (dy1, dx1,
-		  a->edge.line.p1.y - b->edge.line.p1.y,
-		  a->edge.line.p1.x - b->edge.line.p1.x);
+    R = det32_64 (dy1, dx1, a->top.y - b->top.y, a->top.x - b->top.x);
+    if (_cairo_int64_is_zero (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
     if (_cairo_int64_negative (den_det)) {
 	if (_cairo_int64_ge (den_det, R))
-	    return FALSE;
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
     } else {
 	if (_cairo_int64_le (den_det, R))
-	    return FALSE;
+	    return CAIRO_BO_STATUS_NO_INTERSECTION;
     }
 
     /* We now know that the two lines should intersect within range. */
 
-    a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
-		      a->edge.line.p2.x, a->edge.line.p2.y);
-    b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
-		      b->edge.line.p2.x, b->edge.line.p2.y);
+    a_det = det32_64 (a->top.x, a->top.y,
+		      a->bottom.x, a->bottom.y);
+    b_det = det32_64 (b->top.x, b->top.y,
+		      b->bottom.x, b->bottom.y);
 
     /* x = det (a_det, dx1, b_det, dx2) / den_det */
     qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
 						       b_det, dx2),
 					 den_det);
     if (_cairo_int64_eq (qr.rem, den_det))
-	return FALSE;
-#if 0
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
+    intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
     intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
-#else
-    intersection->x.exactness = EXACT;
-    if (! _cairo_int64_is_zero (qr.rem)) {
-	if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
-	    qr.rem = _cairo_int64_negate (qr.rem);
-	qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
-	if (_cairo_int64_ge (qr.rem, den_det)) {
-	    qr.quo = _cairo_int64_add (qr.quo,
-				       _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
-	} else
-	    intersection->x.exactness = INEXACT;
-    }
-#endif
-    intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
 
     /* 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 FALSE;
-#if 0
+	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;
-#else
-    intersection->y.exactness = EXACT;
-    if (! _cairo_int64_is_zero (qr.rem)) {
-	if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
-	    qr.rem = _cairo_int64_negate (qr.rem);
-	qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
-	if (_cairo_int64_ge (qr.rem, den_det)) {
-	    qr.quo = _cairo_int64_add (qr.quo,
-				       _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
-	} else
-	    intersection->y.exactness = INEXACT;
-    }
-#endif
-    intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
 
-    return TRUE;
+    return CAIRO_BO_STATUS_INTERSECTION;
 }
 
 static int
 _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t	a,
 					 int32_t			b)
 {
     /* First compare the quotient */
     if (a.ordinate > b)
@@ -767,20 +820,18 @@ static cairo_bool_t
 
     /* XXX: When running the actual algorithm, we don't actually need to
      * compare against edge->top at all here, since any intersection above
      * top is eliminated early via a slope comparison. We're leaving these
      * here for now only for the sake of the quadratic-time intersection
      * finder which needs them.
      */
 
-    cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y,
-						       edge->edge.top);
-    cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y,
-							  edge->edge.bottom);
+    cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->top.y);
+    cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->bottom.y);
 
     if (cmp_top < 0 || cmp_bottom > 0)
     {
 	return FALSE;
     }
 
     if (cmp_top > 0 && cmp_bottom < 0)
     {
@@ -793,29 +844,20 @@ static cairo_bool_t
 
     /* If the y value of the point is the same as the y value of the
      * top of the edge, then the x value of the point must be greater
      * to be considered as inside the edge. Similarly, if the y value
      * of the point is the same as the y value of the bottom of the
      * edge, then the x value of the point must be less to be
      * considered as inside. */
 
-    if (cmp_top == 0) {
-	cairo_fixed_t top_x;
-
-	top_x = _line_compute_intersection_x_for_y (&edge->edge.line,
-						    edge->edge.top);
-	return _cairo_bo_intersect_ordinate_32_compare (point->x, top_x) > 0;
-    } else { /* cmp_bottom == 0 */
-	cairo_fixed_t bot_x;
-
-	bot_x = _line_compute_intersection_x_for_y (&edge->edge.line,
-						    edge->edge.bottom);
-	return _cairo_bo_intersect_ordinate_32_compare (point->x, bot_x) < 0;
-    }
+    if (cmp_top == 0)
+	return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->top.x) > 0);
+    else /* cmp_bottom == 0 */
+	return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->bottom.x) < 0);
 }
 
 /* Compute the intersection of two edges. The result is provided as a
  * coordinate pair of 128-bit integers.
  *
  * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection
  * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the
  * intersection of the lines defined by the edges occurs outside of
@@ -824,394 +866,317 @@ static cairo_bool_t
  *
  * Note that when determining if a candidate intersection is "inside"
  * an edge, we consider both the infinitesimal shortening and the
  * infinitesimal tilt rules described by John Hobby. Specifically, if
  * the intersection is exactly the same as an edge point, it is
  * effectively outside (no intersection is returned). Also, if the
  * intersection point has the same
  */
-static cairo_bool_t
+static cairo_bo_status_t
 _cairo_bo_edge_intersect (cairo_bo_edge_t	*a,
 			  cairo_bo_edge_t	*b,
 			  cairo_bo_point32_t	*intersection)
 {
+    cairo_bo_status_t status;
     cairo_bo_intersect_point_t quorem;
 
-    if (! intersect_lines (a, b, &quorem))
-	return FALSE;
+    status = intersect_lines (a, b, &quorem);
+    if (status)
+	return status;
 
     if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
-	return FALSE;
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
 
     if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
-	return FALSE;
+	return CAIRO_BO_STATUS_NO_INTERSECTION;
 
     /* Now that we've correctly compared the intersection point and
      * determined that it lies within the edge, then we know that we
      * no longer need any more bits of storage for the intersection
      * than we do for our edge coordinates. We also no longer need the
      * remainder from the division. */
     intersection->x = quorem.x.ordinate;
     intersection->y = quorem.y.ordinate;
 
-    return TRUE;
+    return CAIRO_BO_STATUS_INTERSECTION;
 }
 
-static inline int
-cairo_bo_event_compare (const cairo_bo_event_t *a,
-			const cairo_bo_event_t *b)
+static void
+_cairo_bo_event_init (cairo_bo_event_t		*event,
+		      cairo_bo_event_type_t	 type,
+		      cairo_bo_edge_t	*e1,
+		      cairo_bo_edge_t	*e2,
+		      cairo_bo_point32_t	 point)
 {
-    int cmp;
-
-    cmp = _cairo_bo_point32_compare (&a->point, &b->point);
-    if (cmp)
-	return cmp;
-
-    cmp = a->type - b->type;
-    if (cmp)
-	return cmp;
-
-    return a - b;
-}
-
-static inline void
-_pqueue_init (pqueue_t *pq)
-{
-    pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
-    pq->size = 0;
-
-    pq->elements = pq->elements_embedded;
-}
-
-static inline void
-_pqueue_fini (pqueue_t *pq)
-{
-    if (pq->elements != pq->elements_embedded)
-	free (pq->elements);
+    event->type = type;
+    event->e1 = e1;
+    event->e2 = e2;
+    event->point = point;
 }
 
 static cairo_status_t
-_pqueue_grow (pqueue_t *pq)
-{
-    cairo_bo_event_t **new_elements;
-    pq->max_size *= 2;
-
-    if (pq->elements == pq->elements_embedded) {
-	new_elements = _cairo_malloc_ab (pq->max_size,
-					 sizeof (cairo_bo_event_t *));
-	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	memcpy (new_elements, pq->elements_embedded,
-		sizeof (pq->elements_embedded));
-    } else {
-	new_elements = _cairo_realloc_ab (pq->elements,
-					  pq->max_size,
-					  sizeof (cairo_bo_event_t *));
-	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    pq->elements = new_elements;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_status_t
-_pqueue_push (pqueue_t *pq, cairo_bo_event_t *event)
+_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
+			      cairo_bo_event_t	     *event)
 {
-    cairo_bo_event_t **elements;
-    int i, parent;
-
-    if (unlikely (pq->size + 1 == pq->max_size)) {
-	cairo_status_t status;
-
-	status = _pqueue_grow (pq);
-	if (unlikely (status))
-	    return status;
-    }
-
-    elements = pq->elements;
-
-    for (i = ++pq->size;
-	 i != PQ_FIRST_ENTRY &&
-	 cairo_bo_event_compare (event,
-				 elements[parent = PQ_PARENT_INDEX (i)]) < 0;
-	 i = parent)
-    {
-	elements[i] = elements[parent];
-    }
-
-    elements[i] = event;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline void
-_pqueue_pop (pqueue_t *pq)
-{
-    cairo_bo_event_t **elements = pq->elements;
-    cairo_bo_event_t *tail;
-    int child, i;
-
-    tail = elements[pq->size--];
-    if (pq->size == 0) {
-	elements[PQ_FIRST_ENTRY] = NULL;
-	return;
-    }
-
-    for (i = PQ_FIRST_ENTRY;
-	 (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
-	 i = child)
-    {
-	if (child != pq->size &&
-	    cairo_bo_event_compare (elements[child+1],
-				    elements[child]) < 0)
-	{
-	    child++;
-	}
-
-	if (cairo_bo_event_compare (elements[child], tail) >= 0)
-	    break;
-
-	elements[i] = elements[child];
-    }
-    elements[i] = tail;
-}
-
-static inline cairo_status_t
-_cairo_bo_event_queue_insert (cairo_bo_event_queue_t	*queue,
-			      cairo_bo_event_type_t	 type,
-			      cairo_bo_edge_t		*e1,
-			      cairo_bo_edge_t		*e2,
-			      const cairo_point_t	 *point)
-{
-    cairo_bo_queue_event_t *event;
-
-    event = _cairo_freepool_alloc (&queue->pool);
-    if (unlikely (event == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    event->type = type;
-    event->e1 = e1;
-    event->e2 = e2;
-    event->point = *point;
-
-    return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event);
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    /* Don't insert if there's already an equivalent intersection event in the queue. */
+    if (_cairo_skip_list_insert (&queue->intersection_queue, event,
+		      event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    return status;
 }
 
 static void
 _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
 			      cairo_bo_event_t	     *event)
 {
-    _cairo_freepool_free (&queue->pool, event);
+    if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
+	_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
 }
 
 static cairo_bo_event_t *
 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
 {
-    cairo_bo_event_t *event, *cmp;
+    skip_elt_t *elt = event_queue->intersection_queue.chains[0];
+    cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
+    cairo_bo_event_t *startstop;
 
-    event = event_queue->pqueue.elements[PQ_FIRST_ENTRY];
-    cmp = *event_queue->start_events;
-    if (event == NULL ||
-	(cmp != NULL && cairo_bo_event_compare (cmp, event) < 0))
+    startstop = *event_queue->sorted_startstop_event_ptrs;
+    if (startstop == NULL)
+	return intersection;
+
+    if (intersection == NULL ||
+	cairo_bo_event_compare (startstop, intersection) <= 0)
     {
-	event = cmp;
-	event_queue->start_events++;
-    }
-    else
-    {
-	_pqueue_pop (&event_queue->pqueue);
+	event_queue->sorted_startstop_event_ptrs++;
+	return startstop;
     }
 
-    return event;
+    return intersection;
 }
 
 CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
 			cairo_bo_event_t *,
-			cairo_bo_event_compare)
-
-static void
-_cairo_bo_event_queue_init (cairo_bo_event_queue_t	 *event_queue,
-			    cairo_bo_event_t		**start_events,
-			    int				  num_events)
-{
-    _cairo_bo_event_queue_sort (start_events, num_events);
-    start_events[num_events] = NULL;
-
-    event_queue->start_events = start_events;
-
-    _cairo_freepool_init (&event_queue->pool,
-			  sizeof (cairo_bo_queue_event_t));
-    _pqueue_init (&event_queue->pqueue);
-    event_queue->pqueue.elements[PQ_FIRST_ENTRY] = NULL;
-}
+			cairo_bo_event_compare_pointers)
 
 static cairo_status_t
-_cairo_bo_event_queue_insert_stop (cairo_bo_event_queue_t	*event_queue,
-				   cairo_bo_edge_t		*edge)
+_cairo_bo_event_queue_init (cairo_bo_event_queue_t	*event_queue,
+			    cairo_bo_edge_t	*edges,
+			    int				 num_edges)
 {
-    cairo_bo_point32_t point;
+    int i;
+    cairo_bo_event_t *events, **sorted_event_ptrs;
+    unsigned num_events = 2*num_edges;
+
+    /* The skip_elt_t field of a cairo_bo_event_t isn't used for start
+     * or stop events, so this allocation is safe.  XXX: make the
+     * event type a union so it doesn't always contain the skip
+     * elt? */
+    events = _cairo_malloc_ab_plus_c (num_events,
+				      sizeof (cairo_bo_event_t) +
+				      sizeof (cairo_bo_event_t *),
+				      sizeof (cairo_bo_event_t *));
+    if (unlikely (events == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
+    event_queue->startstop_events = events;
+    event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
 
-    point.y = edge->edge.bottom;
-    point.x = _line_compute_intersection_x_for_y (&edge->edge.line,
-						  point.y);
-    return _cairo_bo_event_queue_insert (event_queue,
-					 CAIRO_BO_EVENT_TYPE_STOP,
-					 edge, NULL,
-					 &point);
+    for (i = 0; i < num_edges; i++) {
+	sorted_event_ptrs[i] = &events[2*i];
+	sorted_event_ptrs[i+num_edges] = &events[2*i+1];
+
+	/* Initialize "middle" to top */
+	edges[i].middle = edges[i].top;
+
+	_cairo_bo_event_init (&events[2*i],
+			      CAIRO_BO_EVENT_TYPE_START,
+			      &edges[i], NULL,
+			      edges[i].top);
+
+	_cairo_bo_event_init (&events[2*i+1],
+			      CAIRO_BO_EVENT_TYPE_STOP,
+			      &edges[i], NULL,
+			      edges[i].bottom);
+    }
+
+    _cairo_bo_event_queue_sort (sorted_event_ptrs, num_events);
+    event_queue->sorted_startstop_event_ptrs[num_events] = NULL;
+
+    _cairo_skip_list_init (&event_queue->intersection_queue,
+			   cairo_bo_event_compare_abstract,
+			   sizeof (cairo_bo_event_t));
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
 {
-    _pqueue_fini (&event_queue->pqueue);
-    _cairo_freepool_fini (&event_queue->pool);
+    _cairo_skip_list_fini (&event_queue->intersection_queue);
+    if (event_queue->startstop_events)
+	free (event_queue->startstop_events);
 }
 
-static inline cairo_status_t
+static cairo_status_t
 _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t	*event_queue,
 							   cairo_bo_edge_t	*left,
-							   cairo_bo_edge_t *right)
+							   cairo_bo_edge_t	*right)
 {
+    cairo_bo_status_t status;
     cairo_bo_point32_t intersection;
+    cairo_bo_event_t event;
 
-    if (_line_equal (&left->edge.line, &right->edge.line))
+    if (left == NULL || right == NULL)
 	return CAIRO_STATUS_SUCCESS;
 
     /* The names "left" and "right" here are correct descriptions of
      * the order of the two edges within the active edge list. So if a
      * slope comparison also puts left less than right, then we know
-     * that the intersection of these two segments has already
+     * that the intersection of these two segments has oalready
      * occurred before the current sweep line position. */
-    if (_slope_compare (left, right) <= 0)
+    if (_slope_compare (left, right) < 0)
 	return CAIRO_STATUS_SUCCESS;
 
-    if (! _cairo_bo_edge_intersect (left, right, &intersection))
+    status = _cairo_bo_edge_intersect (left, right, &intersection);
+    if (status == CAIRO_BO_STATUS_PARALLEL ||
+	status == CAIRO_BO_STATUS_NO_INTERSECTION)
+    {
 	return CAIRO_STATUS_SUCCESS;
+    }
 
-    return _cairo_bo_event_queue_insert (event_queue,
-					 CAIRO_BO_EVENT_TYPE_INTERSECTION,
-					 left, right,
-					 &intersection);
+    _cairo_bo_event_init (&event,
+			  CAIRO_BO_EVENT_TYPE_INTERSECTION,
+			  left, right,
+			  intersection);
+
+    return _cairo_bo_event_queue_insert (event_queue, &event);
 }
 
 static void
 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
 {
+    _cairo_skip_list_init (&sweep_line->active_edges,
+			   _sweep_line_elt_compare,
+			   sizeof (sweep_line_elt_t));
+
     sweep_line->head = NULL;
-    sweep_line->stopped = NULL;
-    sweep_line->current_y = INT32_MIN;
-    sweep_line->current_edge = NULL;
+    sweep_line->tail = NULL;
+    sweep_line->current_y = 0;
+}
+
+static void
+_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
+{
+    _cairo_skip_list_fini (&sweep_line->active_edges);
 }
 
 static cairo_status_t
 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t		*edge)
 {
-    if (sweep_line->current_edge != NULL) {
-	cairo_bo_edge_t *prev, *next;
-	int cmp;
+    skip_elt_t *next_elt;
+    sweep_line_elt_t *sweep_line_elt;
+    cairo_bo_edge_t **prev_of_next, **next_of_prev;
 
-	cmp = _cairo_bo_sweep_line_compare_edges (sweep_line,
-						  sweep_line->current_edge,
-						  edge);
-	if (cmp < 0) {
-	    prev = sweep_line->current_edge;
-	    next = prev->next;
-	    while (next != NULL &&
-		   _cairo_bo_sweep_line_compare_edges (sweep_line,
-						       next, edge) < 0)
-	    {
-		prev = next, next = prev->next;
-	    }
+    sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
+					      1 /* unique inserts*/);
+    if (unlikely (sweep_line_elt == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	    prev->next = edge;
-	    edge->prev = prev;
-	    edge->next = next;
-	    if (next != NULL)
-		next->prev = edge;
-	} else if (cmp > 0) {
-	    next = sweep_line->current_edge;
-	    prev = next->prev;
-	    while (prev != NULL &&
-		   _cairo_bo_sweep_line_compare_edges (sweep_line,
-						       prev, edge) > 0)
-	    {
-		next = prev, prev = next->prev;
-	    }
+    next_elt = sweep_line_elt->elt.next[0];
+    if (next_elt)
+	prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev);
+    else
+	prev_of_next = &sweep_line->tail;
 
-	    next->prev = edge;
-	    edge->next = next;
-	    edge->prev = prev;
-	    if (prev != NULL)
-		prev->next = edge;
-	    else
-		sweep_line->head = edge;
-	} else {
-	    prev = sweep_line->current_edge;
-	    edge->prev = prev;
-	    edge->next = prev->next;
-	    if (prev->next != NULL)
-		prev->next->prev = edge;
-	    prev->next = edge;
-	}
-    } else {
-	sweep_line->head = edge;
-    }
+    if (*prev_of_next)
+	next_of_prev = &(*prev_of_next)->next;
+    else
+	next_of_prev = &sweep_line->head;
 
-    sweep_line->current_edge = edge;
+    edge->prev = *prev_of_next;
+    edge->next = *next_of_prev;
+    *prev_of_next = edge;
+    *next_of_prev = edge;
+
+    edge->sweep_line_elt = sweep_line_elt;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t	*edge)
 {
-    if (edge->prev != NULL)
-	edge->prev->next = edge->next;
-    else
-	sweep_line->head = edge->next;
+    cairo_bo_edge_t **left_next, **right_prev;
+
+    _cairo_skip_list_delete_given (&sweep_line->active_edges,
+				   &edge->sweep_line_elt->elt);
 
-    if (edge->next != NULL)
-	edge->next->prev = edge->prev;
+    left_next = &sweep_line->head;
+    if (edge->prev)
+	left_next = &edge->prev->next;
 
-    if (sweep_line->current_edge == edge)
-	sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
+    right_prev = &sweep_line->tail;
+    if (edge->next)
+	right_prev = &edge->next->prev;
+
+    *left_next = edge->next;
+    *right_prev = edge->prev;
 }
 
 static void
 _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t	*sweep_line,
 			   cairo_bo_edge_t		*left,
 			   cairo_bo_edge_t		*right)
 {
-    if (left->prev != NULL)
-	left->prev->next = right;
-    else
-	sweep_line->head = right;
+    sweep_line_elt_t *left_elt, *right_elt;
+    cairo_bo_edge_t **before_left, **after_right;
+
+    /* Within the skip list we can do the swap simply by swapping the
+     * pointers to the edge elements and leaving all of the skip list
+     * elements and pointers unchanged. */
+    left_elt = left->sweep_line_elt;
+    right_elt = SKIP_ELT_TO_EDGE_ELT (left_elt->elt.next[0]);
+
+    left_elt->edge = right;
+    right->sweep_line_elt = left_elt;
 
-    if (right->next != NULL)
-	right->next->prev = left;
+    right_elt->edge = left;
+    left->sweep_line_elt = right_elt;
+
+    /* Within the doubly-linked list of edges, there's a bit more
+     * bookkeeping involved with the swap. */
+    before_left = &sweep_line->head;
+    if (left->prev)
+	before_left = &left->prev->next;
+    *before_left = right;
+
+    after_right = &sweep_line->tail;
+    if (right->next)
+	after_right = &right->next->prev;
+    *after_right = left;
 
     left->next = right->next;
     right->next = left;
 
     right->prev = left->prev;
     left->prev = right;
 }
 
 #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->edge.line.p1.x, edge->edge.line.p1.y,
-	    edge->edge.line.p2.x, edge->edge.line.p2.y);
+	    edge->top.x, edge->top.y,
+	    edge->bottom.x, edge->bottom.y);
 }
 
 static void
 _cairo_bo_event_print (cairo_bo_event_t *event)
 {
     switch (event->type) {
     case CAIRO_BO_EVENT_TYPE_START:
 	printf ("Start: ");
@@ -1230,648 +1195,618 @@ static void
 	_cairo_bo_edge_print (event->e2);
     }
     printf ("\n");
 }
 
 static void
 _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue)
 {
+    skip_elt_t *elt;
     /* XXX: fixme to print the start/stop array too. */
+    cairo_skip_list_t *queue = &event_queue->intersection_queue;
+    cairo_bo_event_t *event;
+
     printf ("Event queue:\n");
+
+    for (elt = queue->chains[0];
+	 elt;
+	 elt = elt->next[0])
+    {
+	event = SKIP_ELT_TO_EVENT (elt);
+	_cairo_bo_event_print (event);
+    }
 }
 
 static void
 _cairo_bo_sweep_line_print (cairo_bo_sweep_line_t *sweep_line)
 {
     cairo_bool_t first = TRUE;
+    skip_elt_t *elt;
     cairo_bo_edge_t *edge;
 
+    printf ("Sweep line (reversed):     ");
+
+    for (edge = sweep_line->tail;
+	 edge;
+	 edge = edge->prev)
+    {
+	if (!first)
+	    printf (", ");
+	_cairo_bo_edge_print (edge);
+	first = FALSE;
+    }
+    printf ("\n");
+
+
     printf ("Sweep line from edge list: ");
     first = TRUE;
     for (edge = sweep_line->head;
 	 edge;
 	 edge = edge->next)
     {
 	if (!first)
 	    printf (", ");
 	_cairo_bo_edge_print (edge);
 	first = FALSE;
     }
     printf ("\n");
+
+    printf ("Sweep line from skip list: ");
+    first = TRUE;
+    for (elt = sweep_line->active_edges.chains[0];
+	 elt;
+	 elt = elt->next[0])
+    {
+	if (!first)
+	    printf (", ");
+	_cairo_bo_edge_print (SKIP_ELT_TO_EDGE (elt));
+	first = FALSE;
+    }
+    printf ("\n");
 }
 
 static void
 print_state (const char			*msg,
-	     cairo_bo_event_t		*event,
 	     cairo_bo_event_queue_t	*event_queue,
 	     cairo_bo_sweep_line_t	*sweep_line)
 {
-    printf ("%s ", msg);
-    _cairo_bo_event_print (event);
+    printf ("%s\n", msg);
     _cairo_bo_event_queue_print (event_queue);
     _cairo_bo_sweep_line_print (sweep_line);
     printf ("\n");
 }
 #endif
 
-#if DEBUG_EVENTS
-static void CAIRO_PRINTF_FORMAT (1, 2)
-event_log (const char *fmt, ...)
+/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t
+ * of bo_traps. */
+static cairo_status_t
+_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
+			 int32_t		bot,
+			 cairo_bo_traps_t	*bo_traps)
 {
-    FILE *file;
+    cairo_fixed_t fixed_top, fixed_bot;
+    cairo_bo_trap_t *trap = left->deferred_trap;
+    cairo_bo_edge_t *right;
+
+    if (!trap)
+	return CAIRO_STATUS_SUCCESS;
+
+     /* If the right edge of the trapezoid stopped earlier than the
+      * left edge, then cut the trapezoid bottom early. */
+    right = trap->right;
+    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_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_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;
 
-    if (getenv ("CAIRO_DEBUG_EVENTS") == NULL)
-	return;
+	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_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 (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
+	}
+    }
+
+    _cairo_freelist_free (&bo_traps->freelist, trap);
+    left->deferred_trap = NULL;
+
+    return _cairo_traps_status (bo_traps->traps);
+}
 
-    file = fopen ("bo-events.txt", "a");
-    if (file != NULL) {
-	va_list ap;
+/* Start a new trapezoid at the given top y coordinate, whose edges
+ * are `edge' and `edge->next'. If `edge' already has a trapezoid,
+ * then either add it to the traps in `bo_traps', if the trapezoid's
+ * right edge differs from `edge->next', or do nothing if the new
+ * trapezoid would be a continuation of the existing one. */
+static cairo_status_t
+_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	*edge,
+				       int32_t		top,
+				       cairo_bo_traps_t	*bo_traps)
+{
+    cairo_status_t status;
+    cairo_bo_trap_t *trap = edge->deferred_trap;
+
+    if (trap) {
+	if (trap->right == edge->next) return CAIRO_STATUS_SUCCESS;
+	status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
+	if (status)
+	    return status;
+    }
+
+    if (edge->next) {
+	trap = edge->deferred_trap = _cairo_freelist_alloc (&bo_traps->freelist);
+	if (!edge->deferred_trap)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	trap->right = edge->next;
+	trap->top = top;
+    }
+    return CAIRO_STATUS_SUCCESS;
+}
 
-	va_start (ap, fmt);
-	vfprintf (file, fmt, ap);
-	va_end (ap);
+static void
+_cairo_bo_traps_init (cairo_bo_traps_t	*bo_traps,
+		      cairo_traps_t	*traps,
+		      cairo_fixed_t	 xmin,
+		      cairo_fixed_t	 ymin,
+		      cairo_fixed_t	 xmax,
+		      cairo_fixed_t	 ymax)
+{
+    bo_traps->traps = traps;
+    _cairo_freelist_init (&bo_traps->freelist, sizeof(cairo_bo_trap_t));
+    bo_traps->xmin = xmin;
+    bo_traps->ymin = ymin;
+    bo_traps->xmax = xmax;
+    bo_traps->ymax = ymax;
+}
+
+static void
+_cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
+{
+    _cairo_freelist_fini (&bo_traps->freelist);
+}
 
-	fclose (file);
+#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");
+	    abort ();
+	}
+    }
+
+    if (edge || elt) {
+	fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
+	abort ();
     }
 }
 #endif
 
-static inline cairo_bool_t
-edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
-{
-    if (_line_equal (&a->edge.line, &b->edge.line))
-	return TRUE;
 
-    if (_slope_compare (a, b))
-	return FALSE;
-
-    /* The choice of y is not truly arbitrary since we must guarantee that it
-     * is greater than the start of either line.
-     */
-    if (a->edge.line.p1.y == b->edge.line.p1.y) {
-	return a->edge.line.p1.x == b->edge.line.p1.x;
-    } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
-	return edge_compare_for_y_against_x (b,
-					     a->edge.line.p1.y,
-					     a->edge.line.p1.x) == 0;
-    } else {
-	return edge_compare_for_y_against_x (a,
-					     b->edge.line.p1.y,
-					     b->edge.line.p1.x) == 0;
-    }
-}
-
-/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t */
 static cairo_status_t
-_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
-			 int32_t		 bot,
-			 cairo_traps_t	        *traps)
-{
-    cairo_bo_trap_t *trap = &left->deferred_trap;
-
-    /* Only emit (trivial) non-degenerate trapezoids with positive height. */
-    if (likely (trap->top < bot)) {
-	_cairo_traps_add_trap (traps,
-			       trap->top, bot,
-			       &left->edge.line, &trap->right->edge.line);
-
-#if DEBUG_PRINT_STATE
-	printf ("Deferred trap: left=(%x, %x)-(%x,%x) "
-		"right=(%x,%x)-(%x,%x) top=%x, bot=%x\n",
-		left->edge.line.p1.x, left->edge.line.p1.y,
-		left->edge.line.p2.x, left->edge.line.p2.y,
-		trap->right->edge.line.p1.x, trap->right->edge.line.p1.y,
-		trap->right->edge.line.p2.x, trap->right->edge.line.p2.y,
-		trap->top, bot);
-#endif
-#if DEBUG_EVENTS
-	event_log ("end trap: %lu %lu %d %d\n",
-		   (long) left,
-		   (long) trap->right,
-		   trap->top,
-		   bot);
-#endif
-    }
-
-    trap->right = NULL;
-
-    return _cairo_traps_status (traps);
-}
-
-
-/* Start a new trapezoid at the given top y coordinate, whose edges
- * are `edge' and `edge->next'. If `edge' already has a trapezoid,
- * then either add it to the traps in `traps', if the trapezoid's
- * right edge differs from `edge->next', or do nothing if the new
- * trapezoid would be a continuation of the existing one. */
-static inline cairo_status_t
-_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	*left,
-				       cairo_bo_edge_t  *right,
-				       int               top,
-				       cairo_traps_t	*traps)
+_active_edges_to_traps (cairo_bo_edge_t		*head,
+			int32_t			 top,
+			cairo_fill_rule_t	 fill_rule,
+			cairo_bo_traps_t	*bo_traps)
 {
     cairo_status_t status;
-
-    if (left->deferred_trap.right == right)
-	return CAIRO_STATUS_SUCCESS;
+    int in_out = 0;
+    cairo_bo_edge_t *edge;
 
-    if (left->deferred_trap.right != NULL) {
-	if (right != NULL && edges_colinear (left->deferred_trap.right, right))
-	{
-	    /* continuation on right, so just swap edges */
-	    left->deferred_trap.right = right;
-	    return CAIRO_STATUS_SUCCESS;
+    for (edge = head; edge; edge = edge->next) {
+	if (fill_rule == CAIRO_FILL_RULE_WINDING) {
+	    in_out += edge->dir;
+	    if (in_out == 0) {
+		status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
+		if (status)
+		    return status;
+		continue;
+	    }
+	} else {
+	    in_out++;
+	    if ((in_out & 1) == 0) {
+		status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
+		if (status)
+		    return status;
+		continue;
+	    }
 	}
 
-	status = _cairo_bo_edge_end_trap (left, top, traps);
-	if (unlikely (status))
+	status = _cairo_bo_edge_start_or_continue_trap (edge, top, bo_traps);
+	if (status)
 	    return status;
     }
 
-    if (right != NULL && ! edges_colinear (left, right)) {
-	left->deferred_trap.top = top;
-	left->deferred_trap.right = right;
-
-#if DEBUG_EVENTS
-	event_log ("begin trap: %lu %lu %d\n",
-		   (long) left,
-		   (long) right,
-		   top);
-#endif
-    }
-
     return CAIRO_STATUS_SUCCESS;
 }
 
-static inline cairo_status_t
-_active_edges_to_traps (cairo_bo_edge_t		*left,
-			int32_t			 top,
-			cairo_fill_rule_t	 fill_rule,
-			cairo_traps_t	        *traps)
-{
-    cairo_bo_edge_t *right;
-    cairo_status_t status;
-
-#if DEBUG_PRINT_STATE
-    printf ("Processing active edges for %x\n", top);
-#endif
-
-    if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-	while (left != NULL) {
-	    int in_out;
-
-	    /* Greedily search for the closing edge, so that we generate the
-	     * maximal span width with the minimal number of trapezoids.
-	     */
-	    in_out = left->edge.dir;
-
-	    /* Check if there is a co-linear edge with an existing trap */
-	    right = left->next;
-	    if (left->deferred_trap.right == NULL) {
-		while (right != NULL && right->deferred_trap.right == NULL)
-		    right = right->next;
-
-		if (right != NULL && edges_colinear (left, right)) {
-		    /* continuation on left */
-		    left->deferred_trap = right->deferred_trap;
-		    right->deferred_trap.right = NULL;
-		}
-	    }
-
-	    /* End all subsumed traps */
-	    right = left->next;
-	    while (right != NULL) {
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		in_out += right->edge.dir;
-		if (in_out == 0) {
-		    cairo_bo_edge_t *next;
-		    cairo_bool_t skip = FALSE;
-
-		    /* skip co-linear edges */
-		    next = right->next;
-		    if (next != NULL)
-			skip = edges_colinear (right, next);
-
-		    if (! skip)
-			break;
-		}
-
-		right = right->next;
-	    }
-
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-
-	    left = right;
-	    if (left != NULL)
-		left = left->next;
-	}
-    } else {
-	while (left != NULL) {
-	    int in_out = 0;
-
-	    right = left->next;
-	    while (right != NULL) {
-		if (right->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (right, top, traps);
-		    if (unlikely (status))
-			return status;
-		}
-
-		if ((in_out++ & 1) == 0) {
-		    cairo_bo_edge_t *next;
-		    cairo_bool_t skip = FALSE;
-
-		    /* skip co-linear edges */
-		    next = right->next;
-		    if (next != NULL)
-			skip = edges_colinear (right, next);
-
-		    if (! skip)
-			break;
-		}
-
-		right = right->next;
-	    }
-
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
-	    if (unlikely (status))
-		return status;
-
-	    left = right;
-	    if (left != NULL)
-		left = left->next;
-	}
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-
 /* Execute a single pass of the Bentley-Ottmann algorithm on edges,
  * generating trapezoids according to the fill_rule and appending them
  * to traps. */
 static cairo_status_t
-_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t   **start_events,
-					    int			 num_events,
+_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t	*edges,
+					    int			 num_edges,
 					    cairo_fill_rule_t	 fill_rule,
 					    cairo_traps_t	*traps,
+					    cairo_fixed_t	xmin,
+					    cairo_fixed_t	ymin,
+					    cairo_fixed_t	xmax,
+					    cairo_fixed_t	ymax,
 					    int			*num_intersections)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
+    cairo_status_t status;
     int intersection_count = 0;
     cairo_bo_event_queue_t event_queue;
     cairo_bo_sweep_line_t sweep_line;
-    cairo_bo_event_t *event;
+    cairo_bo_traps_t bo_traps;
+    cairo_bo_event_t *event, event_saved;
+    cairo_bo_edge_t *edge;
     cairo_bo_edge_t *left, *right;
-    cairo_bo_edge_t *e1, *e2;
+    cairo_bo_edge_t *edge1, *edge2;
 
-#if DEBUG_EVENTS
-    {
-	int i;
+    if (num_edges == 0)
+	return CAIRO_STATUS_SUCCESS;
 
-	for (i = 0; i < num_events; i++) {
-	    cairo_bo_start_event_t *event =
-		((cairo_bo_start_event_t **) start_events)[i];
-	    event_log ("edge: %lu (%d, %d) (%d, %d) (%d, %d) %d\n",
-		       (long) &events[i].edge,
-		       event->edge.edge.line.p1.x,
-		       event->edge.edge.line.p1.y,
-		       event->edge.edge.line.p2.x,
-		       event->edge.edge.line.p2.y,
-		       event->edge.top,
-		       event->edge.bottom,
-		       event->edge.edge.dir);
-	}
-    }
+    status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
+    if (status)
+	return status;
+
+    _cairo_bo_sweep_line_init (&sweep_line);
+
+    _cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
+
+#if DEBUG_PRINT_STATE
+    print_state ("After initializing", &event_queue, &sweep_line);
 #endif
 
-    _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
-    _cairo_bo_sweep_line_init (&sweep_line);
+    while (1)
+    {
+	event = _cairo_bo_event_dequeue (&event_queue);
+	if (!event)
+	    break;
 
-    while ((event = _cairo_bo_event_dequeue (&event_queue))) {
 	if (event->point.y != sweep_line.current_y) {
-	    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
-		if (e1->deferred_trap.right != NULL) {
-		    status = _cairo_bo_edge_end_trap (e1,
-						      e1->edge.bottom,
-						      traps);
-		    if (unlikely (status))
-			goto unwind;
-		}
-	    }
-	    sweep_line.stopped = NULL;
-
 	    status = _active_edges_to_traps (sweep_line.head,
 					     sweep_line.current_y,
-					     fill_rule, traps);
-	    if (unlikely (status))
+					     fill_rule, &bo_traps);
+	    if (status)
 		goto unwind;
 
 	    sweep_line.current_y = event->point.y;
 	}
 
-#if DEBUG_EVENTS
-	event_log ("event: %d (%ld, %ld) %lu, %lu\n",
-		   event->type,
-		   (long) event->point.x,
-		   (long) event->point.y,
-		   (long) event->e1,
-		   (long) event->e2);
-#endif
+	event_saved = *event;
+	_cairo_bo_event_queue_delete (&event_queue, event);
+	event = &event_saved;
 
 	switch (event->type) {
 	case CAIRO_BO_EVENT_TYPE_START:
-	    e1 = &((cairo_bo_start_event_t *) event)->edge;
+	    edge = event->e1;
 
-	    status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
-	    if (unlikely (status))
+	    status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
+	    if (status)
 		goto unwind;
+	    /* Cache the insert position for use in pass 2.
+	    event->e2 = Sortlist::prev (sweep_line, edge);
+	    */
 
-	    status = _cairo_bo_event_queue_insert_stop (&event_queue, e1);
-	    if (unlikely (status))
+	    left = edge->prev;
+	    right = edge->next;
+
+	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
+	    if (status)
 		goto unwind;
 
-	    /* check to see if this is a continuation of a stopped edge */
-	    /* XXX change to an infinitesimal lengthening rule */
-	    for (left = sweep_line.stopped; left; left = left->next) {
-		if (e1->edge.top <= left->edge.bottom &&
-		    edges_colinear (e1, left))
-		{
-		    e1->deferred_trap = left->deferred_trap;
-		    if (left->prev != NULL)
-			left->prev = left->next;
-		    else
-			sweep_line.stopped = left->next;
-		    if (left->next != NULL)
-			left->next->prev = left->prev;
-		    break;
-		}
-	    }
+	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
+	    if (status)
+		goto unwind;
 
-	    left = e1->prev;
-	    right = e1->next;
-
-	    if (left != NULL) {
-		status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1);
-		if (unlikely (status))
-		    goto unwind;
-	    }
-
-	    if (right != NULL) {
-		status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
-		if (unlikely (status))
-		    goto unwind;
-	    }
-
+#if DEBUG_PRINT_STATE
+	    print_state ("After processing start", &event_queue, &sweep_line);
+#endif
 	    break;
 
 	case CAIRO_BO_EVENT_TYPE_STOP:
-	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
-	    _cairo_bo_event_queue_delete (&event_queue, event);
+	    edge = event->e1;
 
-	    left = e1->prev;
-	    right = e1->next;
+	    left = edge->prev;
+	    right = edge->next;
 
-	    _cairo_bo_sweep_line_delete (&sweep_line, e1);
+	    _cairo_bo_sweep_line_delete (&sweep_line, edge);
 
-	    /* first, check to see if we have a continuation via a fresh edge */
-	    if (e1->deferred_trap.right != NULL) {
-		e1->next = sweep_line.stopped;
-		if (sweep_line.stopped != NULL)
-		    sweep_line.stopped->prev = e1;
-		sweep_line.stopped = e1;
-		e1->prev = NULL;
-	    }
+	    status = _cairo_bo_edge_end_trap (edge, edge->bottom.y, &bo_traps);
+	    if (status)
+		goto unwind;
 
-	    if (left != NULL && right != NULL) {
-		status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
-		if (unlikely (status))
-		    goto unwind;
-	    }
+	    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
 	    break;
 
 	case CAIRO_BO_EVENT_TYPE_INTERSECTION:
-	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
-	    e2 = ((cairo_bo_queue_event_t *) event)->e2;
-	    _cairo_bo_event_queue_delete (&event_queue, event);
+	    edge1 = event->e1;
+	    edge2 = event->e2;
 
 	    /* skip this intersection if its edges are not adjacent */
-	    if (e2 != e1->next)
+	    if (edge2 != edge1->next)
 		break;
 
 	    intersection_count++;
 
-	    left = e1->prev;
-	    right = e2->next;
+	    edge1->middle = event->point;
+	    edge2->middle = event->point;
 
-	    _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);
+	    left = edge1->prev;
+	    right = edge2->next;
+
+	    _cairo_bo_sweep_line_swap (&sweep_line, edge1, edge2);
 
 	    /* after the swap e2 is left of e1 */
 
-	    if (left != NULL) {
-		status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2);
-		if (unlikely (status))
-		    goto unwind;
-	    }
+	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
+								       left, edge2);
+	    if (status)
+		goto unwind;
 
-	    if (right != NULL) {
-		status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
-		if (unlikely (status))
-		    goto unwind;
-	    }
+	    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
 	    break;
 	}
+#if DEBUG_VALIDATE
+	_cairo_bo_sweep_line_validate (&sweep_line);
+#endif
     }
 
     *num_intersections = intersection_count;
-    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
-	if (e1->deferred_trap.right != NULL) {
-	    status = _cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
-	    if (unlikely (status))
-		break;
-	}
+ 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);
+	if (!status)
+	    status = status2;
     }
- unwind:
+    _cairo_bo_traps_fini (&bo_traps);
+    _cairo_bo_sweep_line_fini (&sweep_line);
     _cairo_bo_event_queue_fini (&event_queue);
+    return status;
+}
 
-#if DEBUG_EVENTS
-    event_log ("\n");
-#endif
-
-    return status;
+static void
+update_minmax(cairo_fixed_t *inout_min,
+	      cairo_fixed_t *inout_max,
+	      cairo_fixed_t v)
+{
+    if (v < *inout_min)
+	*inout_min = v;
+    if (v > *inout_max)
+	*inout_max = v;
 }
 
 cairo_status_t
 _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
 					   const cairo_polygon_t *polygon,
 					   cairo_fill_rule_t	  fill_rule)
 {
     int intersections;
     cairo_status_t status;
-    cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
-    cairo_bo_start_event_t *events;
-    cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
-    cairo_bo_event_t **event_ptrs;
-    int num_events;
+    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;
 
-    num_events = polygon->num_edges;
-    if (unlikely (0 == num_events))
+    if (0 == polygon->num_edges)
 	return CAIRO_STATUS_SUCCESS;
 
-    events = stack_events;
-    event_ptrs = stack_event_ptrs;
-    if (num_events > ARRAY_LENGTH (stack_events)) {
-	events = _cairo_malloc_ab_plus_c (num_events,
-					  sizeof (cairo_bo_start_event_t) +
-					  sizeof (cairo_bo_event_t *),
-					  sizeof (cairo_bo_event_t *));
-	if (unlikely (events == NULL))
+    if (CAIRO_INJECT_FAULT ())
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    has_limits = _cairo_traps_get_limit (traps, &limit);
+
+    edges = stack_edges;
+    if (polygon->num_edges > ARRAY_LENGTH (stack_edges)) {
+	edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
+	if (unlikely (edges == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-	event_ptrs = (cairo_bo_event_t **) (events + num_events);
+    /* Figure out the bounding box of the input coordinates and
+     * validate that we're not given invalid polygon edges. */
+    for (i = 0; i < polygon->num_edges; i++) {
+	update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x);
+	update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y);
+	update_minmax (&xmin, &xmax, polygon->edges[i].edge.p2.x);
+	update_minmax (&ymin, &ymax, polygon->edges[i].edge.p2.y);
+	assert (polygon->edges[i].edge.p1.y <= polygon->edges[i].edge.p2.y &&
+		"BUG: tessellator given upside down or horizontal edges");
     }
 
-    for (i = 0; i < num_events; i++) {
-	event_ptrs[i] = (cairo_bo_event_t *) &events[i];
+    /* The tessellation functions currently assume that no line
+     * segment extends more than 2^31-1 in either dimension.  We
+     * guarantee this by offsetting the internal coordinates to the
+     * range [0,2^31-1], and clamping to 2^31-1 if a coordinate
+     * exceeds the range (and yes, this generates an incorrect
+     * result).  First we have to clamp the bounding box itself. */
+    /* XXX: Rather than changing the input values, a better approach
+     * would be to detect out-of-bounds input and return a
+     * CAIRO_STATUS_OVERFLOW value to the user. */
+    if (xmax - xmin < 0)
+	xmax = xmin + 0x7FFFFFFF;
+    if (ymax - ymin < 0)
+	ymax = ymin + 0x7FFFFFFF;
 
-	events[i].type = CAIRO_BO_EVENT_TYPE_START;
-	events[i].point.y = polygon->edges[i].top;
-	events[i].point.x =
-	    _line_compute_intersection_x_for_y (&polygon->edges[i].line,
-						events[i].point.y);
+    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;
+	}
 
-	events[i].edge.edge = polygon->edges[i];
-	events[i].edge.deferred_trap.right = NULL;
-	events[i].edge.prev = NULL;
-	events[i].edge.next = NULL;
+	/* 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
+	 * coordinates into the clamped bounding box.  */
+	if (top.x < 0) top.x = xmax - xmin;
+	if (top.y < 0) top.y = ymax - ymin;
+	if (bot.x < 0) bot.x = xmax - xmin;
+	if (bot.y < 0) bot.y = ymax - ymin;
+
+	if (top.y == bot.y) {
+	    /* Clamping might have produced horizontal edges.  Ignore
+	     * those. */
+	    continue;
+	}
+	assert (top.y < bot.y &&
+		"BUG: clamping the input range flipped the "
+		"orientation of an edge");
+
+	edge->top.x = top.x;
+	edge->top.y = top.y;
+	edge->bottom.x = bot.x;
+	edge->bottom.y = bot.y;
+	edge->dir = polygon->edges[i].dir;
+	edge->deferred_trap = NULL;
+	edge->prev = NULL;
+	edge->next = NULL;
+	edge->sweep_line_elt = NULL;
+
+	num_bo_edges++;
     }
 
-#if DEBUG_TRAPS
-    dump_edges (events, num_events, "bo-polygon-edges.txt");
-#endif
-
     /* XXX: This would be the convenient place to throw in multiple
      * passes of the Bentley-Ottmann algorithm. It would merely
      * require storing the results of each pass into a temporary
      * cairo_traps_t. */
-    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
-							 num_events,
+    status = _cairo_bentley_ottmann_tessellate_bo_edges (edges, num_bo_edges,
 							 fill_rule, traps,
+							 xmin, ymin, xmax, ymax,
 							 &intersections);
-#if DEBUG_TRAPS
-    dump_traps (traps, "bo-polygon-out.txt");
-#endif
-
-    if (events != stack_events)
-	free (events);
-
-    return status;
-}
-
-cairo_status_t
-_cairo_bentley_ottmann_tessellate_traps (cairo_traps_t *traps,
-					 cairo_fill_rule_t fill_rule)
-{
-    cairo_status_t status;
-    cairo_polygon_t polygon;
-    int i;
-
-    if (unlikely (0 == traps->num_traps))
-	return CAIRO_STATUS_SUCCESS;
-
-#if DEBUG_TRAPS
-    dump_traps (traps, "bo-traps-in.txt");
-#endif
 
-    _cairo_polygon_init (&polygon);
-    _cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
-
-    for (i = 0; i < traps->num_traps; i++) {
-	status = _cairo_polygon_add_line (&polygon,
-					  &traps->traps[i].left,
-					  traps->traps[i].top,
-					  traps->traps[i].bottom,
-					  1);
-	if (unlikely (status))
-	    goto CLEANUP;
-
-	status = _cairo_polygon_add_line (&polygon,
-					  &traps->traps[i].right,
-					  traps->traps[i].top,
-					  traps->traps[i].bottom,
-					  -1);
-	if (unlikely (status))
-	    goto CLEANUP;
-    }
-
-    _cairo_traps_clear (traps);
-    status = _cairo_bentley_ottmann_tessellate_polygon (traps,
-							&polygon,
-							fill_rule);
-
-#if DEBUG_TRAPS
-    dump_traps (traps, "bo-traps-out.txt");
-#endif
-
-  CLEANUP:
-    _cairo_polygon_fini (&polygon);
+    if (edges != stack_edges)
+	free (edges);
 
     return status;
 }
 
 #if 0
 static cairo_bool_t
 edges_have_an_intersection_quadratic (cairo_bo_edge_t	*edges,
 				      int		 num_edges)
 
 {
     int i, j;
     cairo_bo_edge_t *a, *b;
     cairo_bo_point32_t intersection;
+    cairo_bo_status_t status;
 
     /* We must not be given any upside-down edges. */
     for (i = 0; i < num_edges; i++) {
 	assert (_cairo_bo_point32_compare (&edges[i].top, &edges[i].bottom) < 0);
-	edges[i].line.p1.x <<= CAIRO_BO_GUARD_BITS;
-	edges[i].line.p1.y <<= CAIRO_BO_GUARD_BITS;
-	edges[i].line.p2.x <<= CAIRO_BO_GUARD_BITS;
-	edges[i].line.p2.y <<= CAIRO_BO_GUARD_BITS;
+	edges[i].top.x <<= CAIRO_BO_GUARD_BITS;
+	edges[i].top.y <<= CAIRO_BO_GUARD_BITS;
+	edges[i].bottom.x <<= CAIRO_BO_GUARD_BITS;
+	edges[i].bottom.y <<= CAIRO_BO_GUARD_BITS;
     }
 
     for (i = 0; i < num_edges; i++) {
 	for (j = 0; j < num_edges; j++) {
 	    if (i == j)
 		continue;
 
 	    a = &edges[i];
 	    b = &edges[j];
 
-	    if (! _cairo_bo_edge_intersect (a, b, &intersection))
+	    status = _cairo_bo_edge_intersect (a, b, &intersection);
+	    if (status == CAIRO_BO_STATUS_PARALLEL ||
+		status == CAIRO_BO_STATUS_NO_INTERSECTION)
+	    {
 		continue;
+	    }
 
 	    printf ("Found intersection (%d,%d) between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d)\n",
 		    intersection.x,
 		    intersection.y,
-		    a->line.p1.x, a->line.p1.y,
-		    a->line.p2.x, a->line.p2.y,
-		    b->line.p1.x, b->line.p1.y,
-		    b->line.p2.x, b->line.p2.y);
+		    a->top.x, a->top.y,
+		    a->bottom.x, a->bottom.y,
+		    b->top.x, b->top.y,
+		    b->bottom.x, b->bottom.y);
 
 	    return TRUE;
 	}
     }
     return FALSE;
 }
 
 #define TEST_MAX_EDGES 10
@@ -2101,28 +2036,29 @@ main (void)
 	run_test (test->name, test->edges, test->num_edges);
     }
 
     for (num_random = 0; num_random < MAX_RANDOM; num_random++) {
 	srand (0);
 	for (i = 0; i < num_random; i++) {
 	    do {
 		edge = &random_edges[i];
-		edge->line.p1.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
-		edge->line.p1.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
-		edge->line.p2.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
-		edge->line.p2.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
-		if (edge->line.p1.y > edge->line.p2.y) {
-		    int32_t tmp = edge->line.p1.y;
-		    edge->line.p1.y = edge->line.p2.y;
-		    edge->line.p2.y = tmp;
+		edge->top.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
+		edge->top.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
+		edge->bottom.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
+		edge->bottom.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
+		if (edge->top.y > edge->bottom.y) {
+		    int32_t tmp = edge->top.y;
+		    edge->top.y = edge->bottom.y;
+		    edge->bottom.y = tmp;
 		}
-	    } while (edge->line.p1.y == edge->line.p2.y);
+	    } while (edge->top.y == edge->bottom.y);
 	}
 
 	sprintf (random_name, "random-%02d", num_random);
 
 	run_test (random_name, random_edges, num_random);
     }
 
     return 0;
 }
 #endif
+
--- a/gfx/cairo/cairo/src/cairo-clip-private.h
+++ b/gfx/cairo/cairo/src/cairo-clip-private.h
@@ -38,100 +38,97 @@
 
 #include "cairo-types-private.h"
 #include "cairo-compiler-private.h"
 #include "cairo-path-fixed-private.h"
 #include "cairo-reference-count-private.h"
 
 extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
 
-enum {
-    CAIRO_CLIP_PATH_HAS_REGION = 0x1,
-    CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED = 0x2,
-    CAIRO_CLIP_PATH_IS_BOX = 0x4
-};
-
 struct _cairo_clip_path {
     cairo_reference_count_t	 ref_count;
     cairo_path_fixed_t		 path;
     cairo_fill_rule_t		 fill_rule;
     double			 tolerance;
     cairo_antialias_t		 antialias;
     cairo_clip_path_t		*prev;
-
-    cairo_rectangle_int_t extents;
-
-    /* partial caches */
-    unsigned int flags;
-    cairo_region_t *region;
-    cairo_surface_t *surface;
 };
 
 struct _cairo_clip {
-    /* can be used as a cairo_hash_entry_t for live clips */
-    cairo_clip_path_t *path;
+    cairo_clip_mode_t mode;
 
     cairo_bool_t all_clipped;
 
+    /*
+     * Mask-based clipping for cases where the backend
+     * clipping isn't sufficiently able.
+     *
+     * The rectangle here represents the
+     * portion of the destination surface that this
+     * clip surface maps to, it does not
+     * represent the extents of the clip region or
+     * clip paths
+     */
+    cairo_surface_t *surface;
+    cairo_rectangle_int_t surface_rect;
+    /*
+     * Surface clip serial number to store
+     * in the surface when this clip is set
+     */
+    unsigned int serial;
+    /*
+     * A clip region that can be placed in the surface
+     */
+    cairo_region_t *region;
+    /*
+     * If the surface supports path clipping, we store the list of
+     * clipping paths that has been set here as a linked list.
+     */
+    cairo_clip_path_t *path;
 };
 
 cairo_private void
-_cairo_clip_init (cairo_clip_t *clip);
+_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
 
 cairo_private cairo_status_t
-_cairo_clip_init_rectangle (cairo_clip_t *clip,
-			    const cairo_rectangle_int_t *rect);
-
-cairo_private_no_warn cairo_clip_t *
 _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
 
 cairo_private cairo_status_t
-_cairo_clip_init_copy_transformed (cairo_clip_t    *clip,
-				   cairo_clip_t    *other,
-				   const cairo_matrix_t *matrix);
+_cairo_clip_init_deep_copy (cairo_clip_t    *clip,
+                            cairo_clip_t    *other,
+                            cairo_surface_t *target);
 
 cairo_private void
 _cairo_clip_reset (cairo_clip_t *clip);
 
-#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
+cairo_private 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_private cairo_status_t
-_cairo_clip_rectangle (cairo_clip_t       *clip,
-		       const cairo_rectangle_int_t *rectangle);
-
-cairo_private cairo_status_t
-_cairo_clip_clip (cairo_clip_t       *clip,
-		  const cairo_path_fixed_t *path,
-		  cairo_fill_rule_t   fill_rule,
-		  double              tolerance,
-		  cairo_antialias_t   antialias);
+_cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
+				    cairo_rectangle_int_t   *rectangle);
 
 cairo_private cairo_status_t
-_cairo_clip_apply_clip (cairo_clip_t *clip,
-			const cairo_clip_t *other);
-
-cairo_private const cairo_rectangle_int_t *
-_cairo_clip_get_extents (const cairo_clip_t *clip);
-
-cairo_private cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst);
+_cairo_clip_intersect_to_region (cairo_clip_t      *clip,
+				 cairo_region_t *region);
 
 cairo_private cairo_status_t
-_cairo_clip_combine_with_surface (cairo_clip_t *clip,
-				  cairo_surface_t *dst,
-				  const cairo_rectangle_int_t *extents);
-
-cairo_private cairo_int_status_t
-_cairo_clip_get_region (cairo_clip_t *clip,
-			cairo_region_t **region);
-
-cairo_private cairo_int_status_t
-_cairo_clip_get_boxes (cairo_clip_t *clip,
-		       cairo_box_t **boxes,
-		       int *count);
+_cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
+				cairo_operator_t               op,
+				cairo_surface_t               *dst,
+				int                            dst_x,
+				int                            dst_y,
+				const cairo_rectangle_int_t   *extents);
 
 cairo_private void
-_cairo_clip_drop_cache (cairo_clip_t  *clip);
+_cairo_clip_translate (cairo_clip_t  *clip,
+                       cairo_fixed_t  tx,
+                       cairo_fixed_t  ty);
 
 cairo_private cairo_rectangle_list_t*
 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
 
 #endif /* CAIRO_CLIP_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -1,14 +1,13 @@
 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
  * Copyright © 2005 Red Hat, Inc.
- * Copyright © 2009 Chris Wilson
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
  * License version 2.1 as published by the Free Software Foundation
  * (the "LGPL") or, at your option, under the terms of the Mozilla
  * Public License Version 1.1 (the "MPL"). If you do not alter this
  * notice, a recipient may use your version of this file under either
  * the MPL or the LGPL.
@@ -31,133 +30,265 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  *	Kristian Høgsberg <krh@redhat.com>
- *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 #include "cairoint.h"
 #include "cairo-clip-private.h"
-#include "cairo-path-fixed-private.h"
-#include "cairo-region-private.h"
 
-/* Keep a stash of recently freed clip_paths, since we need to
- * reallocate them frequently.
- */
-#define MAX_FREED_POOL_SIZE 4
-typedef struct {
-    void *pool[MAX_FREED_POOL_SIZE];
-    int top;
-} freed_pool_t;
+static cairo_clip_path_t *
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
 
-static freed_pool_t clip_path_pool;
-
-static void *
-_atomic_fetch (void **slot)
+void
+_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
 {
-    return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
-}
+    if (target && target->backend)
+	clip->mode = _cairo_surface_get_clip_mode (target);
+    else
+	clip->mode = CAIRO_CLIP_MODE_MASK;
+
+    clip->all_clipped = FALSE;
 
-static cairo_bool_t
-_atomic_store (void **slot, void *ptr)
-{
-    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
+    clip->surface = NULL;
+    clip->surface_rect.x = 0;
+    clip->surface_rect.y = 0;
+    clip->surface_rect.width  = 0;
+    clip->surface_rect.height = 0;
+
+    clip->serial = 0;
+
+    clip->region = NULL;
+
+    clip->path = NULL;
 }
 
-static void *
-_freed_pool_get (freed_pool_t *pool)
+cairo_status_t
+_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
 {
-    void *ptr;
-    int i;
+    clip->mode = other->mode;
+
+    clip->all_clipped = other->all_clipped;
+    
+    clip->surface = cairo_surface_reference (other->surface);
+    clip->surface_rect = other->surface_rect;
+
+    clip->serial = other->serial;
+
+    if (other->region) {
+	cairo_status_t status;
+	
+	clip->region = cairo_region_copy (other->region);
 
-    i = pool->top - 1;
-    if (i < 0)
-	i = 0;
+	status = cairo_region_status (clip->region);
+	if (unlikely (status)) {
+	    cairo_surface_destroy (clip->surface);
+	    cairo_region_destroy (clip->region);
+	    clip->region = NULL;
+	    
+	    return status;
+	}
+    } else {
+	clip->region = NULL;
+    }
+    
+    clip->path = _cairo_clip_path_reference (other->path);
 
-    ptr = _atomic_fetch (&pool->pool[i]);
-    if (ptr != NULL) {
-	pool->top = i;
-	return ptr;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+void
+_cairo_clip_reset (cairo_clip_t *clip)
+{
+    clip->all_clipped = FALSE;
+
+    /* destroy any existing clip-region artifacts */
+    cairo_surface_destroy (clip->surface);
+    clip->surface = NULL;
+
+    clip->serial = 0;
+
+    if (clip->region) {
+	cairo_region_destroy (clip->region);
+
+	clip->region = NULL;
     }
 
-    /* either empty or contended */
-    for (i = ARRAY_LENGTH (pool->pool); i--;) {
-	ptr = _atomic_fetch (&pool->pool[i]);
-	if (ptr != NULL) {
-	    pool->top = i;
-	    return ptr;
-	}
-    }
-
-    /* empty */
-    pool->top = 0;
-    return NULL;
+    _cairo_clip_path_destroy (clip->path);
+    clip->path = NULL;
 }
 
 static void
-_freed_pool_put (freed_pool_t *pool, void *ptr)
+_cairo_clip_set_all_clipped (cairo_clip_t *clip, cairo_surface_t *target)
 {
-    int i = pool->top;
+    _cairo_clip_reset (clip);
+
+    clip->all_clipped = TRUE;
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
+}
+
 
-    if (_atomic_store (&pool->pool[i], ptr)) {
-	pool->top = i + 1;
-	return;
+static cairo_status_t
+_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
+				         cairo_rectangle_int_t   *rectangle)
+{
+    while (clip_path) {
+        cairo_rectangle_int_t extents;
+
+	_cairo_path_fixed_approximate_clip_extents (&clip_path->path, &extents);
+
+        if (! _cairo_rectangle_intersect (rectangle, &extents))
+	    return CAIRO_STATUS_SUCCESS;
+
+        clip_path = clip_path->prev;
     }
 
-    /* either full or contended */
-    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
-	if (_atomic_store (&pool->pool[i], ptr)) {
-	    pool->top = i + 1;
-	    return;
-	}
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
+				    cairo_rectangle_int_t *rectangle)
+{
+    cairo_status_t status;
+    cairo_bool_t is_empty;
+
+    if (!clip)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (clip->all_clipped) {
+	*rectangle = clip->surface_rect;
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    /* full */
-    pool->top = ARRAY_LENGTH (pool->pool);
-    free (ptr);
+    if (clip->path) {
+        status = _cairo_clip_path_intersect_to_rectangle (clip->path,
+                                                          rectangle);
+        if (unlikely (status))
+            return status;
+    }
+
+    if (clip->region) {
+	cairo_rectangle_int_t extents;
+
+	cairo_region_get_extents (clip->region, &extents);
+	is_empty = _cairo_rectangle_intersect (rectangle, &extents);
+	if (is_empty)
+	    return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (clip->surface)
+	is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_freed_pool_reset (freed_pool_t *pool)
+cairo_status_t
+_cairo_clip_intersect_to_region (cairo_clip_t   *clip,
+				 cairo_region_t *region)
 {
-    int i;
+    cairo_status_t status;
+
+    if (!clip)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (clip->all_clipped)
+	return cairo_region_intersect_rectangle (region, &clip->surface_rect);
 
-    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
-	free (pool->pool[i]);
-	pool->pool[i] = NULL;
+    if (clip->path) {
+	/* Intersect clip path into region. */
     }
+
+    if (clip->region) {
+	status = cairo_region_intersect (region, clip->region);
+	if (unlikely (status))
+	    return status;
+    }
+
+    if (clip->surface)
+	return cairo_region_intersect_rectangle (region, &clip->surface_rect);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_clip_path_t *
-_cairo_clip_path_create (cairo_clip_t *clip)
+/* Combines the region of clip->surface given by extents in
+ * device backend coordinates into the given temporary surface,
+ * which has its origin at dst_x, dst_y in backend coordinates
+ */
+cairo_status_t
+_cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
+				cairo_operator_t              op,
+				cairo_surface_t               *dst,
+				int                           dst_x,
+				int                           dst_y,
+				const cairo_rectangle_int_t *extents)
+{
+    cairo_surface_pattern_t pattern;
+    cairo_status_t status;
+
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
+    _cairo_pattern_init_for_surface (&pattern, clip->surface);
+
+    status = _cairo_surface_composite (op,
+				       &pattern.base,
+				       NULL,
+				       dst,
+				       extents->x - clip->surface_rect.x,
+				       extents->y - clip->surface_rect.y,
+				       0, 0,
+				       extents->x - dst_x,
+				       extents->y - dst_y,
+				       extents->width, extents->height);
+
+    _cairo_pattern_fini (&pattern.base);
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_clip_intersect_path (cairo_clip_t       *clip,
+			    cairo_path_fixed_t *path,
+			    cairo_fill_rule_t   fill_rule,
+			    double              tolerance,
+			    cairo_antialias_t   antialias)
 {
     cairo_clip_path_t *clip_path;
+    cairo_status_t status;
 
-    clip_path = _freed_pool_get (&clip_path_pool);
-    if (unlikely (clip_path == NULL)) {
-	clip_path = malloc (sizeof (cairo_clip_path_t));
-	if (unlikely (clip_path == NULL))
-	    return NULL;
+    if (clip->mode != CAIRO_CLIP_MODE_PATH)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    clip_path = malloc (sizeof (cairo_clip_path_t));
+    if (unlikely (clip_path == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = _cairo_path_fixed_init_copy (&clip_path->path, path);
+    if (unlikely (status)) {
+	free (clip_path);
+	return status;
     }
 
     CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
-
-    clip_path->flags = 0;
-    clip_path->region = NULL;
-    clip_path->surface = NULL;
-
+    clip_path->fill_rule = fill_rule;
+    clip_path->tolerance = tolerance;
+    clip_path->antialias = antialias;
     clip_path->prev = clip->path;
     clip->path = clip_path;
 
-    return clip_path;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_clip_path_t *
 _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
 {
     if (clip_path == NULL)
 	return NULL;
 
@@ -166,1187 +297,545 @@ static cairo_clip_path_t *
     _cairo_reference_count_inc (&clip_path->ref_count);
 
     return clip_path;
 }
 
 static void
 _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
 {
+    if (clip_path == NULL)
+	return;
+
     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
 
     if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count))
 	return;
 
     _cairo_path_fixed_fini (&clip_path->path);
-    if (clip_path->region != NULL)
-	cairo_region_destroy (clip_path->region);
-    if (clip_path->surface != NULL)
-	cairo_surface_destroy (clip_path->surface);
-
-    if (clip_path->prev != NULL)
-	_cairo_clip_path_destroy (clip_path->prev);
-
-    _freed_pool_put (&clip_path_pool, clip_path);
+    _cairo_clip_path_destroy (clip_path->prev);
+    free (clip_path);
 }
 
-void
-_cairo_clip_init (cairo_clip_t *clip)
+
+static cairo_int_status_t
+_cairo_clip_intersect_region (cairo_clip_t    *clip,
+			      cairo_traps_t   *traps,
+			      cairo_surface_t *target)
 {
-    clip->all_clipped = FALSE;
-    clip->path = NULL;
-}
+    cairo_region_t *region;
+    cairo_int_status_t status;
+
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (clip->mode != CAIRO_CLIP_MODE_REGION)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-static void
-_cairo_clip_set_all_clipped (cairo_clip_t *clip)
-{
-    clip->all_clipped = TRUE;
-    if (clip->path != NULL) {
-	_cairo_clip_path_destroy (clip->path);
-	clip->path = NULL;
+    status = _cairo_traps_extract_region (traps, &region);
+    if (status)
+	return status;
+
+    if (clip->region) {
+	status = cairo_region_intersect (clip->region, region);
+	cairo_region_destroy (region);
+    } else {
+	clip->region = region;
     }
+
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
+
+    if (!clip->region || cairo_region_is_empty (clip->region))
+	_cairo_clip_set_all_clipped (clip, target);
+
+    return status;
 }
 
 static cairo_status_t
-_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
-				 const cairo_rectangle_int_t *rect)
+_cairo_clip_intersect_mask (cairo_clip_t      *clip,
+			    cairo_traps_t     *traps,
+			    cairo_antialias_t antialias,
+			    cairo_surface_t   *target)
 {
-    cairo_clip_path_t *clip_path;
-    cairo_status_t status;
+    cairo_pattern_union_t pattern;
+    cairo_box_t extents;
+    cairo_rectangle_int_t surface_rect, target_rect;
+    cairo_surface_t *surface = NULL;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-    if (clip->path != NULL) {
-	if (rect->x <= clip->path->extents.x &&
-	    rect->y <= clip->path->extents.y &&
-	    rect->x + rect->width >= clip->path->extents.x + clip->path->extents.width &&
-	    rect->y + rect->height >= clip->path->extents.y + clip->path->extents.height)
-	{
-	    return CAIRO_STATUS_SUCCESS;
-	}
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* Represent the clip as a mask surface.  We create a new surface
+     * the size of the intersection of the old mask surface and the
+     * extents of the new clip path. */
+
+    _cairo_traps_extents (traps, &extents);
+    _cairo_box_round_to_rectangle (&extents, &surface_rect);
+
+    if (clip->surface != NULL) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	    goto DONE;
     }
 
-    clip_path = _cairo_clip_path_create (clip);
-    if (unlikely (clip_path == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    _cairo_path_fixed_init (&clip_path->path);
-
-    status = _cairo_path_fixed_move_to (&clip_path->path,
-					_cairo_fixed_from_int (rect->x),
-					_cairo_fixed_from_int (rect->y));
-    assert (status == CAIRO_STATUS_SUCCESS);
-    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
-					    _cairo_fixed_from_int (rect->width),
-					    _cairo_fixed_from_int (0));
-    assert (status == CAIRO_STATUS_SUCCESS);
-    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
-					    _cairo_fixed_from_int (0),
-					    _cairo_fixed_from_int (rect->height));
-    assert (status == CAIRO_STATUS_SUCCESS);
-    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
-					    _cairo_fixed_from_int (-rect->width),
-					    _cairo_fixed_from_int (0));
-    assert (status == CAIRO_STATUS_SUCCESS);
-    status = _cairo_path_fixed_close_path (&clip_path->path);
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    clip_path->extents = *rect;
-    clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
-    clip_path->tolerance = 1;
-    clip_path->antialias = CAIRO_ANTIALIAS_NONE;
-    clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
-
-    /* could preallocate the region if it proves worthwhile */
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* XXX consider accepting a matrix, no users yet. */
-cairo_status_t
-_cairo_clip_init_rectangle (cairo_clip_t *clip,
-			    const cairo_rectangle_int_t *rect)
-{
-    _cairo_clip_init (clip);
-
-    if (rect == NULL)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (rect->width == 0 || rect->height == 0) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_STATUS_SUCCESS;
+    /* Intersect with the target surface rectangle so we don't use
+     * more memory and time than we need to. */
+    status = _cairo_surface_get_extents (target, &target_rect);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	if (! _cairo_rectangle_intersect (&surface_rect, &target_rect))
+	    goto DONE;
     }
 
-    return _cairo_clip_intersect_rectangle (clip, rect);
-}
+    if (surface_rect.width == 0 || surface_rect.height == 0)
+	goto DONE;
+
+    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+			       CAIRO_CONTENT_COLOR);
+    /* The clipping operation should ideally be something like the following to
+     * avoid having to do as many passes over the data
 
-cairo_clip_t *
-_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
-{
-    if (other != NULL) {
-	clip->all_clipped = other->all_clipped;
-	clip->path = _cairo_clip_path_reference (other->path);
+	if (clip->surface != NULL) {
+	    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
+	} else {
+	    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+			       CAIRO_CONTENT_COLOR);
+	}
+	status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
+						  &pattern.base,
+						  surface,
+						  antialias,
+						  0, 0,
+						  0, 0,
+						  surface_rect.width,
+						  surface_rect.height,
+						  traps->traps,
+						  traps->num_traps);
 
-	/* this guy is here because of the weird return semantics of _cairo_clip_init_copy */
-	if (!other->path)
-	    return NULL;
-    } else {
-	_cairo_clip_init (clip);
+	However this operation is not accelerated by pixman
+
+	I believe the best possible operation would probably an unbounded SRC
+	operator.  Using SRC we could potentially avoid having to initialize
+	the surface which would be ideal from an efficiency point of view.
+	However, CAIRO_OPERATOR_SOURCE is bounded by the trapezoid mask and
+	_cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) will assert
+	because it assumes CAIRO_OPERATOR_SOURCE has been converted into other
+	operations.
+    */
+
+    surface = _cairo_surface_create_similar_solid (target,
+						   CAIRO_CONTENT_ALPHA,
+						   surface_rect.width,
+						   surface_rect.height,
+						   CAIRO_COLOR_TRANSPARENT);
+    if (surface->status) {
+	_cairo_pattern_fini (&pattern.base);
+	return surface->status;
     }
 
-    return clip;
-}
-
-void
-_cairo_clip_reset (cairo_clip_t *clip)
-{
-    clip->all_clipped = FALSE;
-    if (clip->path != NULL) {
-	_cairo_clip_path_destroy (clip->path);
-	clip->path = NULL;
-    }
-}
+    /* Render the new clipping path into the new mask surface. */
 
-static cairo_status_t
-_cairo_clip_intersect_path (cairo_clip_t       *clip,
-			    const cairo_path_fixed_t *path,
-			    cairo_fill_rule_t   fill_rule,
-			    double              tolerance,
-			    cairo_antialias_t   antialias)
-{
-    cairo_clip_path_t *clip_path;
-    cairo_status_t status;
-    cairo_rectangle_int_t extents;
-    cairo_box_t box;
-    cairo_bool_t is_box = FALSE;
+    _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
 
-    if (clip->path != NULL) {
-	if (clip->path->fill_rule == fill_rule &&
-	    (path->is_rectilinear ||
-	     (tolerance == clip->path->tolerance &&
-	      antialias == clip->path->antialias)) &&
-	    _cairo_path_fixed_equal (&clip->path->path, path))
-	{
-	    return CAIRO_STATUS_SUCCESS;
-	}
-    }
-
-    _cairo_path_fixed_approximate_clip_extents (path, &extents);
-    if (extents.width == 0 || extents.height == 0) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_STATUS_SUCCESS;
-    }
+    status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
+						  &pattern.base,
+						  surface,
+						  antialias,
+						  0, 0,
+						  0, 0,
+						  surface_rect.width,
+						  surface_rect.height,
+						  traps->traps,
+						  traps->num_traps);
 
-    is_box = _cairo_path_fixed_is_box (path, &box);
-    if (clip->path != NULL) {
-	if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) {
-	    _cairo_clip_set_all_clipped (clip);
-	    return CAIRO_STATUS_SUCCESS;
-	}
+    _cairo_pattern_fini (&pattern.base);
 
-	/* does this clip wholly subsume the others? */
-	if (is_box &&
-	    box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) &&
-	    box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) &&
-	    box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) &&
-	    box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height))
-	{
-	    return CAIRO_STATUS_SUCCESS;
-	}
-    }
-
-    clip_path = _cairo_clip_path_create (clip);
-    if (unlikely (clip_path == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = _cairo_path_fixed_init_copy (&clip_path->path, path);
     if (unlikely (status)) {
-	clip->path = clip->path->prev;
-	_cairo_clip_path_destroy (clip_path);
+	cairo_surface_destroy (surface);
 	return status;
     }
 
-    clip_path->extents = extents;
-    clip_path->fill_rule = fill_rule;
-    clip_path->tolerance = tolerance;
-    clip_path->antialias = antialias;
-    if (is_box)
-	clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
-
-    return CAIRO_STATUS_SUCCESS;
-}
+    /* If there was a clip surface already, combine it with the new
+     * mask surface using the IN operator, so we get the intersection
+     * of the old and new clipping paths. */
 
-cairo_status_t
-_cairo_clip_clip (cairo_clip_t       *clip,
-		  const cairo_path_fixed_t *path,
-		  cairo_fill_rule_t   fill_rule,
-		  double              tolerance,
-		  cairo_antialias_t   antialias)
-{
-    if (clip->all_clipped)
-	return CAIRO_STATUS_SUCCESS;
-
-    /* catch the empty clip path */
-    if (_cairo_path_fixed_fill_is_empty (path)) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_STATUS_SUCCESS;
-    }
+    if (clip->surface != NULL) {
+	_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
 
-    return _cairo_clip_intersect_path (clip,
-				       path, fill_rule, tolerance,
-				       antialias);
-}
-
-cairo_status_t
-_cairo_clip_rectangle (cairo_clip_t       *clip,
-		       const cairo_rectangle_int_t *rectangle)
-{
-    if (clip->all_clipped)
-	return CAIRO_STATUS_SUCCESS;
+	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
+					   &pattern.base,
+					   NULL,
+					   surface,
+					   surface_rect.x - clip->surface_rect.x,
+					   surface_rect.y - clip->surface_rect.y,
+					   0, 0,
+					   0, 0,
+					   surface_rect.width,
+					   surface_rect.height);
 
-    if (rectangle->width == 0 || rectangle->height == 0) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_STATUS_SUCCESS;
-    }
+	_cairo_pattern_fini (&pattern.base);
 
-    /* if a smaller clip has already been set, ignore the new path */
-    if (clip->path != NULL) {
-	if (rectangle->x <= clip->path->extents.x &&
-	    rectangle->y <= clip->path->extents.x &&
-	    rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
-	    rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
-	{
-	    return CAIRO_STATUS_SUCCESS;
+	if (unlikely (status)) {
+	    cairo_surface_destroy (surface);
+	    return status;
 	}
     }
 
-    return _cairo_clip_intersect_rectangle (clip, rectangle);
-}
-
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t      *clip,
-					      cairo_clip_path_t *other_path,
-					      const cairo_matrix_t *matrix)
-{
-    cairo_status_t status;
-    cairo_clip_path_t *clip_path;
-    cairo_bool_t is_empty;
-
-    if (other_path->prev != NULL) {
-        status = _cairo_clip_path_reapply_clip_path_transform (clip,
-							       other_path->prev,
-							       matrix);
-	if (unlikely (status))
-	    return status;
-    }
-
-    clip_path = _cairo_clip_path_create (clip);
-    if (unlikely (clip_path == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = _cairo_path_fixed_init_copy (&clip_path->path,
-					  &other_path->path);
-    if (unlikely (status)) {
-	_cairo_clip_path_destroy (clip_path);
-	return status;
-    }
-
-    _cairo_path_fixed_transform (&clip_path->path, matrix);
-    _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
-						&clip_path->extents);
-    if (clip_path->prev != NULL) {
-	is_empty = _cairo_rectangle_intersect (&clip_path->extents,
-					       &clip_path->prev->extents);
-    }
-
-    clip_path->fill_rule = other_path->fill_rule;
-    clip_path->tolerance = other_path->tolerance;
-    clip_path->antialias = other_path->antialias;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_translate (cairo_clip_t      *clip,
-					      cairo_clip_path_t *other_path,
-					      int tx, int ty)
-{
-    cairo_status_t status;
-    cairo_clip_path_t *clip_path;
-
-    if (other_path->prev != NULL) {
-        status = _cairo_clip_path_reapply_clip_path_translate (clip,
-							       other_path->prev,
-							       tx, ty);
-	if (unlikely (status))
-	    return status;
-    }
-
-    clip_path = _cairo_clip_path_create (clip);
-    if (unlikely (clip_path == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ DONE:
+    cairo_surface_destroy (clip->surface);
+    clip->surface = surface;
+    clip->surface_rect = surface_rect;
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
 
-    status = _cairo_path_fixed_init_copy (&clip_path->path,
-					  &other_path->path);
-    if (unlikely (status)) {
-	_cairo_clip_path_destroy (clip_path);
-	return status;
-    }
-
-    _cairo_path_fixed_translate (&clip_path->path,
-				 _cairo_fixed_from_int (tx),
-				 _cairo_fixed_from_int (ty));
-
-    clip_path->fill_rule = other_path->fill_rule;
-    clip_path->tolerance = other_path->tolerance;
-    clip_path->antialias = other_path->antialias;
-
-    clip_path->flags = other_path->flags;
-    if (other_path->region != NULL) {
-	clip_path->region = cairo_region_copy (other_path->region);
-	cairo_region_translate (clip_path->region, tx, ty);
-    }
-    clip_path->surface = cairo_surface_reference (other_path->surface);
-
-    clip_path->extents = other_path->extents;
-    clip_path->extents.x += tx;
-    clip_path->extents.y += ty;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_clip_init_copy_transformed (cairo_clip_t    *clip,
-				   cairo_clip_t    *other,
-				   const cairo_matrix_t *matrix)
-{
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    int tx, ty;
-
-    if (other == NULL) {
-	_cairo_clip_init (clip);
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    if (other->all_clipped) {
-	_cairo_clip_init (clip);
-	clip->all_clipped = TRUE;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    if (_cairo_matrix_is_identity (matrix)) {
-	_cairo_clip_init_copy (clip, other);
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    if (other->path != NULL) {
-	_cairo_clip_init (clip);
-
-	/* if we only need to translate, so we can reuse the caches... */
-	/* XXX we still loose the benefit of constructs when the copy is
-	 * deleted though. Indirect clip_paths?
-	 */
-	if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) {
-	    status = _cairo_clip_path_reapply_clip_path_translate (clip,
-								   other->path,
-								   tx, ty);
-	} else {
-	    status = _cairo_clip_path_reapply_clip_path_transform (clip,
-								   other->path,
-								   matrix);
-	    if (clip->path->extents.width == 0 &&
-		clip->path->extents.height == 0)
-	    {
-		_cairo_clip_set_all_clipped (clip);
-	    }
-	}
-    }
+    if (surface_rect.width == 0 || surface_rect.height == 0)
+	_cairo_clip_set_all_clipped (clip, target);
 
     return status;
 }
 
 static cairo_status_t
-_cairo_clip_apply_clip_path (cairo_clip_t *clip,
-			     const cairo_clip_path_t *path)
+_cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
+					cairo_path_fixed_t *path,
+					cairo_fill_rule_t   fill_rule,
+					double		    tolerance,
+					cairo_antialias_t   antialias,
+					cairo_surface_t    *target)
 {
+    cairo_span_renderer_t *renderer = NULL;
+    cairo_pattern_union_t pattern;
+    cairo_rectangle_int_t surface_rect;
+    cairo_surface_t *surface = NULL;
     cairo_status_t status;
-
-    if (path->prev != NULL)
-	status = _cairo_clip_apply_clip_path (clip, path->prev);
-
-    return _cairo_clip_intersect_path (clip,
-				       &path->path,
-				       path->fill_rule,
-				       path->tolerance,
-				       path->antialias);
-}
-
-cairo_status_t
-_cairo_clip_apply_clip (cairo_clip_t *clip,
-			const cairo_clip_t *other)
-{
-    cairo_status_t status;
+    cairo_operator_t op;
+    cairo_composite_rectangles_t rects;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
-    if (other->all_clipped) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_STATUS_SUCCESS;
+    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+			       CAIRO_CONTENT_COLOR);
+
+    /* If we have a clip surface we're going to use IN to combine our
+     * new clip with the old clip.  The ADD is done to a transparent
+     * surface, as that's a fast way of doing it currently.  We should
+     * really be using SOURCE instead, but _cairo_surface_composite()
+     * checks that it's not called with SOURCE or DEST. */
+    op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;
+
+    /* Test if the target can composite spans.  We're going to assume
+     * this is a good indicator of whether a similar surface is going
+     * to be able to composite spans too. */
+    if ( !_cairo_surface_check_span_renderer (op,
+					      &pattern.base,
+					      target,
+					      antialias,
+					      NULL))
+    {
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	goto BAIL;
+    }
+
+    status = _cairo_surface_get_extents (target, &surface_rect);
+    if (status)
+	goto BAIL;
+
+    /* We'll create a new surface the size of the intersection of the
+     * old mask surface and the extents of the new clip path. */
+    {
+	cairo_rectangle_int_t extents;
+
+	_cairo_path_fixed_approximate_clip_extents (path, &extents);
+	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
+	    goto SUCCESS;
+
+	if (clip->surface != NULL &&
+	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+	    goto SUCCESS;
+    }
+
+    /* Make the new mask surface and optionally initialise it from the
+     * previous clip if we have one. */
+    surface = _cairo_surface_create_similar_solid (target,
+						   CAIRO_CONTENT_ALPHA,
+						   surface_rect.width,
+						   surface_rect.height,
+						   CAIRO_COLOR_TRANSPARENT);
+    if (surface->status) {
+	_cairo_pattern_fini (&pattern.base);
+	return surface->status;
     }
 
-    status = CAIRO_STATUS_SUCCESS;
-    if (other->path != NULL)
-	status = _cairo_clip_apply_clip_path (clip, other->path);
+    if (clip->surface) {
+	cairo_surface_pattern_t old_clip;
+	_cairo_pattern_init_for_surface (&old_clip, clip->surface);
+	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+					   &old_clip.base,
+					   NULL,
+					   surface,
+					   surface_rect.x - clip->surface_rect.x,
+					   surface_rect.y - clip->surface_rect.y,
+					   0, 0,
+					   0, 0,
+					   surface_rect.width,
+					   surface_rect.height);
+	_cairo_pattern_fini (&old_clip.base);
+	if (status)
+	    goto BAIL;
+    }
+
+    _cairo_composite_rectangles_init (&rects,
+				      surface_rect.x,
+				      surface_rect.y,
+				      surface_rect.width,
+				      surface_rect.height);
+    rects.dst.x = 0;
+    rects.dst.y = 0;
 
+    /* Render the new clipping path into the new mask surface. We've
+     * chosen op to either combine the new clip path with the existing
+     * clip mask (if there is one) or just render it. */
+    status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
+						path, surface,
+						fill_rule, tolerance,
+						antialias, &rects);
+    if (status)
+	goto BAIL;
+
+ SUCCESS:
+    if (clip->surface != NULL)
+	cairo_surface_destroy (clip->surface);
+    clip->surface = surface;
+    clip->surface_rect = surface_rect;
+    clip->serial = _cairo_surface_allocate_clip_serial (target);
+    surface = NULL;
+
+    if (surface_rect.width == 0 || surface_rect.height == 0)
+	_cairo_clip_set_all_clipped (clip, target);
+
+ BAIL:
+    if (renderer)
+	renderer->destroy(renderer);
+    if (surface)
+	cairo_surface_destroy (surface);
+    _cairo_pattern_fini (&pattern.base);
     return status;
 }
 
-static inline cairo_bool_t
-_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
+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)
 {
-    while (clip_path != NULL) {
-	if (! clip_path->path.is_rectilinear)
-	    return FALSE;
-
-	clip_path = clip_path->prev;
-    }
-
-    return TRUE;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
-{
+    cairo_status_t status;
+    cairo_rectangle_int_t limits, extents;
     cairo_traps_t traps;
-    cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)];
-    cairo_box_t *boxes = stack_boxes;
-    cairo_status_t status;
-    int n;
-
-    /* If we have nothing to intersect with this path, then it cannot
-     * magically be reduced into a region.
-     */
-    if (clip_path->prev == NULL)
-	goto UNSUPPORTED;
+    cairo_box_t ignored_box;
+    cairo_bool_t have_limits;
 
-    /* Start simple... Intersect some boxes with an arbitrary path. */
-    if (! clip_path->path.is_rectilinear)
-	goto UNSUPPORTED;
-    if (clip_path->prev->prev != NULL)
-	goto UNSUPPORTED;
-
-    _cairo_traps_init (&traps);
-    _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
-    _cairo_traps_limit (&traps, boxes, 1);
+    if (clip->all_clipped)
+	return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path,
-							  clip_path->fill_rule,
-							  &traps);
-    if (unlikely (_cairo_status_is_error (status)))
-	return status;
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	goto UNSUPPORTED;
-
-    if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) {
-	boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
-	if (unlikely (boxes == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    for (n = 0; n < traps.num_traps; n++) {
-	boxes[n].p1.x = traps.traps[n].left.p1.x;
-	boxes[n].p1.y = traps.traps[n].top;
-	boxes[n].p2.x = traps.traps[n].right.p1.x;
-	boxes[n].p2.y = traps.traps[n].bottom;
+    /* catch the empty clip path */
+    if (! path->has_current_point) {
+	_cairo_clip_set_all_clipped (clip, target);
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_traps_clear (&traps);
-    _cairo_traps_limit (&traps, boxes, n);
-    status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
-					      clip_path->prev->fill_rule,
-					      clip_path->prev->tolerance,
-					      &traps);
-    if (boxes != stack_boxes)
-	free (boxes);
+    status = _cairo_clip_intersect_path (clip,
+					 path, fill_rule, tolerance,
+					 antialias);
+    if (status == CAIRO_STATUS_SUCCESS)
+        clip->serial = _cairo_surface_allocate_clip_serial (target);
 
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_traps_extract_region (&traps, &clip_path->region);
-    _cairo_traps_fini (&traps);
-
-    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-	goto UNSUPPORTED;
-    if (unlikely (status))
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
-    return CAIRO_STATUS_SUCCESS;
-
-UNSUPPORTED:
-    clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
-    return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
-{
-    cairo_int_status_t status;
-    cairo_region_t *prev = NULL;
-
-    if (clip_path->flags &
-	(CAIRO_CLIP_PATH_HAS_REGION |
-	 CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED))
+    /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter
+     * again. */
+    if (antialias != CAIRO_ANTIALIAS_NONE &&
+	!_cairo_path_fixed_is_box (path, &ignored_box) &&
+	!_cairo_path_fixed_is_region (path))
     {
-	return clip_path->flags & CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED ?
-	    CAIRO_INT_STATUS_UNSUPPORTED :
-	    CAIRO_STATUS_SUCCESS;
-    }
-
-    if (! clip_path->path.maybe_fill_region)
-	return _cairo_clip_path_to_region_geometric (clip_path);
-
-    /* first retrieve the region for our antecedents */
-    if (clip_path->prev != NULL) {
-	status = _cairo_clip_path_to_region (clip_path->prev);
-	if (status) {
-	    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-		return _cairo_clip_path_to_region_geometric (clip_path);
-
-	    return status;
-	}
-
-	prev = clip_path->prev->region;
-    }
-
-    /* now extract the region for ourselves */
-    clip_path->region =
-	_cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path,
-						      clip_path->fill_rule,
-						      &clip_path->extents);
-    assert (clip_path->region != NULL);
-
-    status = clip_path->region->status;
-    if (unlikely (status))
-	return status;
-
-    if (prev != NULL) {
-	status = cairo_region_intersect (clip_path->region, prev);
-	if (unlikely (status))
+	status = _cairo_clip_intersect_mask_using_spans (
+	    clip, path, fill_rule, tolerance, antialias, target);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	    return status;
     }
 
-    clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static inline int
-pot (int v)
-{
-    v--;
-    v |= v >> 1;
-    v |= v >> 2;
-    v |= v >> 4;
-    v |= v >> 8;
-    v |= v >> 16;
-    v++;
-    return v;
-}
-
-/* XXX there is likely a faster method! ;-) */
-static cairo_status_t
-_region_clip_to_boxes (const cairo_region_t *region,
-		       cairo_box_t **boxes,
-		       int *num_boxes,
-		       int *size_boxes)
-{
-    cairo_traps_t traps;
-    cairo_status_t status;
-    int n, num_rects;
-
     _cairo_traps_init (&traps);
-    _cairo_traps_limit (&traps, *boxes, *num_boxes);
-    traps.is_rectilinear = TRUE;
-    traps.is_rectangular = TRUE;
 
-    num_rects = cairo_region_num_rectangles (region);
-    for (n = 0; n < num_rects; n++) {
-	cairo_rectangle_int_t rect;
-	cairo_point_t p1, p2;
-
-	cairo_region_get_rectangle (region, n, &rect);
-
-	p1.x = _cairo_fixed_from_int (rect.x);
-	p1.y = _cairo_fixed_from_int (rect.y);
-	p2.x = _cairo_fixed_from_int (rect.x + rect.width);
-	p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-
-	status = _cairo_traps_tessellate_rectangle (&traps, &p1, &p2);
-	if (unlikely (status))
-	    goto CLEANUP;
-    }
-
-    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps, CAIRO_FILL_RULE_WINDING);
-    if (unlikely (status))
-	goto CLEANUP;
-
-    n = *size_boxes;
-    if (n < 0)
-	n = -n;
-
-    if (traps.num_traps > n) {
-	cairo_box_t *new_boxes;
-
-	new_boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
-	if (unlikely (new_boxes == NULL)) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto CLEANUP;
-	}
-
-	if (*size_boxes > 0)
-	    free (*boxes);
-
-	*boxes = new_boxes;
-	*size_boxes = traps.num_traps;
+    /* Limit the traps to the target surface and current clip
+     * - so we don't add more traps than needed. */
+    have_limits = FALSE;
+    if (clip->region != NULL) {
+	cairo_region_get_extents (clip->region, &limits);
+	have_limits = TRUE;
     }
 
-    for (n = 0; n < traps.num_traps; n++) {
-	(*boxes)[n].p1.x = traps.traps[n].left.p1.x;
-	(*boxes)[n].p1.y = traps.traps[n].top;
-	(*boxes)[n].p2.x = traps.traps[n].right.p1.x;
-	(*boxes)[n].p2.y = traps.traps[n].bottom;
-    }
-    *num_boxes = n;
-
-  CLEANUP:
-    _cairo_traps_fini (&traps);
-
-    return status;
-}
-
-static cairo_status_t
-_rectilinear_clip_to_boxes (const cairo_path_fixed_t *path,
-			    cairo_fill_rule_t fill_rule,
-			    cairo_box_t **boxes,
-			    int *num_boxes,
-			    int *size_boxes)
-{
-    cairo_polygon_t polygon;
-    cairo_traps_t traps;
-    cairo_status_t status;
-
-    _cairo_traps_init (&traps);
-    _cairo_traps_limit (&traps, *boxes, *num_boxes);
-
-    _cairo_polygon_init (&polygon);
-    _cairo_polygon_limit (&polygon, *boxes, *num_boxes);
-
-    status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
-							  fill_rule,
-							  &traps);
-    if (unlikely (_cairo_status_is_error (status)))
-	goto CLEANUP;
-    if (status == CAIRO_STATUS_SUCCESS)
-	goto BOXES;
-
-    /* tolerance will be ignored as the path is rectilinear */
-    status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
-    if (unlikely (status))
-	goto CLEANUP;
-
-    if (polygon.num_edges == 0) {
-	*num_boxes = 0;
-    } else {
-	status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
-									&polygon,
-									fill_rule);
-	if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	    int i;
-
-          BOXES:
-	    i = *size_boxes;
-	    if (i < 0)
-		i = -i;
-
-	    if (traps.num_traps > i) {
-		cairo_box_t *new_boxes;
-		int new_size;
-
-		new_size = pot (traps.num_traps);
-		new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t));
-		if (unlikely (new_boxes == NULL)) {
-		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-		    goto CLEANUP;
-		}
-
-		if (*size_boxes > 0)
-		    free (*boxes);
-
-		*boxes = new_boxes;
-		*size_boxes = new_size;
+    if (clip->surface != NULL) {
+	if (have_limits) {
+	    if (! _cairo_rectangle_intersect (&limits, &clip->surface_rect)) {
+		_cairo_clip_set_all_clipped (clip, target);
+		return CAIRO_STATUS_SUCCESS;
 	    }
-
-	    for (i = 0; i < traps.num_traps; i++) {
-		(*boxes)[i].p1.x = traps.traps[i].left.p1.x;
-		(*boxes)[i].p1.y = traps.traps[i].top;
-		(*boxes)[i].p2.x = traps.traps[i].right.p1.x;
-		(*boxes)[i].p2.y = traps.traps[i].bottom;
-	    }
-	    *num_boxes = i;
+	} else {
+	    limits = clip->surface_rect;
+	    have_limits = TRUE;
 	}
     }
 
-  CLEANUP:
-    _cairo_polygon_fini (&polygon);
+    status = _cairo_surface_get_extents (target, &extents);
+    if (status == CAIRO_STATUS_SUCCESS) {
+	if (have_limits) {
+	    if (! _cairo_rectangle_intersect (&limits, &extents)) {
+		_cairo_clip_set_all_clipped (clip, target);
+		return CAIRO_STATUS_SUCCESS;
+	    }
+	} else {
+	    limits = extents;
+	    have_limits = TRUE;
+	}
+    }
+
+    if (have_limits) {
+	cairo_box_t box;
+
+	_cairo_box_from_rectangle (&box, &limits);
+	_cairo_traps_limit (&traps, &box);
+    }
+
+    status = _cairo_path_fixed_fill_to_traps (path,
+					      fill_rule,
+					      tolerance,
+					      &traps);
+    if (unlikely (status))
+	goto bail;
+
+    status = _cairo_clip_intersect_region (clip, &traps, target);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	goto bail;
+
+    status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);
+
+ bail:
     _cairo_traps_fini (&traps);
 
     return status;
 }
 
-static cairo_int_status_t
-_cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
-			   cairo_box_t **boxes,
-			   int *count)
+void
+_cairo_clip_translate (cairo_clip_t  *clip,
+                       cairo_fixed_t  tx,
+                       cairo_fixed_t  ty)
 {
-    int size = -*count;
-    int num_boxes = 0;
-    cairo_status_t status;
-
-    if (clip_path->region != NULL) {
-	int num_rects, n;
-
-	num_rects = cairo_region_num_rectangles (clip_path->region);
-	if (num_rects > -size) {
-	    cairo_box_t *new_boxes;
+    if (clip->all_clipped)
+	return;
 
-	    new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t));
-	    if (unlikely (new_boxes == NULL))
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	    *boxes = new_boxes;
-	}
-
-	for (n = 0; n < num_rects; n++) {
-	    cairo_rectangle_int_t rect;
-
-	    cairo_region_get_rectangle (clip_path->region, n, &rect);
-	    (*boxes)[n].p1.x = _cairo_fixed_from_int (rect.x);
-	    (*boxes)[n].p1.y = _cairo_fixed_from_int (rect.y);
-	    (*boxes)[n].p2.x = _cairo_fixed_from_int (rect.x + rect.width);
-	    (*boxes)[n].p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-	}
-
-	*count = num_rects;
-	return CAIRO_STATUS_SUCCESS;
+    if (clip->region) {
+        cairo_region_translate (clip->region,
+				_cairo_fixed_integer_part (tx),
+				_cairo_fixed_integer_part (ty));
     }
 
-    /* keep it simple at first */
-    if (! _clip_paths_are_rectilinear (clip_path))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    assert (-size >= 1);
-    if (_cairo_path_fixed_is_box (&clip_path->path, *boxes)) {
-	num_boxes = 1;
-    } else {
-	status = _rectilinear_clip_to_boxes (&clip_path->path,
-					     clip_path->fill_rule,
-					     boxes, &num_boxes, &size);
-	if (unlikely (status))
-	    return status;
+    if (clip->surface) {
+        clip->surface_rect.x += _cairo_fixed_integer_part (tx);
+        clip->surface_rect.y += _cairo_fixed_integer_part (ty);
     }
 
-    while (num_boxes > 0 && (clip_path = clip_path->prev) != NULL) {
-	cairo_box_t box;
-
-	if (clip_path->region != NULL) {
-	    status = _region_clip_to_boxes (clip_path->region,
-					    boxes, &num_boxes, &size);
-	    if (unlikely (status))
-		return status;
-
-	    break;
-	} else if (_cairo_path_fixed_is_box (&clip_path->path, &box)) {
-	    int i, j;
-
-	    for (i = j = 0; i < num_boxes; i++) {
-		if (j != i)
-		    (*boxes)[j] = (*boxes)[i];
-
-		if (box.p1.x > (*boxes)[j].p1.x)
-		    (*boxes)[j].p1.x = box.p1.x;
-		if (box.p2.x < (*boxes)[j].p2.x)
-		    (*boxes)[j].p2.x = box.p2.x;
+    if (clip->path) {
+        cairo_clip_path_t *clip_path = clip->path;
+	cairo_matrix_t matrix;
 
-		if (box.p1.y > (*boxes)[j].p1.y)
-		    (*boxes)[j].p1.y = box.p1.y;
-		if (box.p2.y < (*boxes)[j].p2.y)
-		    (*boxes)[j].p2.y = box.p2.y;
-
-		j += (*boxes)[j].p2.x > (*boxes)[j].p1.x &&
-		     (*boxes)[j].p2.y > (*boxes)[j].p1.y;
-	    }
+	cairo_matrix_init_translate (&matrix,
+				     _cairo_fixed_to_double (tx),
+				     _cairo_fixed_to_double (ty));
 
-	    num_boxes = j;
-	} else {
-	    status = _rectilinear_clip_to_boxes (&clip_path->path,
-						 clip_path->fill_rule,
-						 boxes, &num_boxes, &size);
-	    if (unlikely (status))
-		return status;
-	}
+        while (clip_path) {
+            _cairo_path_fixed_transform (&clip_path->path, &matrix);
+            clip_path = clip_path->prev;
+        }
     }
-
-    *count = num_boxes;
-    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_combine_region (cairo_surface_t *surface,
-		 const cairo_region_t *region,
-		 const cairo_rectangle_int_t *extents)
+_cairo_clip_path_reapply_clip_path (cairo_clip_t      *clip,
+                                    cairo_clip_path_t *clip_path)
 {
-    cairo_region_t clear_region;
     cairo_status_t status;
 
-    _cairo_region_init_rectangle (&clear_region, extents);
-    status = cairo_region_subtract (&clear_region, region);
-    if (unlikely (status))
-	return status;
-
-    if (! cairo_region_is_empty (&clear_region)) {
-	cairo_region_translate (&clear_region, -extents->x, -extents->y);
-	status = _cairo_surface_fill_region (surface,
-					     CAIRO_OPERATOR_CLEAR,
-					     CAIRO_COLOR_TRANSPARENT,
-					     &clear_region);
-    }
-    _cairo_region_fini (&clear_region);
-
-    return status;
-}
-
-static cairo_surface_t *
-_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
-			      cairo_surface_t *target)
-{
-    cairo_surface_t *surface;
-    cairo_pattern_union_t pattern;
-    cairo_status_t status;
-    const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
-    cairo_clip_path_t *prev;
-    cairo_bool_t need_translate;
-
-    if (clip_path->surface != NULL &&
-	clip_path->surface->backend == target->backend)
-    {
-	return cairo_surface_reference (clip_path->surface);
+    if (clip_path->prev) {
+        status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev);
+	if (_cairo_status_is_error (status))
+	    return status;
     }
 
-    surface = _cairo_surface_create_similar_solid (target,
-						   CAIRO_CONTENT_ALPHA,
-						   clip_extents->width,
-						   clip_extents->height,
-						   CAIRO_COLOR_TRANSPARENT,
-						   FALSE);
-    if (surface == NULL) {
-	if (clip_path->surface != NULL &&
-	    clip_path->surface->backend == &_cairo_image_surface_backend)
-	{
-	    return cairo_surface_reference (clip_path->surface);
-	}
-
-	surface =
-	    _cairo_image_surface_create_with_content (CAIRO_CONTENT_ALPHA,
-						      clip_extents->width,
-						      clip_extents->height);
-    }
-    if (unlikely (surface->status))
-	return surface;
+    return _cairo_clip_intersect_path (clip,
+                                       &clip_path->path,
+				       clip_path->fill_rule,
+				       clip_path->tolerance,
+				       clip_path->antialias);
+}
 
-    _cairo_pattern_init_solid (&pattern.solid,
-			       CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
-
-    status = _cairo_clip_path_to_region (clip_path);
-    if (unlikely (_cairo_status_is_error (status)))
-	goto BAIL;
+cairo_status_t
+_cairo_clip_init_deep_copy (cairo_clip_t    *clip,
+                            cairo_clip_t    *other,
+                            cairo_surface_t *target)
+{
+    cairo_status_t status;
 
-    need_translate = clip_extents->x | clip_extents->y;
-    if (status == CAIRO_STATUS_SUCCESS) {
-	if (need_translate) {
-	    cairo_region_translate (clip_path->region,
-				    -clip_extents->x, -clip_extents->y);
-	}
-	status = _cairo_surface_fill_region (surface,
-					     CAIRO_OPERATOR_SOURCE,
-					     CAIRO_COLOR_WHITE,
-					     clip_path->region);
-	if (need_translate) {
-	    cairo_region_translate (clip_path->region,
-				    clip_extents->x, clip_extents->y);
-	}
-	if (unlikely (status))
-	    goto BAIL;
+    _cairo_clip_init (clip, target);
 
-	goto DONE;
+    if (other->mode != clip->mode) {
+        /* We should reapply the original clip path in this case, and let
+         * whatever the right handling is happen */
     } else {
-	if (need_translate) {
-	    _cairo_path_fixed_translate (&clip_path->path,
-					 _cairo_fixed_from_int (-clip_extents->x),
-					 _cairo_fixed_from_int (-clip_extents->y));
-	}
-	status = _cairo_surface_fill (surface,
-				      CAIRO_OPERATOR_OVER,
-				      &pattern.base,
-				      &clip_path->path,
-				      clip_path->fill_rule,
-				      clip_path->tolerance,
-				      clip_path->antialias,
-				      NULL);
-	if (need_translate) {
-	    _cairo_path_fixed_translate (&clip_path->path,
-					 _cairo_fixed_from_int (clip_extents->x),
-					 _cairo_fixed_from_int (clip_extents->y));
-	}
-
-	if (unlikely (status))
-	    goto BAIL;
-    }
+        if (other->region) {
+	    clip->region = cairo_region_copy (other->region);
+	    if (unlikely ((status = cairo_region_status (clip->region))))
+		goto BAIL;
+        }
 
-    prev = clip_path->prev;
-  NEXT_PATH:
-    if (prev != NULL) {
-	status = _cairo_clip_path_to_region (prev);
-	if (unlikely (_cairo_status_is_error (status)))
-	    goto BAIL;
-
-	if (status == CAIRO_STATUS_SUCCESS) {
-	    status = _combine_region (surface, prev->region, clip_extents);
-	    if (unlikely (status))
-		goto BAIL;
-	} else if (prev->flags & CAIRO_CLIP_PATH_IS_BOX) {
-	    /* a simple box only affects the extents */
-	} else if (prev->path.is_rectilinear) {
-	    if (need_translate) {
-		_cairo_path_fixed_translate (&prev->path,
-					     _cairo_fixed_from_int (-clip_extents->x),
-					     _cairo_fixed_from_int (-clip_extents->y));
-	    }
-	    status = _cairo_surface_fill (surface,
-					  CAIRO_OPERATOR_IN,
-					  &pattern.base,
-					  &prev->path,
-					  prev->fill_rule,
-					  prev->tolerance,
-					  prev->antialias,
-					  NULL);
-	    if (need_translate) {
-		_cairo_path_fixed_translate (&prev->path,
-					     _cairo_fixed_from_int (clip_extents->x),
-					     _cairo_fixed_from_int (clip_extents->y));
-	    }
-
+        if (other->surface) {
+	    int dx, dy;
+            status = _cairo_surface_clone_similar (target, other->surface,
+						   CAIRO_CONTENT_ALPHA,
+					           0,
+						   0,
+						   other->surface_rect.width,
+						   other->surface_rect.height,
+						   &dx, &dy,
+						   &clip->surface);
 	    if (unlikely (status))
 		goto BAIL;
 
-	    prev = prev->prev;
-	    goto NEXT_PATH;
-	} else {
-	    cairo_surface_t *prev_surface;
-
-	    prev_surface = _cairo_clip_path_get_surface (prev, target);
-	    _cairo_pattern_init_for_surface (&pattern.surface, prev_surface);
-	    cairo_surface_destroy (prev_surface);
-
-	    cairo_matrix_init_translate (&pattern.base.matrix,
-					 -prev->extents.x + clip_extents->x,
-					 -prev->extents.y + clip_extents->y);
-	    status = _cairo_surface_paint (surface,
-					   CAIRO_OPERATOR_IN,
-					   &pattern.base,
-					   NULL);
-	    _cairo_pattern_fini (&pattern.base);
-
-	    if (unlikely (status))
-		goto BAIL;
-	}
-    }
+            clip->surface_rect = other->surface_rect;
 
-  DONE:
-    cairo_surface_destroy (clip_path->surface);
-    return clip_path->surface = cairo_surface_reference (surface);
-
-  BAIL:
-    cairo_surface_destroy (surface);
-    return _cairo_surface_create_in_error (status);
-}
-
-void
-_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
-{
-    cairo_clip_path_t *clip_path;
+	    /* src offset was 0, so we expect an exact replica of the surface */
+	    assert (dx == 0);
+	    assert (dy == 0);
+        }
 
-    if (clip == NULL) {
-	fprintf (stream, "no clip\n");
-	return;
-    }
-
-    if (clip->all_clipped) {
-	fprintf (stream, "clip: all-clipped\n");
-	return;
-    }
-
-    if (clip->path == NULL) {
-	fprintf (stream, "clip: empty\n");
-	return;
+        if (other->path) {
+            status = _cairo_clip_path_reapply_clip_path (clip, other->path);
+	    if (_cairo_status_is_error (status))
+		goto BAIL;
+        }
     }
 
-    fprintf (stream, "clip:\n");
-
-    clip_path = clip->path;
-    do {
-	fprintf (stream, "path: has region? %s, has surface? %s: ",
-		 clip_path->region == NULL ? "no" : "yes",
-		 clip_path->surface == NULL ? "no" : "yes");
-	_cairo_debug_print_path (stream, &clip_path->path);
-	fprintf (stream, "\n");
-    } while ((clip_path = clip_path->prev) != NULL);
-}
-
-cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
-{
-    assert (clip->path != NULL);
-    return _cairo_clip_path_get_surface (clip->path, target);
-}
-
-cairo_status_t
-_cairo_clip_combine_with_surface (cairo_clip_t *clip,
-				  cairo_surface_t *dst,
-				  const cairo_rectangle_int_t *extents)
-{
-    cairo_pattern_union_t pattern;
-    cairo_clip_path_t *clip_path = clip->path;
-    cairo_bool_t need_translate;
-    cairo_status_t status;
-
-    assert (clip_path != NULL);
-
-    if (clip_path->surface != NULL &&
-	clip_path->surface->backend == dst->backend)
-    {
-	_cairo_pattern_init_for_surface (&pattern.surface,
-					 clip_path->surface);
-	cairo_matrix_init_translate (&pattern.base.matrix,
-				     extents->x - clip_path->extents.x,
-				     extents->y - clip_path->extents.y);
-	status = _cairo_surface_paint (dst,
-				       CAIRO_OPERATOR_IN,
-				       &pattern.base,
-				       NULL);
-
-	_cairo_pattern_fini (&pattern.base);
-
-	return status;
-    }
-
-    _cairo_pattern_init_solid (&pattern.solid,
-			       CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
-
-    need_translate = extents->x | extents->y;
-    do {
-	status = _cairo_clip_path_to_region (clip_path);
-	if (unlikely (_cairo_status_is_error (status)))
-	    return status;
-
-	if (status == CAIRO_STATUS_SUCCESS)
-	    return _combine_region (dst, clip_path->region, extents);
+    return CAIRO_STATUS_SUCCESS;
 
-	if (clip_path->surface != NULL &&
-	    clip_path->surface->backend == dst->backend)
-	{
-	    _cairo_pattern_init_for_surface (&pattern.surface,
-					     clip_path->surface);
-	    cairo_matrix_init_translate (&pattern.base.matrix,
-					 extents->x - clip_path->extents.x,
-					 extents->y - clip_path->extents.y);
-	    status = _cairo_surface_paint (dst,
-					   CAIRO_OPERATOR_IN,
-					   &pattern.base,
-					   NULL);
-
-	    _cairo_pattern_fini (&pattern.base);
-
-	    return status;
-	}
-
-	if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) {
-	    cairo_region_t clip_region;
+BAIL:
+    if (clip->region)
+	cairo_region_destroy (clip->region);
+    if (clip->surface)
+	cairo_surface_destroy (clip->surface);
 
-	    _cairo_region_init_rectangle (&clip_region, &clip_path->extents);
-	    status = _combine_region (dst, &clip_region, extents);
-	} else {
-	    if (need_translate) {
-		_cairo_path_fixed_translate (&clip_path->path,
-					     _cairo_fixed_from_int (-extents->x),
-					     _cairo_fixed_from_int (-extents->y));
-	    }
-	    status = _cairo_surface_fill (dst,
-					  CAIRO_OPERATOR_IN,
-					  &pattern.base,
-					  &clip_path->path,
-					  clip_path->fill_rule,
-					  clip_path->tolerance,
-					  clip_path->antialias,
-					  NULL);
-	    if (need_translate) {
-		_cairo_path_fixed_translate (&clip_path->path,
-					     _cairo_fixed_from_int (extents->x),
-					     _cairo_fixed_from_int (extents->y));
-	    }
-	}
-
-	if (unlikely (status))
-	    return status;
-    } while ((clip_path = clip_path->prev) != NULL);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-const cairo_rectangle_int_t *
-_cairo_clip_get_extents (const cairo_clip_t *clip)
-{
-    if (clip->path == NULL)
-	return NULL;
-
-    return &clip->path->extents;
-}
-
-void
-_cairo_clip_drop_cache (cairo_clip_t  *clip)
-{
-    cairo_clip_path_t *clip_path;
-
-    if (clip->path == NULL)
-	return;
-
-    clip_path = clip->path;
-    do {
-	if (clip_path->region != NULL) {
-	    cairo_region_destroy (clip_path->region);
-	    clip_path->region = NULL;
-	}
-
-	if (clip_path->surface != NULL) {
-	    cairo_surface_destroy (clip_path->surface);
-	    clip_path->surface = NULL;
-	}
-
-	clip_path->flags &= ~CAIRO_CLIP_PATH_HAS_REGION;
-    } while ((clip_path = clip_path->prev) != NULL);
+    return status;
 }
 
 const cairo_rectangle_list_t _cairo_rectangles_nil =
   { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
 static const cairo_rectangle_list_t _cairo_rectangles_not_representable =
   { CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 };
 
 static cairo_bool_t
@@ -1368,172 +857,87 @@ static cairo_bool_t
     user_rect->x = x1;
     user_rect->y = y1;
     user_rect->width  = x2 - x1;
     user_rect->height = y2 - y1;
 
     return is_tight;
 }
 
-cairo_int_status_t
-_cairo_clip_get_region (cairo_clip_t *clip,
-			cairo_region_t **region)
-{
-    cairo_int_status_t status;
-
-    if (clip->all_clipped)
-	goto CLIPPED;
-
-    assert (clip->path != NULL);
-
-    status = _cairo_clip_path_to_region (clip->path);
-    if (status)
-	return status;
-
-    if (cairo_region_is_empty (clip->path->region)) {
-	_cairo_clip_set_all_clipped (clip);
-	goto CLIPPED;
-    }
-
-    if (region)
-	*region = clip->path->region;
-    return CAIRO_STATUS_SUCCESS;
-
-  CLIPPED:
-    if (region)
-	*region = NULL;
-    return CAIRO_INT_STATUS_NOTHING_TO_DO;
-}
-
-cairo_int_status_t
-_cairo_clip_get_boxes (cairo_clip_t *clip,
-		       cairo_box_t **boxes,
-		       int *count)
-{
-    cairo_int_status_t status;
-
-    if (clip->all_clipped)
-	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
-    assert (clip->path != NULL);
-
-    status = _cairo_clip_path_to_boxes (clip->path, boxes, count);
-    if (status)
-	return status;
-
-    if (*count == 0) {
-	_cairo_clip_set_all_clipped (clip);
-	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_rectangle_list_t *
-_cairo_rectangle_list_create_in_error (cairo_status_t status)
-{
-    cairo_rectangle_list_t *list;
-
-    if (status == CAIRO_STATUS_NO_MEMORY)
-	return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
-    if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
-	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
-
-    list = malloc (sizeof (*list));
-    if (unlikely (list == NULL)) {
-	_cairo_error_throw (status);
-	return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
-    }
-
-    list->status = status;
-    list->rectangles = NULL;
-    list->num_rectangles = 0;
-
-    return list;
-}
-
 cairo_rectangle_list_t *
 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 {
-#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S));
-
     cairo_rectangle_list_t *list;
     cairo_rectangle_t *rectangles = NULL;
-    cairo_region_t *region = NULL;
-    cairo_int_status_t status;
     int n_rects = 0;
-    int i;
 
-    if (clip != NULL && clip->path != NULL) {
-	status = _cairo_clip_get_region (clip, &region);
-	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
-	    goto DONE;
-	} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
-	} else if (unlikely (status)) {
-	    return ERROR_LIST (status);
-	}
+    if (clip->all_clipped)
+	goto DONE;
+
+    if (clip->path || clip->surface) {
+	_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
     }
 
-    if (region != NULL) {
-	n_rects = cairo_region_num_rectangles (region);
+    if (clip->region) {
+        int i;
+
+	n_rects = cairo_region_num_rectangles (clip->region);
+
 	if (n_rects) {
 	    rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
 	    if (unlikely (rectangles == NULL)) {
-		return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
+		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+		return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
 	    }
 
 	    for (i = 0; i < n_rects; ++i) {
 		cairo_rectangle_int_t clip_rect;
 
-		cairo_region_get_rectangle (region, i, &clip_rect);
-
-		if (! _cairo_clip_int_rect_to_user (gstate,
-						    &clip_rect,
-						    &rectangles[i]))
-		{
+		cairo_region_get_rectangle (clip->region, i, &clip_rect);
+		
+		if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
+		    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 		    free (rectangles);
-		    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+		    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 		}
 	    }
 	}
     } else {
         cairo_rectangle_int_t extents;
 
-	if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
-					  &extents))
-	{
-	    /* unbounded surface -> unclipped */
-	    goto DONE;
+	n_rects = 1;
+
+	rectangles = malloc(sizeof (cairo_rectangle_t));
+	if (unlikely (rectangles == NULL)) {
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
 	}
 
-	n_rects = 1;
-	rectangles = malloc(sizeof (cairo_rectangle_t));
-	if (unlikely (rectangles == NULL))
-	    return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
-
-	if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) {
+	if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) ||
+	    !_cairo_clip_int_rect_to_user(gstate, &extents, rectangles))
+	{
+	    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 	    free (rectangles);
-	    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+	    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 	}
     }
 
  DONE:
     list = malloc (sizeof (cairo_rectangle_list_t));
     if (unlikely (list == NULL)) {
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         free (rectangles);
-	return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
+        return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
     }
 
     list->status = CAIRO_STATUS_SUCCESS;
     list->rectangles = rectangles;
     list->num_rectangles = n_rects;
     return list;
-
-#undef ERROR_LIST
 }
 
 /**
  * cairo_rectangle_list_destroy:
  * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles()
  *
  * Unconditionally frees @rectangle_list and all associated
  * references. After this call, the @rectangle_list pointer must not
@@ -1546,14 +950,8 @@ cairo_rectangle_list_destroy (cairo_rect
 {
     if (rectangle_list == NULL || rectangle_list == &_cairo_rectangles_nil ||
         rectangle_list == &_cairo_rectangles_not_representable)
         return;
 
     free (rectangle_list->rectangles);
     free (rectangle_list);
 }
-
-void
-_cairo_clip_reset_static_data (void)
-{
-    _freed_pool_reset (&clip_path_pool);
-}
--- a/gfx/cairo/cairo/src/cairo-combsort-private.h
+++ b/gfx/cairo/cairo/src/cairo-combsort-private.h
@@ -51,21 +51,21 @@ static inline unsigned int
 static void \
 NAME (TYPE *base, unsigned int nmemb) \
 { \
   unsigned int gap = nmemb; \
   unsigned int i, j; \
   int swapped; \
   do { \
       gap = _cairo_combsort_newgap (gap); \
-      swapped = gap > 1; \
+      swapped = 0; \
       for (i = 0; i < nmemb-gap ; i++) { \
 	  j = i + gap; \
 	  if (CMP (base[i], base[j]) > 0 ) { \
 	      TYPE tmp; \
 	      tmp = base[i]; \
 	      base[i] = base[j]; \
 	      base[j] = tmp; \
 	      swapped = 1; \
 	  } \
       } \
-  } while (swapped); \
+  } while (gap > 1 || swapped); \
 }
--- a/gfx/cairo/cairo/src/cairo-d2d-private.h
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.h
@@ -40,17 +40,16 @@
 
 #include <windows.h>
 #include <d2d1.h>
 #include <d3d10.h>
 #include <dxgi.h>
 
 extern "C" {
 #include "cairoint.h"
-#include "cairo-surface-clipper-private.h"
 }
 
 struct _cairo_d2d_surface {
     cairo_surface_t base;
     /** Render target of the texture we render to */
     ID2D1RenderTarget *rt;
     /** Surface containing our backstore */
     ID3D10Resource *surface;
@@ -87,18 +86,16 @@ struct _cairo_d2d_surface {
     /** Brush used for bitmaps */
     ID2D1BitmapBrush *bitmapBrush;
     /** Brush used for solid colors */
     ID2D1SolidColorBrush *solidColorBrush;
     /** Indicates if our render target is currently in drawing mode */
     bool isDrawing;
     /** Indicates if text rendering is initialized */
     bool textRenderingInit;
-
-    cairo_surface_clipper_t clipper;
 };
 typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
 
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     __in D2D1_FACTORY_TYPE factoryType,
     __in REFIID iid,
     __in_opt CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
     __out void **factory
@@ -215,13 +212,10 @@ private:
 
 ID2D1Brush*
 _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf, 
 			            const cairo_pattern_t *pattern,
 				    unsigned int lastrun,
 				    unsigned int *runs_remaining,
 				    bool *pushed_clip,
 				    bool unique = false);
-void
-_cairo_d2d_begin_draw_state(cairo_d2d_surface_t *d2dsurf);
-
 #endif /* CAIRO_HAS_D2D_SURFACE */
 #endif /* CAIRO_D2D_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -37,17 +37,16 @@
 
 #include "cairo.h"
 #include "cairo-d2d-private.h"
 #include "cairo-dwrite-private.h"
 
 extern "C" {
 #include "cairo-win32.h"
 #include "cairo-analysis-surface-private.h"
-#include "cairo-surface-clipper-private.h"
 }
 
 
 ID2D1Factory *D2DSurfFactory::mFactoryInstance = NULL;
 ID3D10Device1 *D3D10Factory::mDeviceInstance = NULL;
 
 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
 
@@ -155,111 +154,115 @@ static cairo_status_t
  * \param surface The surface to apply this operation to, must be
  * a D2D surface
  * \param op The operator to use
  * \param source The source pattern to fill this path with
  * \param path The path to fill
  * \param fill_rule The fill rule to uses on the path
  * \param tolerance The tolerance applied to the filling
  * \param antialias The anti-alias mode to use
- * \param clip The clip of this operation
+ * \param extents The extents of the surface to which to apply this operation
  * \return Return code, this can be CAIRO_ERROR_SURFACE_TYPE_MISMATCH,
  * CAIRO_INT_STATUS_UNSUPPORTED or CAIRO_STATUS_SUCCESS
  */
 static cairo_int_status_t
 _cairo_d2d_fill(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		cairo_path_fixed_t	*path,
 		cairo_fill_rule_t	 fill_rule,
 		double			 tolerance,
 		cairo_antialias_t	 antialias,
-		cairo_clip_t		*clip);
+		cairo_rectangle_int_t	*extents);
 
 /**
  * Paint this surface, applying the operation to the entire surface
+ * or to the passed in 'extents' of the surface.
  *
  * \param surface The surface to apply this operation to, must be
  * a D2D surface
  * \param op Operator to use when painting
  * \param source The pattern to fill this surface with, source of the op
- * \param clip The clip of this operation
+ * \param Extents of the surface to apply this operation to
  * \return Return code, this can be CAIRO_ERROR_SURFACE_TYPE_MISMATCH,
  * CAIRO_INT_STATUS_UNSUPPORTED or CAIRO_STATUS_SUCCESS
  */
 static cairo_int_status_t
 _cairo_d2d_paint(void			*surface,
 		 cairo_operator_t	 op,
 		 const cairo_pattern_t	*source,
-		 cairo_clip_t		*clip);
+		 cairo_rectangle_int_t  *extents);
 
 /**
  * Paint something on the surface applying a certain mask to that
  * source.
  *
  * \param surface The surface to apply this oepration to, must be
  * a D2D surface
  * \param op Operator to use
  * \param source Source for this operation
  * \param mask Pattern to mask source with
- * \param clip The clip of this operation
+ * \param extents Extents of the surface to apply this operation to
  * \return Return code, this can be CAIRO_ERROR_SURFACE_TYPE_MISMATCH,
  * CAIRO_INT_STATUS_UNSUPPORTED or CAIRO_STATUS_SUCCESS
  */
 static cairo_int_status_t
 _cairo_d2d_mask(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		const cairo_pattern_t	*mask,
-		cairo_clip_t		*clip);
+		cairo_rectangle_int_t  *extents);
 
 /**
  * Show a glyph run on the target D2D surface.
  *
  * \param surface The surface to apply this oepration to, must be
  * a D2D surface
  * \param op Operator to use
  * \param source Source for this operation
  * \param glyphs Glyphs to draw
  * \param num_gluphs Amount of glyphs stored at glyphs
  * \param scaled_font Scaled font to draw
  * \param remaining_glyphs Pointer to store amount of glyphs still
  * requiring drawing.
- * \param clip The clip of this operation
+ * \param extents Extents this operation applies to.
  * \return CAIRO_ERROR_SURFACE_TYPE_MISMATCH, CAIRO_ERROR_FONT_TYPE_MISMATCH,
  * CAIRO_INT_STATUS_UNSUPPORTED or CAIRO_STATUS_SUCCESS
  */
 static cairo_int_status_t
 _cairo_d2d_show_glyphs (void			*surface,
 			cairo_operator_t	 op,
 			const cairo_pattern_t	*source,
 			cairo_glyph_t		*glyphs,
 			int			 num_glyphs,
 			cairo_scaled_font_t	*scaled_font,
-			cairo_clip_t		*clip,
-			int			*remaining_glyphs);
+			int			*remaining_glyphs,
+			cairo_rectangle_int_t	*extents);
 
 /**
  * Get the extents of this surface.
  *
  * \param surface D2D surface to get the extents for
  * \param extents Pointer to where to store the extents
  * \param CAIRO_ERROR_SURFACE_TYPE_MISTMATCH or CAIRO_STATUS_SUCCESS
  */
-static cairo_bool_t
+static cairo_int_status_t
 _cairo_d2d_getextents(void		       *surface,
 		      cairo_rectangle_int_t    *extents);
 
 
-static cairo_status_t
-_cairo_d2d_surface_clipper_intersect_clip_path(cairo_surface_clipper_t *clipper,
-					       cairo_path_fixed_t	*path,
-					       cairo_fill_rule_t	fill_rule,
-					       double			tolerance,
-					       cairo_antialias_t	antialias);
+/**
+ * See cairo backend documentation.
+ */
+static cairo_int_status_t
+_cairo_d2d_intersect_clip_path(void			*dst,
+			       cairo_path_fixed_t	*path,
+			       cairo_fill_rule_t	fill_rule,
+			       double			tolerance,
+			       cairo_antialias_t	antialias);
 
 /**
  * Stroke a path on this D2D surface.
  *
  * \param surface The surface to apply this operation to, must be
  * a D2D surface
  * \param op The operator to use
  * \param source The source pattern to fill this path with
@@ -267,31 +270,31 @@ static cairo_status_t
  * \param style The style of the stroke
  * \param ctm A logical to device matrix, since the path might be in
  * device space the miter angle and such are not, hence we need to
  * be aware of the transformation to apply correct stroking.
  * \param ctm_inverse Inverse of ctm, used to transform the path back
  * to logical space.
  * \param tolerance Tolerance to stroke with
  * \param antialias Antialias mode to use
- * \param clip The clip of this operation
+ * \param extents Extents of the surface to apply this operation to
  * \return Return code, this can be CAIRO_ERROR_SURFACE_TYPE_MISMATCH,
  * CAIRO_INT_STATUS_UNSUPPORTED or CAIRO_STATUS_SUCCESS
  */
 static cairo_int_status_t
 _cairo_d2d_stroke(void			*surface,
 		  cairo_operator_t	 op,
 		  const cairo_pattern_t	*source,
 		  cairo_path_fixed_t	*path,
 		  cairo_stroke_style_t	*style,
 		  cairo_matrix_t	*ctm,
 		  cairo_matrix_t	*ctm_inverse,
 		  double		 tolerance,
 		  cairo_antialias_t	 antialias,
-		  cairo_clip_t		*clip);
+		  cairo_rectangle_int_t  *extents);
 
 static const cairo_surface_backend_t cairo_d2d_surface_backend = {
     CAIRO_SURFACE_TYPE_D2D,
     _cairo_d2d_create_similar, /* create_similar */
     _cairo_d2d_finish, /* finish */
     _cairo_d2d_acquire_source_image, /* acquire_source_image */
     _cairo_d2d_release_source_image, /* release_source_image */
     _cairo_d2d_acquire_dest_image, /* acquire_dest_image */
@@ -299,29 +302,32 @@ static const cairo_surface_backend_t cai
     NULL, /* clone_similar */
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
     NULL, /* create_span_renderer */
     NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
-    _cairo_d2d_getextents, /* get_extents */
+    NULL, /* set_clip_region */
+    _cairo_d2d_intersect_clip_path, /* intersect_clip_path */
+    _cairo_d2d_getextents, /* getextents */
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
     _cairo_d2d_flush, /* flush */
     NULL, /* mark_dirty_rectangle */
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
     _cairo_d2d_paint, /* paint */
     _cairo_d2d_mask, /* mask */
     _cairo_d2d_stroke, /* stroke */
     _cairo_d2d_fill, /* fill */
     _cairo_d2d_show_glyphs, /* show_glyphs */
     NULL, /* snapshot */
+    NULL,
     NULL
 };
 
 /*
  * Helper functions.
  */
 
 static D2D1_POINT_2F
@@ -491,25 +497,16 @@ static void _begin_draw_state(cairo_d2d_
 	surface->rt->BeginDraw();
 	surface->isDrawing = true;
     }
     if (!surface->clipping) {
 	_cairo_d2d_surface_push_clip(surface);
     }
 }
 
-/* External helper called from dwrite code.
- * Will hopefully go away when/if that code
- * moves into here */
-void
-_cairo_d2d_begin_draw_state(cairo_d2d_surface_t *d2dsurf)
-{
-	_begin_draw_state(d2dsurf);
-}
-
 /**
  * Get a D2D matrix from a cairo matrix. Note that D2D uses row vectors where cairo
  * uses column vectors. Hence the transposition.
  *
  * \param Cairo matrix
  * \return D2D matrix
  */
 static D2D1::Matrix3x2F
@@ -1283,17 +1280,16 @@ static cairo_surface_t*
 			  int			 height)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     
     memset(newSurf, 0, sizeof(cairo_d2d_surface_t));
 
     _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
-    _cairo_surface_clipper_init(&newSurf->clipper, _cairo_d2d_surface_clipper_intersect_clip_path);
 
     D2D1_SIZE_U sizePixels;
     D2D1_SIZE_F size;
     HRESULT hr;
 
     sizePixels.width = width;
     sizePixels.height = height;
     FLOAT dpiX;
@@ -1390,19 +1386,16 @@ FAIL_D3DTEXTURE:
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
 static cairo_status_t
 _cairo_d2d_finish(void	    *surface)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
-
-    _cairo_surface_clipper_reset (&d2dsurf->clipper);
-
     if (d2dsurf->rt) {
 	d2dsurf->rt->Release();
     }
     if (d2dsurf->surfaceBitmap) {
 	d2dsurf->surfaceBitmap->Release();
     }
     if (d2dsurf->backBuf) {
 	d2dsurf->backBuf->Release();
@@ -1432,17 +1425,16 @@ static cairo_status_t
 	d2dsurf->surface->Release();
     }
     if (d2dsurf->helperLayer) {
 	d2dsurf->helperLayer->Release();
     }
     if (d2dsurf->bufferTexture) {
 	d2dsurf->bufferTexture->Release();
     }
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_d2d_acquire_source_image(void                    *abstract_surface,
 				cairo_image_surface_t  **image_out,
 				void                   **image_extra)
 {
@@ -1591,65 +1583,64 @@ static void
 
     cairo_surface_destroy(&image->base);
 
     softTexture->Unmap(0);
     D3D10Factory::Device()->CopyResource(d2dsurf->surface, softTexture);
     softTexture->Release();
 }
 
-static cairo_status_t
-_cairo_d2d_surface_clipper_intersect_clip_path(cairo_surface_clipper_t *clipper,
-					       cairo_path_fixed_t      *path,
-					       cairo_fill_rule_t	fill_rule,
-					       double			tolerance,
-					       cairo_antialias_t	antialias)
+cairo_int_status_t
+_cairo_d2d_intersect_clip_path(void			*dst,
+			       cairo_path_fixed_t	*path,
+			       cairo_fill_rule_t	fill_rule,
+			       double			tolerance,
+			       cairo_antialias_t	antialias)
 {
-    cairo_d2d_surface_t *d2dsurf = cairo_container_of (clipper, cairo_d2d_surface_t, clipper);
+    cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(dst);
 
     _cairo_d2d_surface_pop_clip(d2dsurf);
     if (!path) {
 	if (d2dsurf->clipMask) {
 	    d2dsurf->clipMask->Release();
 	    d2dsurf->clipMask = NULL;
 	}
 	if (d2dsurf->clipRect) {
 	    delete d2dsurf->clipRect;
 	    d2dsurf->clipRect = NULL;
 	}
-	return CAIRO_STATUS_SUCCESS;
+	return CAIRO_INT_STATUS_SUCCESS;
     }
     cairo_box_t box;
 
     if (_cairo_path_fixed_is_box(path, &box) && box.p1.y < box.p2.y) {
 	/** 
 	 * Nice axis aligned rectangular clip, try and do our best to keep it
 	 * that way.
 	 */
 	if (!d2dsurf->clipRect && !d2dsurf->clipMask) {
 	    /** Nothing yet, just use this clip rect */
-	    //XXX: unchecked allocation
 	    d2dsurf->clipRect = new D2D1_RECT_F(D2D1::RectF(_cairo_fixed_to_float(box.p1.x),
 							    _cairo_fixed_to_float(box.p1.y),
 							    _cairo_fixed_to_float(box.p2.x),
 							    _cairo_fixed_to_float(box.p2.y)));
-	    return CAIRO_STATUS_SUCCESS;
+	    return CAIRO_INT_STATUS_SUCCESS;
 	} else if (!d2dsurf->clipMask) {
 	    /** We have a clip rect, intersect of two rects is simple */
 	    d2dsurf->clipRect->top = max(_cairo_fixed_to_float(box.p1.y), d2dsurf->clipRect->top);
 	    d2dsurf->clipRect->left = max(d2dsurf->clipRect->left, _cairo_fixed_to_float(box.p1.x));
 	    d2dsurf->clipRect->bottom = min(d2dsurf->clipRect->bottom, _cairo_fixed_to_float(box.p2.y));
 	    d2dsurf->clipRect->right = min(d2dsurf->clipRect->right, _cairo_fixed_to_float(box.p2.x));
 	    if (d2dsurf->clipRect->top > d2dsurf->clipRect->bottom) {
 		d2dsurf->clipRect->top = d2dsurf->clipRect->bottom;
 	    }
 	    if (d2dsurf->clipRect->left > d2dsurf->clipRect->right) {
 		d2dsurf->clipRect->left = d2dsurf->clipRect->right;
 	    }
-	    return CAIRO_STATUS_SUCCESS;
+	    return CAIRO_INT_STATUS_SUCCESS;
 	} else {
 	    /** 
 	     * We have a mask, see if this rect is completely contained by it, so we
 	     * can optimize by just using this rect rather than a geometry mask.
 	     */
 	    ID2D1RectangleGeometry *newMask;
 	    D2DSurfFactory::Instance()->CreateRectangleGeometry(D2D1::RectF(_cairo_fixed_to_float(box.p1.x),
 									    _cairo_fixed_to_float(box.p1.y),
@@ -1657,22 +1648,21 @@ static cairo_status_t
 									    _cairo_fixed_to_float(box.p2.y)), 
 								&newMask);
 	    D2D1_GEOMETRY_RELATION relation;
 	    d2dsurf->clipMask->CompareWithGeometry(newMask, D2D1::Matrix3x2F::Identity(), &relation);
 	    if (relation == D2D1_GEOMETRY_RELATION_CONTAINS) {
 	        d2dsurf->clipMask->Release();
 		d2dsurf->clipMask = NULL;
 	        newMask->Release();
-		//XXX: unchecked allocation
 	        d2dsurf->clipRect = new D2D1_RECT_F(D2D1::RectF(_cairo_fixed_to_float(box.p1.x),
 								_cairo_fixed_to_float(box.p1.y),
 								_cairo_fixed_to_float(box.p2.x),
 								_cairo_fixed_to_float(box.p2.y)));
-		return CAIRO_STATUS_SUCCESS;
+		return CAIRO_INT_STATUS_SUCCESS;		    
 		
 	    }
 	    newMask->Release();
 	}
     }
     
     if (!d2dsurf->clipRect && !d2dsurf->clipMask) {
 	/** Nothing yet, just use this clip path */
@@ -1702,17 +1692,17 @@ static cairo_status_t
 	ID2D1RectangleGeometry *currentMask;
 	D2DSurfFactory::Instance()->CreateRectangleGeometry(d2dsurf->clipRect, &currentMask);
 	ID2D1Geometry *newMask = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
         D2D1_GEOMETRY_RELATION relation;
 	newMask->CompareWithGeometry(currentMask, D2D1::Matrix3x2F::Identity(), &relation);
 	if (relation == D2D1_GEOMETRY_RELATION_CONTAINS) {
 	    currentMask->Release();
 	    newMask->Release();
-	    return CAIRO_STATUS_SUCCESS;
+	    return CAIRO_INT_STATUS_SUCCESS;
 	} else if (relation == D2D1_GEOMETRY_RELATION_IS_CONTAINED) {
 	    currentMask->Release();
 	    d2dsurf->clipMask = newMask;
 	} else {
 	    ID2D1PathGeometry *finalMask;
 	    D2DSurfFactory::Instance()->CreatePathGeometry(&finalMask);
 	    ID2D1GeometrySink *sink;
 	    finalMask->Open(&sink);
@@ -1728,17 +1718,17 @@ static cairo_status_t
 	}
     }
 
     if (d2dsurf->clipRect) {
 	delete d2dsurf->clipRect;
 	d2dsurf->clipRect = NULL;
     }
   
-    return CAIRO_STATUS_SUCCESS;
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_d2d_flush(void                  *surface)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
 
     if (d2dsurf->isDrawing) {
@@ -1748,25 +1738,19 @@ static cairo_status_t
     }
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_d2d_paint(void			*surface,
 		 cairo_operator_t	 op,
 		 const cairo_pattern_t	*source,
-		 cairo_clip_t		*clip)
+		 cairo_rectangle_int_t  *extents)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
-    cairo_int_status_t status;
-
-    status = (cairo_int_status_t)_cairo_surface_clipper_set_clip (&d2dsurf->clipper, clip);
-    if (unlikely(status))
-	return status;
-
     _begin_draw_state(d2dsurf);
 
     op = _cairo_d2d_simplify_operator(op, source);
 
     if (op == CAIRO_OPERATOR_CLEAR) {
 	_cairo_d2d_clear_geometry(d2dsurf, NULL);
 	return CAIRO_INT_STATUS_SUCCESS;
     }
@@ -1782,24 +1766,30 @@ static cairo_int_status_t
 								source,
 								last_run++,
 								&runs_remaining,
 								&pushed_clip);
 
 	if (!brush) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
-	if (op == CAIRO_OPERATOR_OVER) {
+	if (op == CAIRO_OPERATOR_OVER && extents) {
+	    d2dsurf->rt->FillRectangle(D2D1::RectF((FLOAT)extents->x,
+						   (FLOAT)extents->y,
+						   (FLOAT)extents->x + extents->width,
+						   (FLOAT)extents->y + extents->height),
+				       brush);
+	} else if (op == CAIRO_OPERATOR_OVER) {
 	    D2D1_SIZE_F size = d2dsurf->rt->GetSize();
 	    d2dsurf->rt->FillRectangle(D2D1::RectF((FLOAT)0,
 						   (FLOAT)0,
 						   (FLOAT)size.width,
 						   (FLOAT)size.height),
 				       brush);
-        } else if (op == CAIRO_OPERATOR_SOURCE) {
+        } else if (op == CAIRO_OPERATOR_SOURCE && !extents) {
 	    D2D1_SIZE_F size = d2dsurf->rt->GetSize();
             d2dsurf->rt->Clear(D2D1::ColorF(0, 0));
             d2dsurf->rt->FillRectangle(D2D1::RectF((FLOAT)0,
 						   (FLOAT)0,
 						   (FLOAT)size.width,
 						   (FLOAT)size.height),
 				       brush);
         } else {
@@ -1815,58 +1805,43 @@ static cairo_int_status_t
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_d2d_mask(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		const cairo_pattern_t	*mask,
-		cairo_clip_t		*clip)
+		cairo_rectangle_int_t	*extents)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
-    cairo_rectangle_int_t extents;
+    _begin_draw_state(d2dsurf);
 
     unsigned int runs_remaining = 0;
     bool pushed_clip;
-    cairo_int_status_t status;
-
-    status = (cairo_int_status_t)_cairo_surface_clipper_set_clip (&d2dsurf->clipper, clip);
-    if (unlikely (status))
-	return status;
-
-    _begin_draw_state(d2dsurf);
-
-    status = (cairo_int_status_t)_cairo_surface_mask_extents (&d2dsurf->base,
-		    op, source,
-		    mask,
-		    clip, &extents);
-    if (unlikely (status))
-	    return status;
-
 
     ID2D1Brush *brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source, 0, &runs_remaining, &pushed_clip);
     if (!brush) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
     if (runs_remaining) {
 	brush->Release();
 	// TODO: Implement me!!
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
     D2D1_RECT_F rect = D2D1::RectF(0,
 				   0,
 				   (FLOAT)d2dsurf->rt->GetPixelSize().width,
 				   (FLOAT)d2dsurf->rt->GetPixelSize().height);
-
-    rect.left = (FLOAT)extents.x;
-    rect.right = (FLOAT)(extents.x + extents.width);
-    rect.top = (FLOAT)extents.y;
-    rect.bottom = (FLOAT)(extents.y + extents.height);
-
+    if (extents) {
+	rect.left = (FLOAT)extents->x;
+	rect.right = (FLOAT)(extents->x + extents->width);
+	rect.top = (FLOAT)extents->y;
+	rect.bottom = (FLOAT)(extents->y + extents->height);
+    }
 
     if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
 	cairo_solid_pattern_t *solidPattern =
 	    (cairo_solid_pattern_t*)mask;
 	if (solidPattern->content = CAIRO_CONTENT_ALPHA) {
 	    brush->SetOpacity((FLOAT)solidPattern->color.alpha);
 	    d2dsurf->rt->FillRectangle(rect,
 				       brush);
@@ -1909,40 +1884,33 @@ static cairo_int_status_t
 		  cairo_operator_t	 op,
 		  const cairo_pattern_t	*source,
 		  cairo_path_fixed_t	*path,
 		  cairo_stroke_style_t	*style,
 		  cairo_matrix_t	*ctm,
 		  cairo_matrix_t	*ctm_inverse,
 		  double		 tolerance,
 		  cairo_antialias_t	 antialias,
-		  cairo_clip_t		*clip)
+		  cairo_rectangle_int_t  *extents)
 {
-    cairo_int_status_t status;
-
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
+    _begin_draw_state(d2dsurf);
 
     op = _cairo_d2d_simplify_operator(op, source);
 
     if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD &&
 	op != CAIRO_OPERATOR_CLEAR) {
 	/** 
 	 * We don't really support ADD yet. True ADD support requires getting
 	 * the tesselated mesh from D2D, and blending that using D3D which has
 	 * an add operator available.
 	 */
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    status = (cairo_int_status_t)_cairo_surface_clipper_set_clip (&d2dsurf->clipper, clip);
-    if (unlikely(status))
-	return status;
-
-    _begin_draw_state(d2dsurf);
-
     if (antialias == CAIRO_ANTIALIAS_NONE) {
 	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
     } else {
 	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
     }
     ID2D1StrokeStyle *strokeStyle = _cairo_d2d_create_strokestyle_for_stroke_style(style);
 
     if (!strokeStyle) {
@@ -2045,40 +2013,36 @@ static cairo_int_status_t
 static cairo_int_status_t
 _cairo_d2d_fill(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		cairo_path_fixed_t	*path,
 		cairo_fill_rule_t	 fill_rule,
 		double			 tolerance,
 		cairo_antialias_t	 antialias,
-		cairo_clip_t		*clip)
+		cairo_rectangle_int_t	*extents)
 {
-    cairo_int_status_t status;
-
+    if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
+    _begin_draw_state(d2dsurf);
 
     op = _cairo_d2d_simplify_operator(op, source);
 
     if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD &&
 	op != CAIRO_OPERATOR_CLEAR) {
 	/** 
 	 * We don't really support ADD yet. True ADD support requires getting
 	 * the tesselated mesh from D2D, and blending that using D3D which has
 	 * an add operator available.
 	 */
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    status = (cairo_int_status_t)_cairo_surface_clipper_set_clip (&d2dsurf->clipper, clip);
-    if (unlikely (status))
-	return status;
-
-    _begin_draw_state(d2dsurf);
-
     if (antialias == CAIRO_ANTIALIAS_NONE) {
 	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
     } else {
 	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
     }
 
     unsigned int runs_remaining = 1;
     unsigned int last_run = 0;
@@ -2149,59 +2113,61 @@ static cairo_int_status_t
 		d2dsurf->rt->PopLayer();
 	    }
 	}
 	d2dpath->Release();
     }
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
-
 static cairo_int_status_t
 _cairo_d2d_show_glyphs (void			*surface,
 			cairo_operator_t	 op,
 			const cairo_pattern_t	*source,
 			cairo_glyph_t		*glyphs,
 			int			 num_glyphs,
 			cairo_scaled_font_t	*scaled_font,
-			cairo_clip_t            *clip,
-			int			*remaining_glyphs)
+			int			*remaining_glyphs,
+			cairo_rectangle_int_t	*extents)
 {
     if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
     if (!d2dsurf->textRenderingInit) {
 	IDWriteRenderingParams *params;
 	DWriteFactory::Instance()->CreateRenderingParams(&params);
 	d2dsurf->rt->SetTextRenderingParams(params);
 	d2dsurf->textRenderingInit = true;
 	params->Release();
     }
+    _begin_draw_state(d2dsurf);
     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
         status = (cairo_int_status_t)
-	    _cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
+	    cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, extents);
     }
 
     return status;
 }
 
-
-static cairo_bool_t
+static cairo_int_status_t
 _cairo_d2d_getextents(void		       *surface,
 		      cairo_rectangle_int_t    *extents)
 {
+    if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D) {
+	return (cairo_int_status_t)CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+    }
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
     extents->x = 0;
     extents->y = 0;
     D2D1_SIZE_U size = d2dsurf->rt->GetPixelSize(); 
     extents->width = size.width;
     extents->height = size.height;
-    return TRUE;
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 
 /** Helper functions. */
 
 cairo_surface_t*
 cairo_d2d_surface_create_for_hwnd(HWND wnd)
 {
@@ -2212,17 +2178,16 @@ cairo_d2d_surface_create_for_hwnd(HWND w
 	 */
 	return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_DEVICE));
     }
 
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
 
     memset(newSurf, 0, sizeof(cairo_d2d_surface_t));
     _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
-    _cairo_surface_clipper_init(&newSurf->clipper, _cairo_d2d_surface_clipper_intersect_clip_path);
 
     RECT rc;
     HRESULT hr;
 
     newSurf->isDrawing = false;
     ::GetClientRect(wnd, &rc);
 
     FLOAT dpiX;
@@ -2348,19 +2313,16 @@ cairo_d2d_surface_create(cairo_format_t 
 	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
     } else if (format == CAIRO_FORMAT_RGB24) {
 	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
 	alpha = D2D1_ALPHA_MODE_IGNORE;
     } else {
 	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
 	dxgiformat = DXGI_FORMAT_A8_UNORM;
     }
-
-    _cairo_surface_clipper_init(&newSurf->clipper, _cairo_d2d_surface_clipper_intersect_clip_path);
-
     newSurf->format = format;
 
     D2D1_SIZE_U sizePixels;
     HRESULT hr;
 
     sizePixels.width = width;
     sizePixels.height = height;
 
--- a/gfx/cairo/cairo/src/cairo-ddraw-private.h
+++ b/gfx/cairo/cairo/src/cairo-ddraw-private.h
@@ -32,17 +32,16 @@
  * Contributor(s):
  */
 
 #ifndef CAIRO_DDRAW_PRIVATE_H
 #define CAIRO_DDRAW_PRIVATE_H
 
 #include "cairo-ddraw.h"
 #include "cairoint.h"
-#include "cairo-region-private.h"
 
 #ifdef CAIRO_DDRAW_USE_GL
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 #endif
 
--- a/gfx/cairo/cairo/src/cairo-ddraw-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ddraw-surface.c
@@ -237,16 +237,38 @@ static cairo_status_t
 # else
 # define CHECK_OGL_ERROR(context)
 # endif
 #endif
 
 #endif /* CAIRO_DDRAW_USE_GL */
 
 static cairo_status_t
+_cairo_ddraw_surface_set_image_clip (cairo_ddraw_surface_t *surface)
+{
+    if (surface->image_clip_invalid) {
+	surface->image_clip_invalid = FALSE;
+	if (surface->has_clip_region) {
+	    unsigned int serial =
+		_cairo_surface_allocate_clip_serial (surface->image);
+	    surface->has_image_clip = TRUE;
+	    return _cairo_surface_set_clip_region (surface->image,
+						   &surface->clip_region,
+						   serial);
+	} else {
+	    surface->has_image_clip = FALSE;
+	    return _cairo_surface_set_clip_region (surface->image,
+						   NULL, 0);
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_ddraw_surface_set_clip_list (cairo_ddraw_surface_t * surface)
 {
     DWORD stack_data[CAIRO_STACK_BUFFER_SIZE / sizeof (DWORD)];
     cairo_rectangle_int_t extents;
     int num_rects;
     RGNDATA * rgn;
     DWORD size;
     cairo_status_t status;
@@ -344,17 +366,20 @@ static cairo_status_t
 						 surface->data_offset,
 						 surface->format,
 						 surface->extents.width,
 						 surface->extents.height,
 						 root_img->stride);
 	if (surface->image->status)
 	    return surface->image->status;
 
-	return CAIRO_STATUS_SUCCESS;
+	surface->has_image_clip = FALSE;
+	surface->image_clip_invalid = surface->has_clip_region;
+
+	return _cairo_ddraw_surface_set_image_clip (surface);
     }
 
     if (surface->locked)
 	return CAIRO_STATUS_SUCCESS;
 
     ddsd.dwSize = sizeof (ddsd);
     START_TIMER(lock);
     if (FAILED(hr = IDDSLock (surface->lpdds, NULL, &ddsd,
@@ -378,17 +403,20 @@ static cairo_status_t
 					     surface->format,
 					     ddsd.dwWidth,
 					     ddsd.dwHeight,
 					     ddsd.lPitch);
 
     if (surface->image->status)
 	return surface->image->status;
 
-    return CAIRO_STATUS_SUCCESS;
+    surface->has_image_clip = FALSE;
+    surface->image_clip_invalid = surface->has_clip_region;
+
+    return _cairo_ddraw_surface_set_image_clip (surface);
 }
 
 static inline cairo_status_t
 _cairo_ddraw_surface_unlock (cairo_ddraw_surface_t *surface)
 {
     cairo_ddraw_surface_t * root = surface->root;
     HRESULT hr;
 
@@ -431,18 +459,16 @@ static inline cairo_status_t
 	HRESULT hr;
 	if (FAILED(hr = IDDSSetClipper(root->lpdds, NULL)))
 	    return _cairo_ddraw_print_ddraw_error ("_reset_clipper", hr);
 	root->installed_clipper = NULL;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
-
-
 #ifdef CAIRO_DDRAW_USE_GL
 #define CAIRO_DDRAW_API_ENTRY_STATUS                                  \
     do {                                                              \
 	int status;                                                   \
 	if (status = _cairo_ddraw_ogl_make_current())		      \
 	    return (status);					      \
     } while (0)
 #define CAIRO_DDRAW_API_ENTRY_VOID do {                               \
@@ -541,17 +567,17 @@ static cairo_status_t
     END_TIMER(flush);
  
     return status;
 }
 
 cairo_status_t
 _cairo_ddraw_surface_reset (cairo_surface_t *surface)
 {
-    return _cairo_ddraw_surface_set_clip_region (surface, NULL);
+    return _cairo_surface_reset_clip (surface);
 }
 
 static cairo_surface_t *
 _cairo_ddraw_surface_create_similar (void * abstract_surface,
 				     cairo_content_t content,
 				     int width,
 				     int height)
 {
@@ -2446,18 +2472,18 @@ static cairo_int_status_t
 
 static cairo_int_status_t
 _cairo_ddraw_surface_show_glyphs (void		         *abstract_dst,
 				  cairo_operator_t	 op,
 				  const cairo_pattern_t  *pattern,
 				  cairo_glyph_t	         *glyphs,
 				  int		         num_glyphs,
 				  cairo_scaled_font_t    *scaled_font,
-				  cairo_clip_t           *clip,
-				  int		         *remaining_glyphs)
+				  int		         *remaining_glyphs,
+				  cairo_rectangle_int_t  *extents)
 { 
     cairo_ddraw_surface_t * dst = (cairo_ddraw_surface_t *) abstract_dst;
     cairo_color_t * color;
     cairo_ddraw_ogl_font_t * font = scaled_font->surface_private;
     GLuint vbo;
     cairo_ddraw_ogl_glyph_quad_t * verts;
     cairo_ddraw_ogl_glyph_idx_t * indices;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -2471,27 +2497,20 @@ static cairo_int_status_t
 
     CAIRO_DDRAW_API_ENTRY_STATUS;
 
     assert (num_glyphs);
 
     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (clip != NULL) {
-	cairo_region_t *clip_region;
-	cairo_status_t status;
-
-	status = _cairo_clip_get_region (clip, &clip_region);
-	assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
-	if (status)
-	    return status;
-
-	_cairo_ddraw_surface_set_clip_region (surface, clip_region);
-    }
+    if (dst->base.clip &&
+	(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
+	 dst->base.clip->surface != NULL))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     color = &((cairo_solid_pattern_t *)pattern)->color;
 
     if (font == NULL) {
 	font = calloc (1, sizeof (cairo_ddraw_ogl_font_t));
 	if (font == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
@@ -2687,18 +2706,17 @@ static cairo_int_status_t
 				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_regiont_t         *clip_region)
+				unsigned int		height)
 {
     cairo_ddraw_surface_t * dst = (cairo_ddraw_surface_t *) abstract_dst;
     cairo_ddraw_ogl_program_info_t * info = NULL;
     cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
     cairo_surface_t * mask_surface = NULL;
     cairo_surface_t * src_surface = NULL;
     cairo_ddraw_surface_t * mask_ddraw_surface = NULL;
     cairo_ddraw_surface_t * src_ddraw_surface = NULL;
@@ -2718,20 +2736,16 @@ static cairo_int_status_t
 
     CAIRO_DDRAW_API_ENTRY_STATUS;
 
     /*XXX TODO - emulate hard textures with shader magic */
 
     if (op == CAIRO_OPERATOR_DEST)
 	return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_ddraw_surface_set_clip_region (dst, clip_region);
-    if (status)
-	return status;
-
     /* bail out for source copies that aren't ddraw surfaces) */
     if (src->type == CAIRO_PATTERN_TYPE_SURFACE &&
 	(((cairo_surface_pattern_t *) src)->surface->type 
 	 != CAIRO_SURFACE_TYPE_DDRAW)) {
 #ifdef CAIRO_DDRAW_DEBUG_VERBOSE
 	_cairo_ddraw_log ("composite of non ddraw surface %d,%d\n", width, height);
 #endif
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -3117,16 +3131,19 @@ static cairo_status_t
 #ifdef CAIRO_DDRAW_USE_GL
     _cairo_ddraw_ogl_flush (surface);
 #endif
 
     if ((status = _cairo_ddraw_surface_lock (surface)))
 	return status;
     END_TIMER(acquiredst);
 
+    if ((status = _cairo_ddraw_surface_set_image_clip (surface)))
+	return status;
+
     *image_out = (cairo_image_surface_t *) surface->image;
     *image_rect = surface->extents;
     *image_extra = NULL;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
@@ -3145,28 +3162,30 @@ cairo_int_status_t
 				      cairo_region_t *region)
 {
     cairo_ddraw_surface_t * surface =
 	(cairo_ddraw_surface_t *) abstract_surface;
 
     if (region) {
 	cairo_region_t *tmp_region;
 	surface->has_clip_region = TRUE;
+	surface->image_clip_invalid = TRUE;
 	surface->clip_list_invalid = TRUE;
 
 	tmp_region = &surface->clip_region;
 	if (! pixman_region32_copy (&tmp_region->rgn, &region->rgn))
 	    return CAIRO_STATUS_NO_MEMORY;
 
 	if (surface->extents.x || surface->extents.y)
 	    cairo_region_translate (&surface->clip_region,
 				    -surface->extents.x,
 				    -surface->extents.y);
     } else {
 	surface->has_clip_region = FALSE;
+	surface->image_clip_invalid = surface->has_image_clip;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * cairo_ddraw_surface_create:
  * @lpdd: pointer to a DirectDraw object
@@ -3260,16 +3279,18 @@ cairo_ddraw_surface_create (LPDIRECTDRAW
 
     surface->lpdd = lpdd;
 
     surface->locked = FALSE;
 #ifdef CAIRO_DDRAW_USE_GL
     surface->dirty = FALSE;
 #endif
     surface->has_clip_region = FALSE;
+    surface->has_image_clip = FALSE;
+    surface->image_clip_invalid = FALSE;
     surface->clip_list_invalid = FALSE;
 
     surface->installed_clipper = NULL;
     surface->image = NULL;
     surface->root = surface;
     surface->data_offset = 0;
 
     surface->extents.x = 0;
@@ -3335,16 +3356,18 @@ cairo_ddraw_surface_create_alias (cairo_
 
     cairo_surface_reference (root_surface);
 
     surface->locked = FALSE;
 #ifdef CAIRO_DDRAW_USE_GL
     surface->dirty = FALSE;
 #endif
     surface->has_clip_region = FALSE;
+    surface->has_image_clip = FALSE;
+    surface->image_clip_invalid = FALSE;
     surface->clip_list_invalid = FALSE;
 
     surface->format = root->format;
     surface->lpdds = root->lpdds;
     surface->lpdd = root->lpdd;
     surface->lpdds = root->lpdds;
     surface->installed_clipper = NULL;
     surface->image = NULL;
@@ -3538,20 +3561,16 @@ static cairo_int_status_t
     if (surface->base.content == CAIRO_CONTENT_COLOR)
 	op = _cairo_ddraw_ogl_op_downgrade[op];
 
     sr = color->red_short   * (1.0f / 65535.0f);
     sg = color->green_short * (1.0f / 65535.0f);
     sb = color->blue_short  * (1.0f / 65535.0f);
     sa = color->alpha_short * (1.0f / 65535.0f);
 
-    status = _cairo_ddraw_surface_set_clip_region (surface, NULL);
-    if (status)
-	return status;
-
     /* convert to solid clears if we can (so we can use glClear) */
     if (op == CAIRO_OPERATOR_SOURCE ||
 	op == CAIRO_OPERATOR_OVER && color->alpha_short >= 0xff00) {
 	op = CAIRO_OPERATOR_SOURCE;
 	if (surface->format == CAIRO_FORMAT_A8) {
 	    can_fold = TRUE;
 	    color_data = color->alpha_short >> 8;
 	} else if (surface->format = CAIRO_FORMAT_RGB24) {
@@ -4086,16 +4105,18 @@ static const cairo_surface_backend_t _ca
 #else
     NULL, /* fill_rectangles */
 #endif
     NULL, /* composite_trapezoids */
     NULL, /* create_span_renderer */
     NULL, /* check_span_renderer */
     NULL, /* copy_page */
     NULL, /* show_page */
+    _cairo_ddraw_surface_set_clip_region,
+    NULL, /* intersect_clip_path */
     _cairo_ddraw_surface_get_extents,
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
     _cairo_ddraw_surface_flush,
     NULL, /* mark_dirty_rectangle */
 #ifdef CAIRO_DDRAW_FONT_ACCELERATION
     _cairo_ddraw_surface_scaled_font_fini,
     _cairo_ddraw_surface_scaled_glyph_fini,
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -70,22 +70,16 @@ cairo_debug_reset_static_data (void)
 #endif
 
     _cairo_intern_string_reset_static_data ();
 
     _cairo_scaled_font_reset_static_data ();
 
     _cairo_pattern_reset_static_data ();
 
-    _cairo_clip_reset_static_data ();
-
-#if CAIRO_HAS_DRM_SURFACE
-    _cairo_drm_device_reset_static_data ();
-#endif
-
     CAIRO_MUTEX_FINALIZE ();
 }
 
 #if HAVE_VALGRIND
 void
 _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
 {
     const cairo_image_surface_t *image = (cairo_image_surface_t *) surface;
@@ -160,75 +154,8 @@ void
         }
     }
 
     fclose (fp);
 
     fprintf (stderr, "Wrote %s\n", fn);
 }
 #endif
-
-static cairo_status_t
-_print_move_to (void *closure,
-		const cairo_point_t *point)
-{
-    fprintf (closure,
-	     " %f %f m",
-	     _cairo_fixed_to_double (point->x),
-	     _cairo_fixed_to_double (point->y));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_print_line_to (void *closure,
-		const cairo_point_t *point)
-{
-    fprintf (closure,
-	     " %f %f l",
-	     _cairo_fixed_to_double (point->x),
-	     _cairo_fixed_to_double (point->y));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_print_curve_to (void *closure,
-		 const cairo_point_t *p1,
-		 const cairo_point_t *p2,
-		 const cairo_point_t *p3)
-{
-    fprintf (closure,
-	     " %f %f %f %f %f %f c",
-	     _cairo_fixed_to_double (p1->x),
-	     _cairo_fixed_to_double (p1->y),
-	     _cairo_fixed_to_double (p2->x),
-	     _cairo_fixed_to_double (p2->y),
-	     _cairo_fixed_to_double (p3->x),
-	     _cairo_fixed_to_double (p3->y));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_print_close (void *closure)
-{
-    fprintf (closure, " h");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-void
-_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
-{
-    cairo_status_t status;
-
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _print_move_to,
-					  _print_line_to,
-					  _print_curve_to,
-					  _print_close,
-					  stream);
-    assert (status == CAIRO_STATUS_SUCCESS);
-
-    printf ("\n");
-}
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -33,26 +33,24 @@
  * Contributor(s):
  *    Michael Emmel <mike.emmel@gmail.com>
  *    Claudio Ciccani <klan@users.sf.net>
  */
 
 #include "cairoint.h"
 #include "cairo-directfb.h"
 
-#include "cairo-clip-private.h"
-
-#include <pixman.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
 
 /*
@@ -65,37 +63,37 @@
  */
 #define DFB_COMPOSITE_TRAPEZOIDS 1
 
 /*
  * ShowGlyphs works fine.
  */
 #define DFB_SHOW_GLYPHS 1
 
-#define PIXMAN_invalid (pixman_format_code_t) 0
-
 
 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;
-
-    pixman_format_code_t	pixman_format;
-    cairo_bool_t		supported_destination;
+    cairo_surface_t      base;
+    cairo_format_t       format;
+    cairo_content_t      content;
 
-    IDirectFB			*dfb;
-    IDirectFBSurface		*dfbsurface;
-    IDirectFBSurface		*tmpsurface;
-    pixman_format_code_t	 tmpformat;
+    IDirectFB           *dfb;
+    IDirectFBSurface    *dfbsurface;
+    IDirectFBSurface    *tmpsurface;
+
+    cairo_bool_t         has_clip;
+    DFBRegion           *clips;
+    int                  n_clips;
 
     int                  width;
     int                  height;
 
     unsigned             local : 1;
     unsigned             blit_premultiplied : 1;
 } cairo_directfb_surface_t;
 
@@ -116,71 +114,60 @@ typedef struct _cairo_directfb_font_cach
 static cairo_surface_backend_t _cairo_directfb_surface_backend;
 
 /*****************************************************************************/
 
 static int _directfb_argb_font = 0;
 
 /*****************************************************************************/
 
-#define RUN_CLIPPED(surface, clip_region, clip, func) {\
-    if ((clip_region) != NULL) {\
-	int n_clips = cairo_region_num_rectangles (clip_region), n; \
-        for (n = 0; n < n_clips; n++) {\
+#define RUN_CLIPPED(surface, clip, func) {\
+    if ((surface)->has_clip) {\
+        int k;\
+        for (k = 0; k < (surface)->n_clips; k++) {\
             if (clip) {\
-                DFBRegion  reg, *cli = (clip); \
-		cairo_rectangle_int_t rect; \
-		cairo_region_get_rectangle (clip_region, n, &rect); \
-		reg.x1 = rect.x; \
-		reg.y1 = rect.y; \
-		reg.x2 = rect.x + rect.width - 1; \
-		reg.y2 = rect.y + rect.height - 1; \
+                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;\
                 if (reg.x1 < cli->x1)\
                     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 {\
-		DFBRegion reg; \
-		cairo_rectangle_int_t rect; \
-		cairo_region_get_rectangle (clip_region, n, &rect); \
-		reg.x1 = rect.x; \
-		reg.y1 = rect.y; \
-		reg.x2 = rect.x + rect.width - 1; \
-		reg.y2 = rect.y + rect.height - 1; \
-                (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg); \
+                (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\
+                                           &(surface)->clips[k]);\
             }\
             func;\
         }\
     } else {\
         (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
         func;\
     }\
 }
 
-#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) do { \
-    double _x = (x); \
-    double _y = (y); \
-    (ret_x) = (_x * (m).xx + (m).x0); \
-    (ret_y) = (_y * (m).yy + (m).y0); \
-} while (0)
+#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) do { \
-    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); \
-} while (0)
+#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\
+    double _x = (x);\
+    double _y = (y);\
+    (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\
+    (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\
+}
 
 /* XXX: A1 has a different bits ordering in cairo.
  *      Probably we should drop it.
  */
 
 static cairo_content_t
 _directfb_format_to_content (DFBSurfacePixelFormat format)
 {
@@ -208,79 +195,33 @@ static inline DFBSurfacePixelFormat
 	return DSPF_A1;
     default:
 	break;
     }
 
     return -1;
 }
 
-static inline pixman_format_code_t
-_directfb_to_pixman_format (DFBSurfacePixelFormat format)
+static inline cairo_format_t
+_directfb_to_cairo_format (DFBSurfacePixelFormat format)
 {
     switch (format) {
-    case DSPF_UNKNOWN: return PIXMAN_invalid;
-    case DSPF_ARGB1555: return PIXMAN_a1r5g5b5;
-    case DSPF_RGB16: return PIXMAN_r5g6b5;
-    case DSPF_RGB24: return PIXMAN_r8g8b8;
-    case DSPF_RGB32: return PIXMAN_x8r8g8b8;
-    case DSPF_ARGB: return PIXMAN_a8r8g8b8;
-    case DSPF_A8: return PIXMAN_a8;
-    case DSPF_YUY2: return PIXMAN_yuy2;
-    case DSPF_RGB332: return PIXMAN_r3g3b2;
-    case DSPF_UYVY: return PIXMAN_invalid;
-    case DSPF_I420: return PIXMAN_invalid;
-    case DSPF_YV12: return PIXMAN_yv12;
-    case DSPF_LUT8: return PIXMAN_invalid;
-    case DSPF_ALUT44: return PIXMAN_invalid;
-    case DSPF_AiRGB: return PIXMAN_invalid;
-    case DSPF_A1: return PIXMAN_a1; /* bit reversed, oops */
-    case DSPF_NV12: return PIXMAN_invalid;
-    case DSPF_NV16: return PIXMAN_invalid;
-    case DSPF_ARGB2554: return PIXMAN_invalid;
-    case DSPF_ARGB4444: return PIXMAN_a4r4g4b4;
-    case DSPF_NV21: return PIXMAN_invalid;
-    case DSPF_AYUV: return PIXMAN_invalid;
-    case DSPF_A4: return PIXMAN_a4;
-    case DSPF_ARGB1666: return PIXMAN_invalid;
-    case DSPF_ARGB6666: return PIXMAN_invalid;
-    case DSPF_RGB18: return PIXMAN_invalid;
-    case DSPF_LUT2: return PIXMAN_invalid;
-    case DSPF_RGB444: return PIXMAN_x4r4g4b4;
-    case DSPF_RGB555: return PIXMAN_x1r5g5b5;
-#if DFB_NUM_PIXELFORMATS >= 29
-    case DSPF_BGR555: return PIXMAN_x1b5g5r5;
-#endif
+    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 PIXMAN_invalid;
-}
 
-static inline DFBSurfacePixelFormat
-_directfb_from_pixman_format (pixman_format_code_t format)
-{
-    switch ((int) format) {
-    case PIXMAN_a1r5g5b5: return DSPF_ARGB1555;
-    case PIXMAN_r5g6b5: return DSPF_RGB16;
-    case PIXMAN_r8g8b8: return DSPF_RGB24;
-    case PIXMAN_x8r8g8b8: return DSPF_RGB32;
-    case PIXMAN_a8r8g8b8: return DSPF_ARGB;
-    case PIXMAN_a8: return DSPF_A8;
-    case PIXMAN_yuy2: return DSPF_YUY2;
-    case PIXMAN_r3g3b2: return DSPF_RGB332;
-    case PIXMAN_yv12: return DSPF_YV12;
-    case PIXMAN_a1: return DSPF_A1; /* bit reversed, oops */
-    case PIXMAN_a4r4g4b4: return DSPF_ARGB4444;
-    case PIXMAN_a4: return DSPF_A4;
-    case PIXMAN_x4r4g4b4: return DSPF_RGB444;
-    case PIXMAN_x1r5g5b5: return DSPF_RGB555;
-#if DFB_NUM_PIXELFORMATS >= 29
-    case PIXMAN_x1b5g5r5: return DSPF_BGR555;
-#endif
-    default: return 0;
-    }
+    return -1;
 }
 
 static cairo_bool_t
 _directfb_get_operator (cairo_operator_t         operator,
                         DFBSurfaceBlendFunction *ret_srcblend,
                         DFBSurfaceBlendFunction *ret_dstblend)
 {
     DFBSurfaceBlendFunction srcblend = DSBF_ONE;
@@ -341,31 +282,16 @@ static cairo_bool_t
 	break;
     case CAIRO_OPERATOR_SATURATE:
 	/* XXX This does not work. */
 #if 0
 	srcblend = DSBF_SRCALPHASAT;
 	dstblend = DSBF_ONE;
 	break;
 #endif
-    case CAIRO_OPERATOR_MULTIPLY:
-    case CAIRO_OPERATOR_SCREEN:
-    case CAIRO_OPERATOR_OVERLAY:
-    case CAIRO_OPERATOR_DARKEN:
-    case CAIRO_OPERATOR_LIGHTEN:
-    case CAIRO_OPERATOR_COLOR_DODGE:
-    case CAIRO_OPERATOR_COLOR_BURN:
-    case CAIRO_OPERATOR_HARD_LIGHT:
-    case CAIRO_OPERATOR_SOFT_LIGHT:
-    case CAIRO_OPERATOR_DIFFERENCE:
-    case CAIRO_OPERATOR_EXCLUSION:
-    case CAIRO_OPERATOR_HSL_HUE:
-    case CAIRO_OPERATOR_HSL_SATURATION:
-    case CAIRO_OPERATOR_HSL_COLOR:
-    case CAIRO_OPERATOR_HSL_LUMINOSITY:
     default:
 	return FALSE;
     }
 
     *ret_srcblend = srcblend;
     *ret_dstblend = dstblend;
 
     return TRUE;
@@ -404,97 +330,85 @@ static cairo_status_t
                            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;
-    pixman_image_t *pixman_image;
-    pixman_format_code_t pixman_format;
+    cairo_format_t cairo_format;
     cairo_status_t status;
     void *data;
     int   pitch;
 
-    if (surface->pixman_format == PIXMAN_invalid) {
-        if (intrest_rec != NULL) {
+    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;
         } else {
             source_rect.x = 0;
             source_rect.y = 0;
             surface->dfbsurface->GetSize (surface->dfbsurface,
                                           &source_rect.w, &source_rect.h);
         }
 
-        if (surface->tmpsurface != NULL) {
+        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;
-                surface->tmpformat = PIXMAN_invalid;
             }
         }
 
-        if (surface->tmpsurface == NULL) {
-	    DFBSurfacePixelFormat format;
-
+        cairo_format = _cairo_format_from_content (surface->content);
+        if (!surface->tmpsurface) {
             D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
 
-	    format = _cairo_to_directfb_format (_cairo_format_from_content (surface->base.content));
             status =
-                _directfb_buffer_surface_create (surface->dfb, format,
+                _directfb_buffer_surface_create (surface->dfb,
+                                                 _cairo_to_directfb_format (cairo_format),
                                                  source_rect.w, source_rect.h,
 						 &surface->tmpsurface);
-            if (unlikely (status))
+            if (status)
                 goto ERROR;
-
-	    surface->tmpformat = _directfb_to_pixman_format (format);
         }
         buffer = surface->tmpsurface;
-	pixman_format = surface->tmpformat;
-
 
 /*        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
-        DFBSurfaceCapabilities caps;
         if (caps & DSCAPS_FLIPPING) {
             DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y,
                                  .x2 = source_rect.x + source_rect.w - 1,
                                  .y2 = source_rect.y + source_rect.h - 1 };
             surface->dfbsurface->Flip (surface->dfbsurface, &region, DSFLIP_BLIT);
         } */
         buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0);
     } else {
         /*might be a subsurface get the offset*/
         surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
-        pixman_format = surface->pixman_format;
+        cairo_format = surface->format;
         buffer = surface->dfbsurface;
     }
 
     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;
     }
 
-    pixman_image = pixman_image_create_bits (pixman_format,
-					     source_rect.w, source_rect.h,
-					     data, pitch);
-    if (pixman_image == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto ERROR;
-    }
-
-    image = _cairo_image_surface_create_for_pixman_image (pixman_image,
-							  pixman_format);
+    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;
@@ -517,98 +431,94 @@ ERROR:
         buffer->Unlock (buffer);
         if (buffer != surface->dfbsurface)
             buffer->Release (buffer);
     }
     return status;
 }
 
 static cairo_surface_t *
-_cairo_directfb_surface_create_internal (IDirectFB *dfb,
-					 DFBSurfacePixelFormat format,
-					 cairo_content_t content,
-					 int              width,
-					 int              height)
+_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;
     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 (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    surface->dfb = dfb;
+    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 */
-        status =  _directfb_buffer_surface_create (dfb, format,
+        status =  _directfb_buffer_surface_create (surface->dfb,
+                                        _cairo_to_directfb_format (format),
                                         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 (dfb, format,
-						  width, height,
-						  &surface->dfbsurface);
+	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);
 	}
     }
 
     _cairo_surface_init (&surface->base,
 			 &_cairo_directfb_surface_backend,
 			 content);
-    surface->pixman_format = _directfb_to_pixman_format (format);
-    surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
-
+    surface->format  = format;
+    surface->content = content;
     surface->width   = width;
     surface->height  = height;
     surface->local   = TRUE;
     surface->blit_premultiplied = TRUE;
 
     return &surface->base;
 }
 
-static cairo_surface_t *
-_cairo_directfb_surface_create_similar (void            *abstract_src,
-                                        cairo_content_t  content,
-                                        int              width,
-                                        int              height)
-{
-    cairo_directfb_surface_t *other  = abstract_src;
-    DFBSurfacePixelFormat     format;
-
-    D_DEBUG_AT (CairoDFB_Surface,
-                "%s( src=%p, content=0x%x, width=%d, height=%d).\n",
-                __FUNCTION__, other, content, width, height);
-
-    width = (width <= 0) ? 1 : width;
-    height = (height<= 0) ? 1 : height;
-
-    format = _cairo_to_directfb_format (_cairo_format_from_content (content));
-    return _cairo_directfb_surface_create_internal (other->dfb, format,
-						    content, width, height);
-}
-
 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->tmpsurface) {
         surface->tmpsurface->Release (surface->tmpsurface);
         surface->tmpsurface = NULL;
     }
 
     if (surface->dfbsurface) {
         surface->dfbsurface->Release (surface->dfbsurface);
         surface->dfbsurface = NULL;
@@ -634,20 +544,21 @@ static cairo_status_t
 				      NULL, image_extra, DSLF_READ);
 }
 
 static void
 _cairo_directfb_surface_release_source_image (void                  *abstract_surface,
                                               cairo_image_surface_t *image,
                                               void                  *image_extra)
 {
+    cairo_directfb_surface_t *surface = abstract_surface;
     IDirectFBSurface *buffer = image_extra;
 
     D_DEBUG_AT (CairoDFB_Acquire,
-		"%s( release=%p ).\n", __FUNCTION__, abstract_surface);
+		"%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,
@@ -689,28 +600,29 @@ static void
     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->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
-        surface->dfbsurface->SetClip (surface->dfbsurface, &region);
-	surface->dfbsurface->Blit (surface->dfbsurface,
-				   buffer, NULL,
-				   image_rect->x, image_rect->y);
+	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,
+				       cairo_content_t	 content,
                                        int               src_x,
                                        int               src_y,
                                        int               width,
                                        int               height,
                                        int              *clone_offset_x,
                                        int              *clone_offset_y,
                                        cairo_surface_t **clone_out)
 {
@@ -723,60 +635,65 @@ static cairo_status_t
     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;
-	DFBSurfacePixelFormat format;
+	unsigned char         *dst, *src = image_src->data;
+	int                    pitch;
+	int                    i, j;
 	DFBResult              ret;
-	pixman_image_t	      *pixman_image;
-	void *data;
-	int pitch;
-
-	format = _directfb_from_pixman_format (image_src->pixman_format);
-	if (format == 0)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	clone = (cairo_directfb_surface_t *)
-	    _cairo_directfb_surface_create_internal (surface->dfb, format,
-						     image_src->base.content,
-						     width, height);
-	if (unlikely (clone->base.status))
+	    _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 *)&data, &pitch);
+				       DSLF_WRITE, (void *)&dst, &pitch);
 	if (ret) {
 	    DirectFBError ("IDirectFBSurface::Lock()", ret);
 	    cairo_surface_destroy (&clone->base);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
 
-	pixman_image = pixman_image_create_bits (clone->pixman_format,
-						 width, height,
-						 data, pitch);
-	if (unlikely (pixman_image == NULL)) {
-	    DirectFBError ("IDirectFBSurface::Lock()", ret);
-	    cairo_surface_destroy (&clone->base);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
+	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;
 
-	pixman_image_composite (PIXMAN_OP_SRC,
-				image_src->pixman_image,
-				NULL,
-				pixman_image,
-				src_x, src_y,
-				0, 0,
-				0, 0,
-				width, height);
+	    if (image_src->format == CAIRO_FORMAT_A8) {
+		src += src_x;
+		len  = width;
+	    } else {
+		src += src_x * 4;
+		len  = width * 4;
+	    }
 
-	pixman_image_unref (pixman_image);
+	    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;
     }
@@ -808,16 +725,18 @@ static cairo_int_status_t
     /* 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;
+
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
 	    const cairo_pattern_t *tmp;
 	    int              tmp_x, tmp_y;
 
 	    if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
 		sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
 		return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -840,43 +759,44 @@ static cairo_int_status_t
 	}
 
 	color = &((cairo_solid_pattern_t *) mask_pattern)->color;
     } else {
 	color = _cairo_stock_color (CAIRO_STOCK_WHITE);
     }
 
     status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+					     CAIRO_CONTENT_COLOR_ALPHA,
 					     *src_x, *src_y, width, height,
 					     CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
 					     (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->base.content & CAIRO_CONTENT_ALPHA) == 0) {
+    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->base.content & CAIRO_CONTENT_ALPHA) == 0) {
+    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)
@@ -973,37 +893,33 @@ static cairo_int_status_t
 _cairo_directfb_surface_composite (cairo_operator_t  op,
                                    const cairo_pattern_t  *src_pattern,
                                    const cairo_pattern_t  *mask_pattern,
                                    void             *abstract_dst,
                                    int  src_x,  int  src_y,
                                    int  mask_x, int  mask_y,
                                    int  dst_x,  int  dst_y,
                                    unsigned int      width,
-                                   unsigned int      height,
-				   cairo_region_t   *clip_region)
+                                   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          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);
 
-    if (! dst->supported_destination)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
     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);
     if (accel == DFXL_NONE) {
@@ -1020,17 +936,17 @@ static cairo_int_status_t
 	    _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 ((int) accel) {
+    switch (accel) {
     case DFXL_BLIT:
 	{
 	    DFBRectangle sr;
 
 	    is_integer_translation =
 		_cairo_matrix_is_integer_translation (&src_attr.matrix,
 						      &tx, &ty);
 	    assert (is_integer_translation);
@@ -1038,34 +954,36 @@ static cairo_int_status_t
 	    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, clip_region, NULL,
+		RUN_CLIPPED (dst, NULL,
 			     dst->dfbsurface->Blit (dst->dfbsurface,
 						    src->dfbsurface,
-						    &sr, dst_x, dst_y));
+						    &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_region, &clip,
+		RUN_CLIPPED (dst, &clip,
 			     dst->dfbsurface->TileBlit (dst->dfbsurface,
 							src->dfbsurface,
-							&sr, dst_x, dst_y));
+							&sr,
+							dst_x, dst_y));
 	    }
 	    break;
 	}
 
     case DFXL_STRETCHBLIT:
 	{
 	    DFBRectangle sr, dr;
 	    double       x1, y1, x2, y2;
@@ -1082,20 +1000,19 @@ static cairo_int_status_t
 
 	    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, clip_region, NULL,
+	    RUN_CLIPPED (dst, NULL,
 			 dst->dfbsurface->StretchBlit (dst->dfbsurface,
-						       src->dfbsurface,
-						       &sr, &dr));
+						       src->dfbsurface, &sr, &dr));
 	    break;
 	}
 
     case DFXL_TEXTRIANGLES:
 	{
 	    DFBRegion clip;
 	    DFBVertex v[4];
 	    float     x1, y1, x2, y2;
@@ -1107,63 +1024,65 @@ static cairo_int_status_t
 
 	    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);
+	    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);
+	    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);
+	    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);
+	    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_region, &clip,
+	    RUN_CLIPPED (dst, &clip,
 			 dst->dfbsurface->TextureTriangles (dst->dfbsurface,
-							    src->dfbsurface,
-							    v, NULL,
-							    4, DTTF_FAN));
+							    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 CAIRO_STATUS_SUCCESS;
+    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,
@@ -1176,34 +1095,34 @@ static cairo_int_status_t
     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 (! dst->supported_destination)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    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 (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->base.content & CAIRO_CONTENT_ALPHA) == 0) {
+    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)
@@ -1225,17 +1144,17 @@ static cairo_int_status_t
 
     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;
     }
 
-    RUN_CLIPPED (dst, NULL, NULL,
+    RUN_CLIPPED (dst, NULL,
 		 dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
 
     return CAIRO_STATUS_SUCCESS;
 }
 #endif
 
 #if DFB_COMPOSITE_TRAPEZOIDS
 static cairo_int_status_t
@@ -1243,35 +1162,31 @@ static cairo_int_status_t
                                               const cairo_pattern_t   *pattern,
                                               void              *abstract_dst,
                                               cairo_antialias_t  antialias,
                                               int  src_x,   int  src_y,
                                               int  dst_x,   int  dst_y,
                                               unsigned int       width,
                                               unsigned int       height,
                                               cairo_trapezoid_t *traps,
-                                              int                num_traps,
-					      cairo_region_t	*clip_region)
+                                              int                num_traps)
 {
     cairo_directfb_surface_t   *dst = abstract_dst;
     cairo_directfb_surface_t   *src;
     cairo_surface_attributes_t  src_attr;
     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 (! dst->supported_destination)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
     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;
 
     status = _directfb_prepare_composite (dst, pattern, NULL, op,
@@ -1356,32 +1271,89 @@ static cairo_int_status_t
 
             traps++;
         }
 #undef ADD_TRI
 #undef ADD_TRI_V
 
         D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
 
-        RUN_CLIPPED (dst, clip_region, NULL,
+        RUN_CLIPPED (dst, NULL,
                      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 status;
 }
 #endif /* DFB_COMPOSITE_TRAPEZOIDS */
 
-static cairo_bool_t
+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);
+
+    if (region) {
+	int              n_rects;
+	cairo_status_t   status;
+	int              i;
+
+	surface->has_clip = TRUE;
+
+	n_rects = cairo_region_num_rectangles (region);
+
+	if (n_rects == 0)
+	    return CAIRO_STATUS_SUCCESS;
+
+	if (surface->n_clips != n_rects) {
+	    if (surface->clips)
+		free (surface->clips);
+
+	    surface->clips = _cairo_malloc_ab (n_rects, sizeof (DFBRegion));
+	    if (!surface->clips) {
+		surface->n_clips = 0;
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+
+	    surface->n_clips = n_rects;
+	}
+
+	for (i = 0; i < n_rects; i++) {
+	    cairo_rectangle_int_t rect;
+
+	    cairo_region_get_rectangle (region, i, &rect);
+	    
+	    surface->clips[i].x1 = rect.x;
+	    surface->clips[i].y1 = rect.y;
+	    surface->clips[i].x2 = rect.x + rect.width - 1;
+	    surface->clips[i].y2 = rect.y + rect.height - 1;
+	}
+    } 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);
@@ -1391,17 +1363,17 @@ static cairo_bool_t
 				      &surface->width, &surface->height);
     }
 
     rectangle->x = 0;
     rectangle->y = 0;
     rectangle->width  = surface->width;
     rectangle->height = surface->height;
 
-    return TRUE;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 #if DFB_SHOW_GLYPHS
 static cairo_status_t
 _directfb_allocate_font_cache (IDirectFB *dfb,
 			       int width, int height,
 			       cairo_directfb_font_cache_t **out)
 {
@@ -1430,17 +1402,16 @@ static cairo_status_t
 
 static void
 _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
 {
     cache->dfbsurface->Release (cache->dfbsurface);
     free (cache);
 }
 
-/* XXX hook into rtree font cache from drm */
 static cairo_status_t
 _directfb_acquire_font_cache (cairo_directfb_surface_t     *surface,
                               cairo_scaled_font_t          *scaled_font,