Bug 542605. Update cairo to 12d521df8acc483b2daa844d4f05dc2fe2765ba6. r=vlad,jwatt,bas
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Mon, 05 Apr 2010 22:28:54 -0400
changeset 40464 2b9a4c865737a743e89d81ccff6931abd5ea6137
parent 40463 67f4c546d40329f52d64b4290779008c670fbdfa
child 40465 4238959a7b0c8cc18410c127f62d04d66d18e4c2
child 40466 d113822ad20fc82681ba338fa3e16a4b78c02303
push idunknown
push userunknown
push dateunknown
reviewersvlad, jwatt, bas
bugs542605
milestone1.9.3a4pre
Bug 542605. Update cairo to 12d521df8acc483b2daa844d4f05dc2fe2765ba6. r=vlad,jwatt,bas
gfx/cairo/README
gfx/cairo/add-a-stash-of-cairo_t-s.patch
gfx/cairo/bgr.patch
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-analysis-surface-private.h
gfx/cairo/cairo/src/cairo-analysis-surface.c
gfx/cairo/cairo/src/cairo-arc.c
gfx/cairo/cairo/src/cairo-atomic-private.h
gfx/cairo/cairo/src/cairo-base64-stream.c
gfx/cairo/cairo/src/cairo-base85-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-bentley-ottmann.c
gfx/cairo/cairo/src/cairo-clip-private.h
gfx/cairo/cairo/src/cairo-clip.c
gfx/cairo/cairo/src/cairo-combsort-private.h
gfx/cairo/cairo/src/cairo-d2d-private.h
gfx/cairo/cairo/src/cairo-d2d-surface.cpp
gfx/cairo/cairo/src/cairo-ddraw-private.h
gfx/cairo/cairo/src/cairo-ddraw-surface.c
gfx/cairo/cairo/src/cairo-debug.c
gfx/cairo/cairo/src/cairo-directfb-surface.c
gfx/cairo/cairo/src/cairo-drm.h
gfx/cairo/cairo/src/cairo-dwrite-font.cpp
gfx/cairo/cairo/src/cairo-dwrite-private.h
gfx/cairo/cairo/src/cairo-eagle-context.c
gfx/cairo/cairo/src/cairo-features-win32.h
gfx/cairo/cairo/src/cairo-fixed-private.h
gfx/cairo/cairo/src/cairo-fixed-type-private.h
gfx/cairo/cairo/src/cairo-font-face-twin.c
gfx/cairo/cairo/src/cairo-freelist-private.h
gfx/cairo/cairo/src/cairo-freelist.c
gfx/cairo/cairo/src/cairo-ft-font.c
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-glitz-surface.c
gfx/cairo/cairo/src/cairo-glx-context.c
gfx/cairo/cairo/src/cairo-gstate.c
gfx/cairo/cairo/src/cairo-hash.c
gfx/cairo/cairo/src/cairo-hull.c
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/cairo/src/cairo-matrix.c
gfx/cairo/cairo/src/cairo-meta-surface.c
gfx/cairo/cairo/src/cairo-misc.c
gfx/cairo/cairo/src/cairo-mutex-impl-private.h
gfx/cairo/cairo/src/cairo-mutex-list-private.h
gfx/cairo/cairo/src/cairo-no-features.h
gfx/cairo/cairo/src/cairo-os2-surface.c
gfx/cairo/cairo/src/cairo-output-stream-private.h
gfx/cairo/cairo/src/cairo-output-stream.c
gfx/cairo/cairo/src/cairo-paginated-private.h
gfx/cairo/cairo/src/cairo-paginated-surface-private.h
gfx/cairo/cairo/src/cairo-paginated-surface.c
gfx/cairo/cairo/src/cairo-path-bounds.c
gfx/cairo/cairo/src/cairo-path-fill.c
gfx/cairo/cairo/src/cairo-path-fixed-private.h
gfx/cairo/cairo/src/cairo-path-fixed.c
gfx/cairo/cairo/src/cairo-path-in-fill.c
gfx/cairo/cairo/src/cairo-path-stroke.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-operators.c
gfx/cairo/cairo/src/cairo-pdf-surface-private.h
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-pen.c
gfx/cairo/cairo/src/cairo-polygon.c
gfx/cairo/cairo/src/cairo-ps-surface-private.h
gfx/cairo/cairo/src/cairo-ps-surface.c
gfx/cairo/cairo/src/cairo-qt.h
gfx/cairo/cairo/src/cairo-quartz-font.c
gfx/cairo/cairo/src/cairo-quartz-image-surface.c
gfx/cairo/cairo/src/cairo-quartz-private.h
gfx/cairo/cairo/src/cairo-quartz-surface.c
gfx/cairo/cairo/src/cairo-recording-surface-private.h
gfx/cairo/cairo/src/cairo-recording-surface.c
gfx/cairo/cairo/src/cairo-rectangle.c
gfx/cairo/cairo/src/cairo-region-private.h
gfx/cairo/cairo/src/cairo-region.c
gfx/cairo/cairo/src/cairo-rtree-private.h
gfx/cairo/cairo/src/cairo-rtree.c
gfx/cairo/cairo/src/cairo-scaled-font-private.h
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-scaled-font.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-skiplist-private.h
gfx/cairo/cairo/src/cairo-skiplist.c
gfx/cairo/cairo/src/cairo-slope-private.h
gfx/cairo/cairo/src/cairo-slope.c
gfx/cairo/cairo/src/cairo-spans-private.h
gfx/cairo/cairo/src/cairo-spans.c
gfx/cairo/cairo/src/cairo-spline.c
gfx/cairo/cairo/src/cairo-stroke-style.c
gfx/cairo/cairo/src/cairo-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-fallback-private.h
gfx/cairo/cairo/src/cairo-surface-fallback.c
gfx/cairo/cairo/src/cairo-surface-private.h
gfx/cairo/cairo/src/cairo-surface-wrapper-private.h
gfx/cairo/cairo/src/cairo-surface-wrapper.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-svg-surface-private.h
gfx/cairo/cairo/src/cairo-svg-surface.c
gfx/cairo/cairo/src/cairo-tee-surface-private.h
gfx/cairo/cairo/src/cairo-tee-surface.c
gfx/cairo/cairo/src/cairo-tor-scan-converter.c
gfx/cairo/cairo/src/cairo-toy-font-face.c
gfx/cairo/cairo/src/cairo-traps.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-type3-glyph-surface-private.h
gfx/cairo/cairo/src/cairo-type3-glyph-surface.c
gfx/cairo/cairo/src/cairo-types-private.h
gfx/cairo/cairo/src/cairo-user-font.c
gfx/cairo/cairo/src/cairo-vg-surface.c
gfx/cairo/cairo/src/cairo-vg.h
gfx/cairo/cairo/src/cairo-wideint-private.h
gfx/cairo/cairo/src/cairo-wideint-type-private.h
gfx/cairo/cairo/src/cairo-wideint.c
gfx/cairo/cairo/src/cairo-win32-font.c
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-xcb-surface.c
gfx/cairo/cairo/src/cairo-xlib-display.c
gfx/cairo/cairo/src/cairo-xlib-private.h
gfx/cairo/cairo/src/cairo-xlib-screen.c
gfx/cairo/cairo/src/cairo-xlib-surface-private.h
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo-xlib-xrender-private.h
gfx/cairo/cairo/src/cairo-xml-surface.c
gfx/cairo/cairo/src/cairo-xml.h
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/cairo/src/test-fallback-surface.c
gfx/cairo/cairo/src/test-paginated-surface.c
gfx/cairo/cairo/src/test-paginated-surface.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/thebes/src/gfxContext.cpp
layout/reftests/bugs/456219-1-mask-wArA.png
layout/reftests/bugs/456219-1-mask-wArB.png
layout/reftests/bugs/456219-1-mask-wArC.png
layout/reftests/bugs/456219-1-mask-wArD.png
layout/reftests/bugs/456219-1-mask-wArE.png
layout/reftests/bugs/456219-1-mask-wBrA.png
layout/reftests/bugs/456219-1-mask-wBrB.png
layout/reftests/bugs/456219-1-mask-wBrC.png
layout/reftests/bugs/456219-1-mask-wBrD.png
layout/reftests/bugs/456219-1-mask-wBrE.png
layout/reftests/bugs/456219-1-mask-wCrA.png
layout/reftests/bugs/456219-1-mask-wCrB.png
layout/reftests/bugs/456219-1-mask-wCrC.png
layout/reftests/bugs/456219-1-mask-wCrD.png
layout/reftests/bugs/456219-1-mask-wCrE.png
layout/reftests/bugs/456219-1-mask-wDrA.png
layout/reftests/bugs/456219-1-mask-wDrB.png
layout/reftests/bugs/456219-1-mask-wDrC.png
layout/reftests/bugs/456219-1-mask-wDrD.png
layout/reftests/bugs/456219-1-mask-wDrE.png
layout/reftests/bugs/456219-1-mask-wErA.png
layout/reftests/bugs/456219-1-mask-wErB.png
layout/reftests/bugs/456219-1-mask-wErC.png
layout/reftests/bugs/456219-1-mask-wErD.png
layout/reftests/bugs/456219-1-mask-wErE.png
layout/reftests/bugs/reftest.list
layout/svg/base/src/nsSVGImageFrame.cpp
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -63,16 +63,42 @@ 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
+
 ==== 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 ====
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/add-a-stash-of-cairo_t-s.patch
@@ -0,0 +1,75 @@
+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 {
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/bgr.patch
@@ -0,0 +1,104 @@
+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,17 +69,20 @@ endif
 
 CSRCS   = \
         cairo.c \
         cairo-analysis-surface.c \
         cairo-arc.c \
         cairo-array.c \
 	cairo-atomic.c \
         cairo-bentley-ottmann.c \
-        cairo-cache.c \
+	cairo-bentley-ottmann-rectilinear.c \
+	cairo-bentley-ottmann-rectangular.c \
+        cairo-base64-stream.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 \
@@ -87,41 +90,43 @@ 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,23 +33,21 @@
  */
 
 #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,
-				int			 width,
-				int			 height);
+_cairo_analysis_surface_create (cairo_surface_t		*target);
 
 cairo_private void
 _cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
-				 cairo_matrix_t  *ctm);
+				 const 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,32 +33,30 @@
  *      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-meta-surface-private.h"
+#include "cairo-recording-surface-private.h"
+#include "cairo-region-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
@@ -73,90 +71,67 @@ 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_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_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_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_meta_surface_pattern (cairo_analysis_surface_t	*surface,
-			       const cairo_pattern_t *pattern)
+_analyze_recording_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_rectangle_int_t old_clip;
-    cairo_rectangle_int_t meta_extents;
-    int old_width;
-    int old_height;
+    cairo_status_t status;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
     surface_pattern = (const cairo_surface_pattern_t *) pattern;
-    assert (_cairo_surface_is_meta (surface_pattern->surface));
+    assert (_cairo_surface_is_recording (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_meta_surface_replay_and_create_regions (surface_pattern->surface,
-							    analysis);
-    if (status == CAIRO_STATUS_SUCCESS)
-	status = analysis->status;
+    status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
+							    &surface->base);
 
     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 */
@@ -169,36 +144,43 @@ static cairo_int_status_t
 	{
 	    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 	}
     }
 
     _cairo_box_from_rectangle (&bbox, rect);
 
     if (surface->has_ctm) {
+	int tx, ty;
 
-	_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
+	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);
 
-	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;
+	    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;
+		}
 	    }
-	    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;
@@ -229,29 +211,28 @@ 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;
-	status = cairo_region_union_rectangle (&surface->supported_region, rect);
-	return status;
+	return cairo_region_union_rectangle (&surface->supported_region, rect);
     }
 
     /* 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 meta surface as using
+     * unsupported operations to the recording 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;
@@ -265,360 +246,342 @@ 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_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
+static cairo_bool_t
 _cairo_analysis_surface_get_extents (void			*abstract_surface,
 				     cairo_rectangle_int_t	*rectangle)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
 
     return _cairo_surface_get_extents (surface->target, rectangle);
 }
 
-static cairo_int_status_t
-_cairo_analysis_surface_paint (void			*abstract_surface,
-			       cairo_operator_t		op,
-			       const cairo_pattern_t	*source,
-			       cairo_rectangle_int_t    *paint_extents)
+static void
+_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
 {
-    cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status, backend_status;
-    cairo_rectangle_int_t  extents;
+    const cairo_rectangle_int_t *clip_extents;
     cairo_bool_t is_empty;
 
-    if (!surface->target->backend->paint)
-	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    else
-	backend_status = (*surface->target->backend->paint) (surface->target, op,
-                                                             source, NULL);
+    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);
+}
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _analyze_meta_surface_pattern (surface, source);
+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;
 
-    status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (_cairo_status_is_error (status))
-	return status;
+    is_empty = _cairo_surface_get_extents (&surface->base, 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);
+	_cairo_pattern_get_extents (source, &source_extents);
+	is_empty = _cairo_rectangle_intersect (extents, &source_extents);
     }
 
-    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
-    if (paint_extents)
-	*paint_extents = extents;
-
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    _rectangle_intersect_clip (extents, clip);
 }
 
 static cairo_int_status_t
-_cairo_analysis_surface_mask (void		*abstract_surface,
-			      cairo_operator_t	 op,
+_cairo_analysis_surface_paint (void			*abstract_surface,
+			       cairo_operator_t		op,
+			       const cairo_pattern_t	*source,
+			       cairo_clip_t		*clip)
+{
+    cairo_analysis_surface_t *surface = abstract_surface;
+    cairo_status_t	     backend_status;
+    cairo_rectangle_int_t  extents;
+
+    if (surface->target->backend->paint == NULL) {
+	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;
+    }
+
+    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);
+
+    return _add_operation (surface, &extents, backend_status);
+}
+
+static cairo_int_status_t
+_cairo_analysis_surface_mask (void			*abstract_surface,
+			      cairo_operator_t		 op,
 			      const cairo_pattern_t	*source,
 			      const cairo_pattern_t	*mask,
-			      cairo_rectangle_int_t 	*mask_extents)
+			      cairo_clip_t		*clip)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_int_status_t	      status, backend_status;
+    cairo_int_status_t	      backend_status;
     cairo_rectangle_int_t   extents;
     cairo_bool_t is_empty;
 
-    if (!surface->target->backend->mask)
+    if (surface->target->backend->mask == NULL) {
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    else
-	backend_status = (*surface->target->backend->mask) (surface->target, op,
-                                                            source, mask, NULL);
+    } else {
+	backend_status =
+	    surface->target->backend->mask (surface->target,
+					    op, source, mask, clip);
+	if (_cairo_status_is_error (backend_status))
+	    return backend_status;
+    }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_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_meta (surface_pattern->surface)) {
+	    if (_cairo_surface_is_recording (surface_pattern->surface)) {
 		backend_source_status =
-		    _analyze_meta_surface_pattern (surface, source);
+		    _analyze_recording_surface_pattern (surface, source);
 		if (_cairo_status_is_error (backend_source_status))
 		    return backend_source_status;
 	    }
 	}
 
 	if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
-	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
+	    if (_cairo_surface_is_recording (surface_pattern->surface)) {
 		backend_mask_status =
-		    _analyze_meta_surface_pattern (surface, mask);
+		    _analyze_recording_surface_pattern (surface, mask);
 		if (_cairo_status_is_error (backend_mask_status))
 		    return backend_mask_status;
 	    }
 	}
 
 	backend_status =
 	    _cairo_analysis_surface_merge_status (backend_source_status,
 						  backend_mask_status);
     }
 
-    status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (_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);
-    }
+    _cairo_analysis_surface_operation_extents (surface,
+					       op, source, clip,
+					       &extents);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	status = _cairo_pattern_get_extents (mask, &mask_extents);
-	if (unlikely (status))
-	    return status;
+	_cairo_pattern_get_extents (mask, &mask_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
 
-	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
 
-    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
-    if (mask_extents)
-	*mask_extents = extents;
-
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    return _add_operation (surface, &extents, backend_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_rectangle_int_t   *stroke_extents)
+				cairo_clip_t		*clip)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status, backend_status;
+    cairo_status_t	     backend_status;
     cairo_rectangle_int_t    extents;
     cairo_bool_t             is_empty;
 
-    if (!surface->target->backend->stroke)
+    if (surface->target->backend->stroke == NULL) {
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    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);
+    } 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;
     }
 
-    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    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);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	_cairo_path_fixed_approximate_stroke_extents (path,
-						      style, ctm,
-						      &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;
+	}
 
 	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
-    if (stroke_extents)
-	*stroke_extents = extents;
 
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    return _add_operation (surface, &extents, backend_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_rectangle_int_t     *fill_extents)
+			      cairo_clip_t		*clip)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
-    cairo_status_t	     status, backend_status;
+    cairo_status_t	     backend_status;
     cairo_rectangle_int_t    extents;
     cairo_bool_t             is_empty;
 
-    if (!surface->target->backend->fill)
+    if (surface->target->backend->fill == NULL) {
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    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);
+    } 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;
     }
 
-    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    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);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_int_t mask_extents;
 
-	_cairo_path_fixed_approximate_fill_extents (path,
-						    &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);
+	}
 	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
-    if (fill_extents)
-	*fill_extents = extents;
 
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    return _add_operation (surface, &extents, backend_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,
-				     int                  *remaining_glyphs,
-				     cairo_rectangle_int_t *show_glyphs_extents)
+				     cairo_clip_t         *clip,
+				     int                  *remaining_glyphs)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
     cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
-    if (surface->target->backend->show_glyphs)
-	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
-								   source,
-								   glyphs, num_glyphs,
-								   scaled_font,
-								   remaining_glyphs, 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);
+    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;
+    }
     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);
     }
 
-    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+    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);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
 							  glyphs,
 							  num_glyphs,
-							  &glyph_extents);
+							  &glyph_extents,
+							  NULL);
 	if (unlikely (status))
 	    return status;
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
-    if (show_glyphs_extents)
-	*show_glyphs_extents = extents;
 
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    return _add_operation (surface, &extents, backend_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);
@@ -631,80 +594,78 @@ 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_rectangle_int_t     *show_text_glyphs_extents)
+					  cairo_clip_t		    *clip)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
     cairo_rectangle_int_t    extents, glyph_extents;
     cairo_bool_t             is_empty;
 
     /* Adapted from _cairo_surface_show_glyphs */
     backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
-    if (surface->target->backend->show_text_glyphs)
-	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
-								     source,
-								     utf8, utf8_len,
-								     glyphs, num_glyphs,
-								     clusters, num_clusters, cluster_flags,
-								     scaled_font, NULL);
-    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
+    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)
+    {
 	int remaining_glyphs = num_glyphs;
-	backend_status = surface->target->backend->show_glyphs (surface->target, op,
-								source,
-								glyphs, num_glyphs,
-								scaled_font,
-								&remaining_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;
+
 	glyphs += num_glyphs - remaining_glyphs;
 	num_glyphs = remaining_glyphs;
 	if (remaining_glyphs == 0)
 	    backend_status = CAIRO_STATUS_SUCCESS;
     }
 
-    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
-	backend_status = _analyze_meta_surface_pattern (surface, source);
-
-    status = _cairo_surface_get_extents (&surface->base, &extents);
-    if (_cairo_status_is_error (status))
-	return status;
+    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
+	backend_status = _analyze_recording_surface_pattern (surface, source);
 
-    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);
+    _cairo_analysis_surface_operation_extents (surface,
+					       op, source, clip,
+					       &extents);
 
     if (_cairo_operator_bounded_by_mask (op)) {
 	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
 							  glyphs,
 							  num_glyphs,
-							  &glyph_extents);
+							  &glyph_extents,
+							  NULL);
 	if (unlikely (status))
 	    return status;
 
 	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
     }
-    if (show_text_glyphs_extents)
-	*show_text_glyphs_extents = extents;
 
-    status = _add_operation (surface, &extents, backend_status);
-
-    return status;
+    return _add_operation (surface, &extents, backend_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 */
@@ -713,44 +674,39 @@ 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,
-				int			 width,
-				int			 height)
+_cairo_analysis_surface_create (cairo_surface_t		*target)
 {
     cairo_analysis_surface_t *surface;
     cairo_status_t status;
 
     status = target->status;
     if (unlikely (status))
 	return _cairo_surface_create_in_error (status);
 
@@ -758,62 +714,48 @@ 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,
-				 cairo_matrix_t  *ctm)
+				 const 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;
 
@@ -867,63 +809,59 @@ 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_rectangle_int_t  *extents);
+				 cairo_clip_t		*clip);
 
 typedef cairo_int_status_t
 (*_mask_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
 				 const cairo_pattern_t	*mask,
-				 cairo_rectangle_int_t  *extents);
+				 cairo_clip_t		*clip);
 
 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_rectangle_int_t  *extents);
+				 cairo_clip_t		*clip);
 
 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_rectangle_int_t  *extents);
+				 cairo_clip_t		*clip);
 
 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,
-				 int			*remaining_glyphs,
-				 cairo_rectangle_int_t  *extents);
+				 cairo_clip_t		*clip,
+				 int			*remaining_glyphs);
 
 static const cairo_surface_backend_t cairo_null_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_NULL,
 
     NULL, /* create_similar */
     NULL, /* finish */
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
@@ -932,33 +870,30 @@ 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 (int) ceil (angle / max_angle);
+    return ceil (fabs (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,24 +38,33 @@
 #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;
@@ -65,16 +74,45 @@ 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);
 
@@ -82,19 +120,16 @@ 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
@@ -102,22 +137,24 @@ 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((int *)x, oldv, newv)
+    _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)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 ((int *) status, CAIRO_STATUS_SUCCESS, err); \
+    int ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
     (void) ret__; \
 } while (0)
 
 CAIRO_END_DECLS
 
 #endif
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-base64-stream.c
@@ -0,0 +1,143 @@
+/* -*- 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,19 +97,16 @@ 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;
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectangular.c
@@ -0,0 +1,739 @@
+/*
+ * 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;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectilinear.c
@@ -0,0 +1,582 @@
+/*
+ * 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,11 +1,12 @@
 /*
  * 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.
@@ -26,145 +27,224 @@
  * 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_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;
-};
-
 struct _cairo_bo_edge {
-    cairo_bo_point32_t top;
-    cairo_bo_point32_t middle;
-    cairo_bo_point32_t bottom;
-    int dir;
+    cairo_edge_t edge;
     cairo_bo_edge_t *prev;
     cairo_bo_edge_t *next;
-    cairo_bo_trap_t *deferred_trap;
-    sweep_line_elt_t *sweep_line_elt;
-};
-
-struct _sweep_line_elt {
-    cairo_bo_edge_t *edge;
-    skip_elt_t elt;
+    cairo_bo_trap_t deferred_trap;
 };
 
-#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)
+/* 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 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_INTERSECTION,
+    CAIRO_BO_EVENT_TYPE_START
 } 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_point32_t point;
-    skip_elt_t elt;
-} cairo_bo_event_t;
+} cairo_bo_queue_event_t;
 
-#define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
+typedef struct _pqueue {
+    int size, max_size;
+
+    cairo_bo_event_t **elements;
+    cairo_bo_event_t *elements_embedded[1024];
+} pqueue_t;
 
 typedef struct _cairo_bo_event_queue {
-    cairo_skip_list_t intersection_queue;
-
-    cairo_bo_event_t *startstop_events;
-    cairo_bo_event_t **sorted_startstop_event_ptrs;
+    cairo_freepool_t pool;
+    pqueue_t pqueue;
+    cairo_bo_event_t **start_events;
 } cairo_bo_event_queue_t;
 
-/* This structure extends #cairo_skip_list_t, which must come first. */
 typedef struct _cairo_bo_sweep_line {
-    cairo_skip_list_t active_edges;
     cairo_bo_edge_t *head;
-    cairo_bo_edge_t *tail;
+    cairo_bo_edge_t *stopped;
     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 = a->y - b->y;
-    if (cmp) return cmp;
+    int cmp;
+
+    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) = (bottom.x - top.x, bottom.y - top.y)
+ *	(dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.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)
@@ -178,27 +258,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 int
-_slope_compare (cairo_bo_edge_t *a,
-		cairo_bo_edge_t *b)
+static inline int
+_slope_compare (const cairo_bo_edge_t *a,
+		const 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->bottom.x - a->top.x;
-    int32_t bdx = b->bottom.x - b->top.x;
+    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;
 
     /* 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;
@@ -206,18 +286,18 @@ static 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->bottom.y - a->top.y;
-	int32_t bdy = b->bottom.y - b->top.y;
+	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;
 	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);
     }
 }
 
 /*
@@ -265,33 +345,56 @@ 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;
 
-    ady = a->bottom.y - a->top.y;
-    adx = a->bottom.x - a->top.x;
+    /* 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;
     if (adx == 0)
 	have_dx_adx_bdx &= ~HAVE_ADX;
 
-    bdy = b->bottom.y - b->top.y;
-    bdx = b->bottom.x - b->top.x;
+    bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+    bdx = b->edge.line.p2.x - b->edge.line.p1.x;
     if (bdx == 0)
 	have_dx_adx_bdx &= ~HAVE_BDX;
 
-    dx = a->top.x - b->top.x;
+    dx = a->edge.line.p1.x - b->edge.line.p1.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->top.y)
-#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->top.y)
+#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)
     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:
@@ -299,17 +402,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->top.y == b->top.y) { /* common origin */
+	} else if (a->edge.line.p1.y == b->edge.line.p1.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);
@@ -318,33 +421,34 @@ 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->top.y - y, adx);
+	    dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
 
 	    return _cairo_int64_cmp (ady_dx, dy_adx);
 	}
     case HAVE_DX_BDX:
 	/* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
 	if ((bdx ^ dx) < 0) {
 	    return dx;
 	} else {
 	    cairo_int64_t bdy_dx, dy_bdx;
 
 	    bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
-	    dy_bdx = _cairo_int32x32_64_mul (y - b->top.y, bdx);
+	    dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.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
 }
 
 /*
@@ -372,26 +476,31 @@ static int
 edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
 			      int32_t y,
 			      int32_t x)
 {
     int32_t adx, ady;
     int32_t dx, dy;
     cairo_int64_t L, R;
 
-    adx = a->bottom.x - a->top.x;
-    dx = x - a->top.x;
+    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;
 
     if (adx == 0)
 	return -dx;
-    if ((adx ^ dx) < 0)
+    if (dx == 0 || (adx ^ dx) < 0)
 	return adx;
 
-    dy = y - a->top.y;
-    ady = a->bottom.y - a->top.y;
+    dy = y - a->edge.line.p1.y;
+    ady = a->edge.line.p2.y - a->edge.line.p1.y;
 
     L = _cairo_int32x32_64_mul (dy, adx);
     R = _cairo_int32x32_64_mul (dx, ady);
 
     return _cairo_int64_cmp (L, R);
 }
 
 static int
@@ -407,311 +516,125 @@ 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->top.y)
-	ax = a->top.x;
-    else if (y == a->bottom.y)
-	ax = a->bottom.x;
+    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;
     else
 	have_ax_bx &= ~HAVE_AX;
 
-    if (y == b->top.y)
-	bx = b->top.x;
-    else if (y == b->bottom.y)
-	bx = b->bottom.x;
+    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;
     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 int
-_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t	*sweep_line,
-				    cairo_bo_edge_t		*a,
-				    cairo_bo_edge_t		*b)
+static inline int
+_line_equal (const cairo_line_t *a, const cairo_line_t *b)
 {
-    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;
+    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;
 }
 
 static int
-_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)
+_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)
 {
     int cmp;
 
-    /* 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);
+    /* 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);
 	if (cmp)
 	    return cmp;
-    }
-    else if (a->type == CAIRO_BO_EVENT_TYPE_STOP) {
-	cmp = _cairo_bo_point32_compare (&a->e1->top,
-					 &b->e1->top);
+
+	/* 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;
     }
-    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;
-     }
 
-    /* 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;
+    /* We've got two collinear edges now. */
+    return b->edge.bottom - a->edge.bottom;
 }
 
 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 */
-    ad = _cairo_int32x32_64_mul (a, d);
-    bc = _cairo_int32x32_64_mul (b, c);
-
-    return _cairo_int64_sub (ad, bc);
+    return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
+			     _cairo_int32x32_64_mul (b, c));
 }
 
 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 */
-    ad = _cairo_int64x32_128_mul (a, d);
-    bc = _cairo_int64x32_128_mul (c, b);
-
-    return _cairo_int128_sub (ad, bc);
+    return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
+			      _cairo_int64x32_128_mul (c, b));
 }
 
 /* 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_bo_status_t
+static cairo_bool_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->top.x - a->bottom.x;
-    int32_t dy1 = a->top.y - a->bottom.y;
+    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 dx2 = b->top.x - b->bottom.x;
-    int32_t dy2 = b->top.y - b->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;
 
     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)
@@ -722,68 +645,92 @@ 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->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;
+    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);
     if (_cairo_int64_negative (den_det)) {
 	if (_cairo_int64_ge (den_det, R))
-	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+	    return FALSE;
     } else {
 	if (_cairo_int64_le (den_det, R))
-	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+	    return FALSE;
     }
 
-    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;
+    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);
     if (_cairo_int64_negative (den_det)) {
 	if (_cairo_int64_ge (den_det, R))
-	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+	    return FALSE;
     } else {
 	if (_cairo_int64_le (den_det, R))
-	    return CAIRO_BO_STATUS_NO_INTERSECTION;
+	    return FALSE;
     }
 
     /* We now know that the two lines should intersect within range. */
 
-    a_det = det32_64 (a->top.x, a->top.y,
-		      a->bottom.x, a->bottom.y);
-    b_det = det32_64 (b->top.x, b->top.y,
-		      b->bottom.x, b->bottom.y);
+    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);
 
     /* 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 CAIRO_BO_STATUS_NO_INTERSECTION;
+	return FALSE;
+#if 0
+    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);
-    intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
 
     /* y = det (a_det, dy1, b_det, dy2) / den_det */
     qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
 						       b_det, dy2),
 					 den_det);
     if (_cairo_int64_eq (qr.rem, den_det))
-	return CAIRO_BO_STATUS_NO_INTERSECTION;
-    intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
+	return FALSE;
+#if 0
     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 CAIRO_BO_STATUS_INTERSECTION;
+    return TRUE;
 }
 
 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)
@@ -820,18 +767,20 @@ 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->top.y);
-    cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->bottom.y);
+    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);
 
     if (cmp_top < 0 || cmp_bottom > 0)
     {
 	return FALSE;
     }
 
     if (cmp_top > 0 && cmp_bottom < 0)
     {
@@ -844,20 +793,29 @@ 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)
-	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);
+    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;
+    }
 }
 
 /* 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
@@ -866,317 +824,394 @@ 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_bo_status_t
+static cairo_bool_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;
 
-    status = intersect_lines (a, b, &quorem);
-    if (status)
-	return status;
+    if (! intersect_lines (a, b, &quorem))
+	return FALSE;
 
     if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
-	return CAIRO_BO_STATUS_NO_INTERSECTION;
+	return FALSE;
 
     if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
-	return CAIRO_BO_STATUS_NO_INTERSECTION;
+	return FALSE;
 
     /* 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 CAIRO_BO_STATUS_INTERSECTION;
+    return TRUE;
+}
+
+static inline int
+cairo_bo_event_compare (const cairo_bo_event_t *a,
+			const cairo_bo_event_t *b)
+{
+    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);
+}
+
+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 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)
+static inline cairo_status_t
+_pqueue_push (pqueue_t *pq, 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;
-}
+    event->point = *point;
 
-static cairo_status_t
-_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
-			      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;
+    return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event);
 }
 
 static void
 _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
 			      cairo_bo_event_t	     *event)
 {
-    if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
-	_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
+    _cairo_freepool_free (&queue->pool, event);
 }
 
 static cairo_bo_event_t *
 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
 {
-    skip_elt_t *elt = event_queue->intersection_queue.chains[0];
-    cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
-    cairo_bo_event_t *startstop;
+    cairo_bo_event_t *event, *cmp;
 
-    startstop = *event_queue->sorted_startstop_event_ptrs;
-    if (startstop == NULL)
-	return intersection;
-
-    if (intersection == NULL ||
-	cairo_bo_event_compare (startstop, intersection) <= 0)
+    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))
     {
-	event_queue->sorted_startstop_event_ptrs++;
-	return startstop;
+	event = cmp;
+	event_queue->start_events++;
+    }
+    else
+    {
+	_pqueue_pop (&event_queue->pqueue);
     }
 
-    return intersection;
+    return event;
 }
 
 CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
 			cairo_bo_event_t *,
-			cairo_bo_event_compare_pointers)
+			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;
+}
 
 static cairo_status_t
-_cairo_bo_event_queue_init (cairo_bo_event_queue_t	*event_queue,
-			    cairo_bo_edge_t	*edges,
-			    int				 num_edges)
+_cairo_bo_event_queue_insert_stop (cairo_bo_event_queue_t	*event_queue,
+				   cairo_bo_edge_t		*edge)
 {
-    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;
+    cairo_bo_point32_t 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;
+    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);
 }
 
 static void
 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
 {
-    _cairo_skip_list_fini (&event_queue->intersection_queue);
-    if (event_queue->startstop_events)
-	free (event_queue->startstop_events);
+    _pqueue_fini (&event_queue->pqueue);
+    _cairo_freepool_fini (&event_queue->pool);
 }
 
-static cairo_status_t
+static inline 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 (left == NULL || right == NULL)
+    if (_line_equal (&left->edge.line, &right->edge.line))
 	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 oalready
+     * that the intersection of these two segments has already
      * occurred before the current sweep line position. */
-    if (_slope_compare (left, right) < 0)
+    if (_slope_compare (left, right) <= 0)
 	return CAIRO_STATUS_SUCCESS;
 
-    status = _cairo_bo_edge_intersect (left, right, &intersection);
-    if (status == CAIRO_BO_STATUS_PARALLEL ||
-	status == CAIRO_BO_STATUS_NO_INTERSECTION)
-    {
+    if (! _cairo_bo_edge_intersect (left, right, &intersection))
 	return CAIRO_STATUS_SUCCESS;
-    }
 
-    _cairo_bo_event_init (&event,
-			  CAIRO_BO_EVENT_TYPE_INTERSECTION,
-			  left, right,
-			  intersection);
-
-    return _cairo_bo_event_queue_insert (event_queue, &event);
+    return _cairo_bo_event_queue_insert (event_queue,
+					 CAIRO_BO_EVENT_TYPE_INTERSECTION,
+					 left, right,
+					 &intersection);
 }
 
 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->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);
+    sweep_line->stopped = NULL;
+    sweep_line->current_y = INT32_MIN;
+    sweep_line->current_edge = NULL;
 }
 
 static cairo_status_t
 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t		*edge)
 {
-    skip_elt_t *next_elt;
-    sweep_line_elt_t *sweep_line_elt;
-    cairo_bo_edge_t **prev_of_next, **next_of_prev;
+    if (sweep_line->current_edge != NULL) {
+	cairo_bo_edge_t *prev, *next;
+	int cmp;
 
-    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);
+	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;
+	    }
 
-    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;
+	    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;
+	    }
 
-    if (*prev_of_next)
-	next_of_prev = &(*prev_of_next)->next;
-    else
-	next_of_prev = &sweep_line->head;
+	    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;
+    }
 
-    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;
+    sweep_line->current_edge = edge;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t	*sweep_line,
 			     cairo_bo_edge_t	*edge)
 {
-    cairo_bo_edge_t **left_next, **right_prev;
-
-    _cairo_skip_list_delete_given (&sweep_line->active_edges,
-				   &edge->sweep_line_elt->elt);
+    if (edge->prev != NULL)
+	edge->prev->next = edge->next;
+    else
+	sweep_line->head = edge->next;
 
-    left_next = &sweep_line->head;
-    if (edge->prev)
-	left_next = &edge->prev->next;
+    if (edge->next != NULL)
+	edge->next->prev = edge->prev;
 
-    right_prev = &sweep_line->tail;
-    if (edge->next)
-	right_prev = &edge->next->prev;
-
-    *left_next = edge->next;
-    *right_prev = edge->prev;
+    if (sweep_line->current_edge == edge)
+	sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
 }
 
 static void
 _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t	*sweep_line,
 			   cairo_bo_edge_t		*left,
 			   cairo_bo_edge_t		*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 (left->prev != NULL)
+	left->prev->next = right;
+    else
+	sweep_line->head = right;
 
-    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;
+    if (right->next != NULL)
+	right->next->prev = 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->top.x, edge->top.y,
-	    edge->bottom.x, edge->bottom.y);
+	    edge->edge.line.p1.x, edge->edge.line.p1.y,
+	    edge->edge.line.p2.x, edge->edge.line.p2.y);
 }
 
 static void
 _cairo_bo_event_print (cairo_bo_event_t *event)
 {
     switch (event->type) {
     case CAIRO_BO_EVENT_TYPE_START:
 	printf ("Start: ");
@@ -1195,618 +1230,648 @@ 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\n", msg);
+    printf ("%s ", msg);
+    _cairo_bo_event_print (event);
     _cairo_bo_event_queue_print (event_queue);
     _cairo_bo_sweep_line_print (sweep_line);
     printf ("\n");
 }
 #endif
 
-/* 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)
+#if DEBUG_EVENTS
+static void CAIRO_PRINTF_FORMAT (1, 2)
+event_log (const char *fmt, ...)
 {
-    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;
+    FILE *file;
 
-	left_line.p1.x  = left->top.x + xmin;
-	left_line.p1.y  = left->top.y + ymin;
-	right_line.p1.x = right->top.x + xmin;
-	right_line.p1.y = right->top.y + ymin;
-
-	left_line.p2.x  = left->bottom.x + xmin;
-	left_line.p2.y  = left->bottom.y + ymin;
-	right_line.p2.x = right->bottom.x + xmin;
-	right_line.p2.y = right->bottom.y + ymin;
-
-	/* Avoid emitting the trapezoid if it is obviously degenerate.
-	 * TODO: need a real collinearity test here for the cases
-	 * where the trapezoid is degenerate, yet the top and bottom
-	 * coordinates aren't equal.  */
-	if (left_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);
-}
+    if (getenv ("CAIRO_DEBUG_EVENTS") == NULL)
+	return;
 
-/* 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;
-}
+    file = fopen ("bo-events.txt", "a");
+    if (file != NULL) {
+	va_list 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);
-}
+	va_start (ap, fmt);
+	vfprintf (file, fmt, ap);
+	va_end (ap);
 
-#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 ();
+	fclose (file);
     }
 }
 #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
-_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_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)
 {
     cairo_status_t status;
-    int in_out = 0;
-    cairo_bo_edge_t *edge;
+
+    if (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;
-	    }
+    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;
 	}
 
-	status = _cairo_bo_edge_start_or_continue_trap (edge, top, bo_traps);
-	if (status)
+	status = _cairo_bo_edge_end_trap (left, top, traps);
+	if (unlikely (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_edge_t	*edges,
-					    int			 num_edges,
+_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t   **start_events,
+					    int			 num_events,
 					    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_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
     int intersection_count = 0;
     cairo_bo_event_queue_t event_queue;
     cairo_bo_sweep_line_t sweep_line;
-    cairo_bo_traps_t bo_traps;
-    cairo_bo_event_t *event, event_saved;
-    cairo_bo_edge_t *edge;
+    cairo_bo_event_t *event;
     cairo_bo_edge_t *left, *right;
-    cairo_bo_edge_t *edge1, *edge2;
+    cairo_bo_edge_t *e1, *e2;
+
+#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);
+	}
+    }
+#endif
 
-    status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
-    if (status)
-	return status;
-
+    _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
     _cairo_bo_sweep_line_init (&sweep_line);
 
-    _cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
-
-#if DEBUG_PRINT_STATE
-    print_state ("After initializing", &event_queue, &sweep_line);
-#endif
+    while ((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;
 
-    while (1)
-    {
-	event = _cairo_bo_event_dequeue (&event_queue);
-	if (!event)
-	    break;
-
-	if (event->point.y != sweep_line.current_y) {
 	    status = _active_edges_to_traps (sweep_line.head,
 					     sweep_line.current_y,
-					     fill_rule, &bo_traps);
-	    if (status)
+					     fill_rule, traps);
+	    if (unlikely (status))
 		goto unwind;
 
 	    sweep_line.current_y = event->point.y;
 	}
 
-	event_saved = *event;
-	_cairo_bo_event_queue_delete (&event_queue, event);
-	event = &event_saved;
+#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
 
 	switch (event->type) {
 	case CAIRO_BO_EVENT_TYPE_START:
-	    edge = event->e1;
+	    e1 = &((cairo_bo_start_event_t *) event)->edge;
 
-	    status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
-	    if (status)
+	    status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
+	    if (unlikely (status))
 		goto unwind;
-	    /* Cache the insert position for use in pass 2.
-	    event->e2 = Sortlist::prev (sweep_line, edge);
-	    */
 
-	    left = edge->prev;
-	    right = edge->next;
-
-	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
-	    if (status)
+	    status = _cairo_bo_event_queue_insert_stop (&event_queue, e1);
+	    if (unlikely (status))
 		goto unwind;
 
-	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
-	    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;
+		}
+	    }
 
-#if DEBUG_PRINT_STATE
-	    print_state ("After processing start", &event_queue, &sweep_line);
-#endif
+	    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;
+	    }
+
 	    break;
 
 	case CAIRO_BO_EVENT_TYPE_STOP:
-	    edge = event->e1;
+	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
+	    _cairo_bo_event_queue_delete (&event_queue, event);
 
-	    left = edge->prev;
-	    right = edge->next;
+	    left = e1->prev;
+	    right = e1->next;
 
-	    _cairo_bo_sweep_line_delete (&sweep_line, edge);
+	    _cairo_bo_sweep_line_delete (&sweep_line, e1);
 
-	    status = _cairo_bo_edge_end_trap (edge, edge->bottom.y, &bo_traps);
-	    if (status)
-		goto unwind;
+	    /* 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_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
-	    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;
+	    }
 
-#if DEBUG_PRINT_STATE
-	    print_state ("After processing stop", &event_queue, &sweep_line);
-#endif
 	    break;
 
 	case CAIRO_BO_EVENT_TYPE_INTERSECTION:
-	    edge1 = event->e1;
-	    edge2 = event->e2;
+	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
+	    e2 = ((cairo_bo_queue_event_t *) event)->e2;
+	    _cairo_bo_event_queue_delete (&event_queue, event);
 
 	    /* skip this intersection if its edges are not adjacent */
-	    if (edge2 != edge1->next)
+	    if (e2 != e1->next)
 		break;
 
 	    intersection_count++;
 
-	    edge1->middle = event->point;
-	    edge2->middle = event->point;
+	    left = e1->prev;
+	    right = e2->next;
 
-	    left = edge1->prev;
-	    right = edge2->next;
-
-	    _cairo_bo_sweep_line_swap (&sweep_line, edge1, edge2);
+	    _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);
 
 	    /* after the swap e2 is left of e1 */
 
-	    status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
-								       left, edge2);
-	    if (status)
-		goto unwind;
+	    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,
-								       edge1, right);
-	    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;
+	    }
 
-#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;
-    }
-    _cairo_bo_traps_fini (&bo_traps);
-    _cairo_bo_sweep_line_fini (&sweep_line);
     _cairo_bo_event_queue_fini (&event_queue);
+
+#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_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;
+    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;
     int i;
 
-    if (0 == polygon->num_edges)
+    num_events = polygon->num_edges;
+    if (unlikely (0 == num_events))
 	return CAIRO_STATUS_SUCCESS;
 
-    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))
+    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))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
 
-    /* Figure out the bounding box of the input coordinates and
-     * validate that we're not given invalid polygon edges. */
-    for (i = 0; i < polygon->num_edges; i++) {
-	update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x);
-	update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y);
-	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");
+	event_ptrs = (cairo_bo_event_t **) (events + num_events);
     }
 
-    /* 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;
+    for (i = 0; i < num_events; i++) {
+	event_ptrs[i] = (cairo_bo_event_t *) &events[i];
 
-    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].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);
 
-	/* 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;
+	events[i].edge.edge = polygon->edges[i];
+	events[i].edge.deferred_trap.right = NULL;
+	events[i].edge.prev = NULL;
+	events[i].edge.next = NULL;
+    }
 
-	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 (edges, num_bo_edges,
+    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
+							 num_events,
 							 fill_rule, traps,
-							 xmin, ymin, xmax, ymax,
 							 &intersections);
+#if DEBUG_TRAPS
+    dump_traps (traps, "bo-polygon-out.txt");
+#endif
 
-    if (edges != stack_edges)
-	free (edges);
+    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);
 
     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].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;
+	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;
     }
 
     for (i = 0; i < num_edges; i++) {
 	for (j = 0; j < num_edges; j++) {
 	    if (i == j)
 		continue;
 
 	    a = &edges[i];
 	    b = &edges[j];
 
-	    status = _cairo_bo_edge_intersect (a, b, &intersection);
-	    if (status == CAIRO_BO_STATUS_PARALLEL ||
-		status == CAIRO_BO_STATUS_NO_INTERSECTION)
-	    {
+	    if (! _cairo_bo_edge_intersect (a, b, &intersection))
 		continue;
-	    }
 
 	    printf ("Found intersection (%d,%d) between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d)\n",
 		    intersection.x,
 		    intersection.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);
+		    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);
 
 	    return TRUE;
 	}
     }
     return FALSE;
 }
 
 #define TEST_MAX_EDGES 10
@@ -2036,29 +2101,28 @@ 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->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;
+		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;
 		}
-	    } while (edge->top.y == edge->bottom.y);
+	    } while (edge->line.p1.y == edge->line.p2.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,97 +38,100 @@
 
 #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 {
-    cairo_clip_mode_t mode;
+    /* can be used as a cairo_hash_entry_t for live clips */
+    cairo_clip_path_t *path;
 
     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_surface_t *target);
+_cairo_clip_init (cairo_clip_t *clip);
 
 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_deep_copy (cairo_clip_t    *clip,
-                            cairo_clip_t    *other,
-                            cairo_surface_t *target);
+_cairo_clip_init_copy_transformed (cairo_clip_t    *clip,
+				   cairo_clip_t    *other,
+				   const cairo_matrix_t *matrix);
 
 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_rectangle (cairo_clip_t       *clip,
+		       const cairo_rectangle_int_t *rectangle);
+
 cairo_private cairo_status_t
 _cairo_clip_clip (cairo_clip_t       *clip,
-		  cairo_path_fixed_t *path,
+		  const 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_intersect_to_rectangle (cairo_clip_t            *clip,
-				    cairo_rectangle_int_t   *rectangle);
+		  cairo_antialias_t   antialias);
 
 cairo_private cairo_status_t
-_cairo_clip_intersect_to_region (cairo_clip_t      *clip,
-				 cairo_region_t *region);
+_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_private 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_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_private void
-_cairo_clip_translate (cairo_clip_t  *clip,
-                       cairo_fixed_t  tx,
-                       cairo_fixed_t  ty);
+_cairo_clip_drop_cache (cairo_clip_t  *clip);
 
 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,13 +1,14 @@
 /* -*- 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.
@@ -30,265 +31,133 @@
  * 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"
-
-static cairo_clip_path_t *
-_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
+#include "cairo-path-fixed-private.h"
+#include "cairo-region-private.h"
 
-static void
-_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
+/* 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;
 
-void
-_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
+static freed_pool_t clip_path_pool;
+
+static void *
+_atomic_fetch (void **slot)
 {
-    if (target && target->backend)
-	clip->mode = _cairo_surface_get_clip_mode (target);
-    else
-	clip->mode = CAIRO_CLIP_MODE_MASK;
-
-    clip->all_clipped = FALSE;
+    return _cairo_atomic_ptr_cmpxchg (slot, *slot, 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 cairo_bool_t
+_atomic_store (void **slot, void *ptr)
+{
+    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
 }
 
-cairo_status_t
-_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
+static void *
+_freed_pool_get (freed_pool_t *pool)
 {
-    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);
+    void *ptr;
+    int i;
 
-	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);
+    i = pool->top - 1;
+    if (i < 0)
+	i = 0;
 
-    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;
+    ptr = _atomic_fetch (&pool->pool[i]);
+    if (ptr != NULL) {
+	pool->top = i;
+	return ptr;
     }
 
-    _cairo_clip_path_destroy (clip->path);
-    clip->path = 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;
 }
 
 static void
-_cairo_clip_set_all_clipped (cairo_clip_t *clip, cairo_surface_t *target)
+_freed_pool_put (freed_pool_t *pool, void *ptr)
 {
-    _cairo_clip_reset (clip);
-
-    clip->all_clipped = TRUE;
-    clip->serial = _cairo_surface_allocate_clip_serial (target);
-}
-
+    int i = pool->top;
 
-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;
+    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;
+    /* 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;
+	}
     }
 
-    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;
+    /* full */
+    pool->top = ARRAY_LENGTH (pool->pool);
+    free (ptr);
 }
 
-cairo_status_t
-_cairo_clip_intersect_to_region (cairo_clip_t   *clip,
-				 cairo_region_t *region)
+static void
+_freed_pool_reset (freed_pool_t *pool)
 {
-    cairo_status_t status;
-
-    if (!clip)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (clip->all_clipped)
-	return cairo_region_intersect_rectangle (region, &clip->surface_rect);
+    int i;
 
-    if (clip->path) {
-	/* Intersect clip path into region. */
+    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
+	free (pool->pool[i]);
+	pool->pool[i] = NULL;
     }
-
-    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;
 }
 
-/* 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)
+static cairo_clip_path_t *
+_cairo_clip_path_create (cairo_clip_t *clip)
 {
     cairo_clip_path_t *clip_path;
-    cairo_status_t status;
 
-    if (clip->mode != CAIRO_CLIP_MODE_PATH)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    clip_path = malloc (sizeof (cairo_clip_path_t));
-    if (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;
+    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;
     }
 
     CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
-    clip_path->fill_rule = fill_rule;
-    clip_path->tolerance = tolerance;
-    clip_path->antialias = antialias;
+
+    clip_path->flags = 0;
+    clip_path->region = NULL;
+    clip_path->surface = NULL;
+
     clip_path->prev = clip->path;
     clip->path = clip_path;
 
-    return CAIRO_STATUS_SUCCESS;
+    return clip_path;
 }
 
 static cairo_clip_path_t *
 _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
 {
     if (clip_path == NULL)
 	return NULL;
 
@@ -297,545 +166,1187 @@ 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);
-    _cairo_clip_path_destroy (clip_path->prev);
-    free (clip_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);
 }
 
-
-static cairo_int_status_t
-_cairo_clip_intersect_region (cairo_clip_t    *clip,
-			      cairo_traps_t   *traps,
-			      cairo_surface_t *target)
+void
+_cairo_clip_init (cairo_clip_t *clip)
 {
-    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;
+    clip->all_clipped = FALSE;
+    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;
+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;
     }
-
-    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_mask (cairo_clip_t      *clip,
-			    cairo_traps_t     *traps,
-			    cairo_antialias_t antialias,
-			    cairo_surface_t   *target)
+_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
+				 const cairo_rectangle_int_t *rect)
+{
+    cairo_clip_path_t *clip_path;
+    cairo_status_t status;
+
+    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;
+	}
+    }
+
+    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;
+    }
+
+    return _cairo_clip_intersect_rectangle (clip, rect);
+}
+
+cairo_clip_t *
+_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
 {
-    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 (other != NULL) {
+	clip->all_clipped = other->all_clipped;
+	clip->path = _cairo_clip_path_reference (other->path);
+
+	/* 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);
+    }
+
+    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;
+    }
+}
+
+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;
+
+    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;
+    }
+
+    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;
+	}
+
+	/* 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);
+	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;
+}
+
+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;
 
-    /* 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;
+    /* catch the empty clip path */
+    if (_cairo_path_fixed_fill_is_empty (path)) {
+	_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_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;
+
+    if (rectangle->width == 0 || rectangle->height == 0) {
+	_cairo_clip_set_all_clipped (clip);
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    if (surface_rect.width == 0 || surface_rect.height == 0)
-	goto DONE;
-
-    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
-    /* The clipping operation should ideally be something like the following to
-     * avoid having to do as many passes over the data
-
-	if (clip->surface != NULL) {
-	    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
-	} else {
-	    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
+    /* 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;
 	}
-	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);
-
-	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;
     }
 
-    /* Render the new clipping path into the new mask surface. */
+    return _cairo_clip_intersect_rectangle (clip, rectangle);
+}
 
-    _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
+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;
 
-    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);
+    if (other_path->prev != NULL) {
+        status = _cairo_clip_path_reapply_clip_path_transform (clip,
+							       other_path->prev,
+							       matrix);
+	if (unlikely (status))
+	    return status;
+    }
 
-    _cairo_pattern_fini (&pattern.base);
+    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_surface_destroy (surface);
+	_cairo_clip_path_destroy (clip_path);
 	return status;
     }
 
-    /* If there was a clip surface already, combine it with the new
-     * mask surface using the IN operator, so we get the intersection
-     * of the old and new clipping paths. */
+    _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 (clip->surface != NULL) {
-	_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
+    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);
+
+    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;
 
-	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);
+    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;
+    }
 
-	_cairo_pattern_fini (&pattern.base);
+    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 (unlikely (status)) {
-	    cairo_surface_destroy (surface);
-	    return status;
+	/* 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);
+	    }
 	}
     }
 
- DONE:
-    cairo_surface_destroy (clip->surface);
-    clip->surface = surface;
-    clip->surface_rect = surface_rect;
-    clip->serial = _cairo_surface_allocate_clip_serial (target);
-
-    if (surface_rect.width == 0 || surface_rect.height == 0)
-	_cairo_clip_set_all_clipped (clip, target);
-
     return status;
 }
 
 static cairo_status_t
-_cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
-					cairo_path_fixed_t *path,
-					cairo_fill_rule_t   fill_rule,
-					double		    tolerance,
-					cairo_antialias_t   antialias,
-					cairo_surface_t    *target)
+_cairo_clip_apply_clip_path (cairo_clip_t *clip,
+			     const cairo_clip_path_t *path)
 {
-    cairo_span_renderer_t *renderer = NULL;
-    cairo_pattern_union_t pattern;
-    cairo_rectangle_int_t surface_rect;
-    cairo_surface_t *surface = NULL;
     cairo_status_t status;
-    cairo_operator_t op;
-    cairo_composite_rectangles_t rects;
+
+    if (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;
 
     if (clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
-
-    /* If we have a clip surface we're going to use IN to combine our
-     * new clip with the old clip.  The ADD is done to a transparent
-     * surface, as that's a fast way of doing it currently.  We should
-     * really be using SOURCE instead, but _cairo_surface_composite()
-     * checks that it's not called with SOURCE or DEST. */
-    op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;
-
-    /* Test if the target can composite spans.  We're going to assume
-     * this is a good indicator of whether a similar surface is going
-     * to be able to composite spans too. */
-    if ( !_cairo_surface_check_span_renderer (op,
-					      &pattern.base,
-					      target,
-					      antialias,
-					      NULL))
-    {
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
-	goto BAIL;
-    }
-
-    status = _cairo_surface_get_extents (target, &surface_rect);
-    if (status)
-	goto BAIL;
-
-    /* We'll create a new surface the size of the intersection of the
-     * old mask surface and the extents of the new clip path. */
-    {
-	cairo_rectangle_int_t extents;
-
-	_cairo_path_fixed_approximate_clip_extents (path, &extents);
-	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
-	    goto SUCCESS;
-
-	if (clip->surface != NULL &&
-	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
-	    goto SUCCESS;
-    }
-
-    /* Make the new mask surface and optionally initialise it from the
-     * previous clip if we have one. */
-    surface = _cairo_surface_create_similar_solid (target,
-						   CAIRO_CONTENT_ALPHA,
-						   surface_rect.width,
-						   surface_rect.height,
-						   CAIRO_COLOR_TRANSPARENT);
-    if (surface->status) {
-	_cairo_pattern_fini (&pattern.base);
-	return surface->status;
+    if (other->all_clipped) {
+	_cairo_clip_set_all_clipped (clip);
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    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;
+    status = CAIRO_STATUS_SUCCESS;
+    if (other->path != NULL)
+	status = _cairo_clip_apply_clip_path (clip, other->path);
 
-    /* Render the new clipping path into the new mask surface. We've
-     * chosen op to either combine the new clip path with the existing
-     * clip mask (if there is one) or just render it. */
-    status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
-						path, surface,
-						fill_rule, tolerance,
-						antialias, &rects);
-    if (status)
-	goto BAIL;
-
- SUCCESS:
-    if (clip->surface != NULL)
-	cairo_surface_destroy (clip->surface);
-    clip->surface = surface;
-    clip->surface_rect = surface_rect;
-    clip->serial = _cairo_surface_allocate_clip_serial (target);
-    surface = NULL;
-
-    if (surface_rect.width == 0 || surface_rect.height == 0)
-	_cairo_clip_set_all_clipped (clip, target);
-
- BAIL:
-    if (renderer)
-	renderer->destroy(renderer);
-    if (surface)
-	cairo_surface_destroy (surface);
-    _cairo_pattern_fini (&pattern.base);
     return status;
 }
 
-cairo_status_t
-_cairo_clip_clip (cairo_clip_t       *clip,
-		  cairo_path_fixed_t *path,
-		  cairo_fill_rule_t   fill_rule,
-		  double              tolerance,
-		  cairo_antialias_t   antialias,
-		  cairo_surface_t    *target)
+static inline cairo_bool_t
+_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
 {
-    cairo_status_t status;
-    cairo_rectangle_int_t limits, extents;
+    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_traps_t traps;
-    cairo_box_t ignored_box;
-    cairo_bool_t have_limits;
+    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;
+
+    /* 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;
 
-    if (clip->all_clipped)
-	return CAIRO_STATUS_SUCCESS;
+    _cairo_traps_init (&traps);
+    _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
+    _cairo_traps_limit (&traps, boxes, 1);
+
+    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;
 
-    /* catch the empty clip path */
-    if (! path->has_current_point) {
-	_cairo_clip_set_all_clipped (clip, target);
-	return CAIRO_STATUS_SUCCESS;
+    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;
     }
 
-    status = _cairo_clip_intersect_path (clip,
-					 path, fill_rule, tolerance,
-					 antialias);
-    if (status == CAIRO_STATUS_SUCCESS)
-        clip->serial = _cairo_surface_allocate_clip_serial (target);
+    _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);
 
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+    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))
 	return status;
 
-    /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter
-     * again. */
-    if (antialias != CAIRO_ANTIALIAS_NONE &&
-	!_cairo_path_fixed_is_box (path, &ignored_box) &&
-	!_cairo_path_fixed_is_region (path))
+    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))
     {
-	status = _cairo_clip_intersect_mask_using_spans (
-	    clip, path, fill_rule, tolerance, antialias, target);
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	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))
 	    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;
 
-    /* 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;
+    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;
     }
 
-    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 (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;
 	    }
-	} else {
-	    limits = clip->surface_rect;
-	    have_limits = TRUE;
+
+	    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;
 	}
     }
 
-    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:
+  CLEANUP:
+    _cairo_polygon_fini (&polygon);
     _cairo_traps_fini (&traps);
 
     return status;
 }
 
-void
-_cairo_clip_translate (cairo_clip_t  *clip,
-                       cairo_fixed_t  tx,
-                       cairo_fixed_t  ty)
+static cairo_int_status_t
+_cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
+			   cairo_box_t **boxes,
+			   int *count)
 {
-    if (clip->all_clipped)
-	return;
+    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;
+
+	    new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t));
+	    if (unlikely (new_boxes == NULL))
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    if (clip->region) {
-        cairo_region_translate (clip->region,
-				_cairo_fixed_integer_part (tx),
-				_cairo_fixed_integer_part (ty));
+	    *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->surface) {
-        clip->surface_rect.x += _cairo_fixed_integer_part (tx);
-        clip->surface_rect.y += _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->path) {
-        cairo_clip_path_t *clip_path = clip->path;
-	cairo_matrix_t matrix;
+    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;
 
-	cairo_matrix_init_translate (&matrix,
-				     _cairo_fixed_to_double (tx),
-				     _cairo_fixed_to_double (ty));
+		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;
+	    }
 
-        while (clip_path) {
-            _cairo_path_fixed_transform (&clip_path->path, &matrix);
-            clip_path = clip_path->prev;
-        }
+	    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;
+	}
     }
+
+    *count = num_boxes;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_clip_path_reapply_clip_path (cairo_clip_t      *clip,
-                                    cairo_clip_path_t *clip_path)
+_combine_region (cairo_surface_t *surface,
+		 const cairo_region_t *region,
+		 const cairo_rectangle_int_t *extents)
 {
+    cairo_region_t clear_region;
     cairo_status_t status;
 
-    if (clip_path->prev) {
-        status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev);
-	if (_cairo_status_is_error (status))
-	    return 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);
+    }
+
+    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;
+
+    _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;
+
+    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;
+
+	goto DONE;
+    } 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;
     }
 
-    return _cairo_clip_intersect_path (clip,
-                                       &clip_path->path,
-				       clip_path->fill_rule,
-				       clip_path->tolerance,
-				       clip_path->antialias);
+    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 (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;
+	}
+    }
+
+  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;
+
+    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;
+    }
+
+    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_init_deep_copy (cairo_clip_t    *clip,
-                            cairo_clip_t    *other,
-                            cairo_surface_t *target)
+_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;
 
-    _cairo_clip_init (clip, target);
-
-    if (other->mode != clip->mode) {
-        /* We should reapply the original clip path in this case, and let
-         * whatever the right handling is happen */
-    } else {
-        if (other->region) {
-	    clip->region = cairo_region_copy (other->region);
-	    if (unlikely ((status = cairo_region_status (clip->region))))
-		goto BAIL;
-        }
+    assert (clip_path != NULL);
 
-        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;
+    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);
 
-            clip->surface_rect = other->surface_rect;
+	_cairo_pattern_fini (&pattern.base);
 
-	    /* src offset was 0, so we expect an exact replica of the surface */
-	    assert (dx == 0);
-	    assert (dy == 0);
-        }
-
-        if (other->path) {
-            status = _cairo_clip_path_reapply_clip_path (clip, other->path);
-	    if (_cairo_status_is_error (status))
-		goto BAIL;
-        }
+	return status;
     }
 
-    return CAIRO_STATUS_SUCCESS;
+    _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);
+
+	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;
+}
 
-    return status;
+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);
 }
 
 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
@@ -857,87 +1368,172 @@ 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->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 (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->region) {
-        int i;
-
-	n_rects = cairo_region_num_rectangles (clip->region);
-
+    if (region != NULL) {
+	n_rects = cairo_region_num_rectangles (region);
 	if (n_rects) {
 	    rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
 	    if (unlikely (rectangles == NULL)) {
-		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-		return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+		return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
 	    }
 
 	    for (i = 0; i < n_rects; ++i) {
 		cairo_rectangle_int_t clip_rect;
 
-		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);
+		cairo_region_get_rectangle (region, i, &clip_rect);
+
+		if (! _cairo_clip_int_rect_to_user (gstate,
+						    &clip_rect,
+						    &rectangles[i]))
+		{
 		    free (rectangles);
-		    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
+		    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 		}
 	    }
 	}
     } else {
         cairo_rectangle_int_t extents;
 
-	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;
+	if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
+					  &extents))
+	{
+	    /* unbounded surface -> unclipped */
+	    goto DONE;
 	}
 
-	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);
+	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)) {
 	    free (rectangles);
-	    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
+	    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 	}
     }
 
  DONE:
     list = malloc (sizeof (cairo_rectangle_list_t));
     if (unlikely (list == NULL)) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
         free (rectangles);
-        return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+	return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
     }
 
     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
@@ -950,8 +1546,14 @@ 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 = 0; \
+      swapped = gap > 1; \
       for (i = 0; i < nmemb-gap ; i++) { \
 	  j = i + gap; \
 	  if (CMP (base[i], base[j]) > 0 ) { \
 	      TYPE tmp; \
 	      tmp = base[i]; \
 	      base[i] = base[j]; \
 	      base[j] = tmp; \
 	      swapped = 1; \
 	  } \
       } \
-  } while (gap > 1 || swapped); \
+  } while (swapped); \
 }
--- a/gfx/cairo/cairo/src/cairo-d2d-private.h
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.h
@@ -40,16 +40,17 @@
 
 #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;
@@ -86,16 +87,18 @@ 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
@@ -212,10 +215,13 @@ 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,16 +37,17 @@
 
 #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
 
@@ -154,115 +155,111 @@ 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 extents The extents of the surface to which to apply this operation
+ * \param clip The clip of 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_rectangle_int_t	*extents);
+		cairo_clip_t		*clip);
 
 /**
  * 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 Extents of the surface to apply this operation to
+ * \param clip The clip of 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_paint(void			*surface,
 		 cairo_operator_t	 op,
 		 const cairo_pattern_t	*source,
-		 cairo_rectangle_int_t  *extents);
+		 cairo_clip_t		*clip);
 
 /**
  * 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 extents Extents of the surface to apply this operation to
+ * \param clip The clip of 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_mask(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		const cairo_pattern_t	*mask,
-		cairo_rectangle_int_t  *extents);
+		cairo_clip_t		*clip);
 
 /**
  * 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 extents Extents this operation applies to.
+ * \param clip The clip of this operation
  * \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,
-			int			*remaining_glyphs,
-			cairo_rectangle_int_t	*extents);
+			cairo_clip_t		*clip,
+			int			*remaining_glyphs);
 
 /**
  * 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_int_status_t
+static cairo_bool_t
 _cairo_d2d_getextents(void		       *surface,
 		      cairo_rectangle_int_t    *extents);
 
 
-/**
- * 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);
+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);
 
 /**
  * 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
@@ -270,31 +267,31 @@ static cairo_int_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 extents Extents of the surface to apply this operation to
+ * \param clip The clip of 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_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_rectangle_int_t  *extents);
+		  cairo_clip_t		*clip);
 
 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 */
@@ -302,32 +299,29 @@ 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_d2d_intersect_clip_path, /* intersect_clip_path */
-    _cairo_d2d_getextents, /* getextents */
+    _cairo_d2d_getextents, /* get_extents */
     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
@@ -497,16 +491,25 @@ 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
@@ -1280,16 +1283,17 @@ 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;
@@ -1386,16 +1390,19 @@ 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();
@@ -1425,16 +1432,17 @@ 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)
 {
@@ -1583,64 +1591,65 @@ static void
 
     cairo_surface_destroy(&image->base);
 
     softTexture->Unmap(0);
     D3D10Factory::Device()->CopyResource(d2dsurf->surface, softTexture);
     softTexture->Release();
 }
 
-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)
+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_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(dst);
+    cairo_d2d_surface_t *d2dsurf = cairo_container_of (clipper, cairo_d2d_surface_t, clipper);
 
     _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_INT_STATUS_SUCCESS;
+	return CAIRO_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_INT_STATUS_SUCCESS;
+	    return CAIRO_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_INT_STATUS_SUCCESS;
+	    return CAIRO_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),
@@ -1648,21 +1657,22 @@ cairo_int_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_INT_STATUS_SUCCESS;		    
+		return CAIRO_STATUS_SUCCESS;
 		
 	    }
 	    newMask->Release();
 	}
     }
     
     if (!d2dsurf->clipRect && !d2dsurf->clipMask) {
 	/** Nothing yet, just use this clip path */
@@ -1692,17 +1702,17 @@ cairo_int_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_INT_STATUS_SUCCESS;
+	    return CAIRO_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);
@@ -1718,17 +1728,17 @@ cairo_int_status_t
 	}
     }
 
     if (d2dsurf->clipRect) {
 	delete d2dsurf->clipRect;
 	d2dsurf->clipRect = NULL;
     }
   
-    return CAIRO_INT_STATUS_SUCCESS;
+    return CAIRO_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) {
@@ -1738,19 +1748,25 @@ 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_rectangle_int_t  *extents)
+		 cairo_clip_t		*clip)
 {
     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;
     }
@@ -1766,30 +1782,24 @@ static cairo_int_status_t
 								source,
 								last_run++,
 								&runs_remaining,
 								&pushed_clip);
 
 	if (!brush) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
-	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) {
+	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 && !extents) {
+        } else if (op == CAIRO_OPERATOR_SOURCE) {
 	    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 {
@@ -1805,43 +1815,58 @@ 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_rectangle_int_t	*extents)
+		cairo_clip_t		*clip)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
-    _begin_draw_state(d2dsurf);
+    cairo_rectangle_int_t extents;
 
     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);
-    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);
-    }
+
+    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);
@@ -1884,33 +1909,40 @@ 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_rectangle_int_t  *extents)
+		  cairo_clip_t		*clip)
 {
+    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) {
@@ -2013,36 +2045,40 @@ 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_rectangle_int_t	*extents)
+		cairo_clip_t		*clip)
 {
-    if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D) {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
+    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);
     }
 
     unsigned int runs_remaining = 1;
     unsigned int last_run = 0;
@@ -2113,61 +2149,59 @@ 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,
-			int			*remaining_glyphs,
-			cairo_rectangle_int_t	*extents)
+			cairo_clip_t            *clip,
+			int			*remaining_glyphs)
 {
     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, extents);
+	    _cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
     }
 
     return status;
 }
 
-static cairo_int_status_t
+
+static cairo_bool_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 CAIRO_INT_STATUS_SUCCESS;
+    return TRUE;
 }
 
 
 /** Helper functions. */
 
 cairo_surface_t*
 cairo_d2d_surface_create_for_hwnd(HWND wnd)
 {
@@ -2178,16 +2212,17 @@ 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;
@@ -2313,16 +2348,19 @@ 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,16 +32,17 @@
  * 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,38 +237,16 @@ 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;
@@ -366,20 +344,17 @@ 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;
 
-	surface->has_image_clip = FALSE;
-	surface->image_clip_invalid = surface->has_clip_region;
-
-	return _cairo_ddraw_surface_set_image_clip (surface);
+	return CAIRO_STATUS_SUCCESS;
     }
 
     if (surface->locked)
 	return CAIRO_STATUS_SUCCESS;
 
     ddsd.dwSize = sizeof (ddsd);
     START_TIMER(lock);
     if (FAILED(hr = IDDSLock (surface->lpdds, NULL, &ddsd,
@@ -403,20 +378,17 @@ static cairo_status_t
 					     surface->format,
 					     ddsd.dwWidth,
 					     ddsd.dwHeight,
 					     ddsd.lPitch);
 
     if (surface->image->status)
 	return surface->image->status;
 
-    surface->has_image_clip = FALSE;
-    surface->image_clip_invalid = surface->has_clip_region;
-
-    return _cairo_ddraw_surface_set_image_clip (surface);
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static inline cairo_status_t
 _cairo_ddraw_surface_unlock (cairo_ddraw_surface_t *surface)
 {
     cairo_ddraw_surface_t * root = surface->root;
     HRESULT hr;
 
@@ -459,16 +431,18 @@ 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 {                               \
@@ -567,17 +541,17 @@ static cairo_status_t
     END_TIMER(flush);
  
     return status;
 }
 
 cairo_status_t
 _cairo_ddraw_surface_reset (cairo_surface_t *surface)
 {
-    return _cairo_surface_reset_clip (surface);
+    return _cairo_ddraw_surface_set_clip_region (surface, NULL);
 }
 
 static cairo_surface_t *
 _cairo_ddraw_surface_create_similar (void * abstract_surface,
 				     cairo_content_t content,
 				     int width,
 				     int height)
 {
@@ -2472,18 +2446,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,
-				  int		         *remaining_glyphs,
-				  cairo_rectangle_int_t  *extents)
+				  cairo_clip_t           *clip,
+				  int		         *remaining_glyphs)
 { 
     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;
@@ -2497,20 +2471,27 @@ 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 (dst->base.clip &&
-	(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
-	 dst->base.clip->surface != NULL))
-	return CAIRO_INT_STATUS_UNSUPPORTED;