Merging cedar with mozilla-central.
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 27 May 2011 17:22:52 +0200
changeset 70256 182b8216990d966d7c31fe9c0fdc572a5e027335
parent 70255 c24a597833bab23b9bb361109cb86ce1c0a63e4c (current diff)
parent 70252 1388b00e8b642c58d22defcb987c1101580b745b (diff)
child 70257 02a5505b965b143a1067a633889c5d1f70c97c06
child 70305 3d845eea88e80518da762984fd2b85a16fcc0295
push id20257
push usermlamouri@mozilla.com
push dateFri, 27 May 2011 15:24:53 +0000
treeherdermozilla-central@182b8216990d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merging cedar with mozilla-central.
--- a/browser/base/content/test/tabview/browser_tabview_bug624265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624265.js
@@ -14,25 +14,16 @@ function test() {
   let assertOneSingleGroupItem = function () {
     is(getContentWindow().GroupItems.groupItems.length, 1, 'There is one single groupItem');
   }
 
   let assertNumberOfVisibleTabs = function (numTabs) {
     is(gBrowser.visibleTabs.length, numTabs, 'There should be ' + numTabs + ' visible tabs');
   }
 
-  let restoreTab = function (callback) {
-    let tab = undoCloseTab(0);
-    
-    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
-      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
-      afterAllTabsLoaded(callback);
-    });
-  }
-
   let next = function () {
     while (gBrowser.tabs.length-1)
       gBrowser.removeTab(gBrowser.tabs[1]);
 
     hideTabView(function () {
       let callback = tests.shift();
 
       if (!callback)
@@ -81,17 +72,17 @@ function test() {
   }
 
   // ----------
   // [623792] duplicating tabs via middle click on forward/back buttons
   let testBackForwardDuplicateTab = function () {
     let tab = gBrowser.loadOneTab('http://mochi.test:8888/#1', {inBackground: true});
     gBrowser.selectedTab = tab;
 
-    let continueTest = function () {
+    afterAllTabsLoaded(function () {
       tab.linkedBrowser.loadURI('http://mochi.test:8888/#2');
 
       afterAllTabsLoaded(function () {
         ok(gBrowser.canGoBack, 'browser can go back in history');
         BrowserBack({button: 1});
 
         afterAllTabsLoaded(function () {
           assertNumberOfVisibleTabs(3);
@@ -101,23 +92,17 @@ function test() {
 
           afterAllTabsLoaded(function () {
             assertNumberOfVisibleTabs(4);
             assertOneSingleGroupItem();
             next();
           });
         });
       });
-    }
-
-    // The executeSoon() call is really needed here because there's probably
-    // some callback waiting to be fired after gBrowser.loadOneTab(). After
-    // that the browser is in a state where loadURI() will create a new entry
-    // in the session history (that is vital for back/forward functionality).
-    afterAllTabsLoaded(function () executeSoon(continueTest));
+    });
   }
 
   // ----------
   // [624102] check state after return from private browsing
   let testPrivateBrowsing = function () {
     gBrowser.loadOneTab('http://mochi.test:8888/#1', {inBackground: true});
     gBrowser.loadOneTab('http://mochi.test:8888/#2', {inBackground: true});
 
@@ -151,50 +136,35 @@ function test() {
   // tests for #624102
   tests.push(testPrivateBrowsing);
 
   loadTabView(next);
 }
 
 // ----------
 function loadTabView(callback) {
-  window.addEventListener('tabviewshown', function () {
-    window.removeEventListener('tabviewshown', arguments.callee, false);
-
-    hideTabView(function () {
-      window.removeEventListener('tabviewhidden', arguments.callee, false);
-      callback();
-    });
-  }, false);
-
-  TabView.show();
-}
-
-// ----------
-function hideTabView(callback) {
-  if (!TabView.isVisible())
-    return callback();
-
-  window.addEventListener('tabviewhidden', function () {
-    window.removeEventListener('tabviewhidden', arguments.callee, false);
-    callback();
-  }, false);
-
-  TabView.hide();
+  showTabView(function () {
+    hideTabView(callback);
+  });
 }
 
 // ----------
 function enterAndLeavePrivateBrowsing(callback) {
+  togglePrivateBrowsing(function () {
+    togglePrivateBrowsing(callback);
+  });
+}
+
+// ----------
+function togglePrivateBrowsing(callback) {
+  let topic = "private-browsing-transition-complete";
+
   function pbObserver(aSubject, aTopic, aData) {
-    if (aTopic != "private-browsing-transition-complete")
+    if (aTopic != topic)
       return;
 
-    if (pb.privateBrowsingEnabled)
-      pb.privateBrowsingEnabled = false;
-    else {
-      Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
-      afterAllTabsLoaded(function () executeSoon(callback));
-    }
+    Services.obs.removeObserver(pbObserver, topic, false);
+    afterAllTabsLoaded(callback);
   }
 
-  Services.obs.addObserver(pbObserver, "private-browsing-transition-complete", false);
-  pb.privateBrowsingEnabled = true;
+  Services.obs.addObserver(pbObserver, topic, false);
+  pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
 }
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -100,17 +100,17 @@ function afterAllTabsLoaded(callback, wi
   let stillToLoad = 0;
   let restoreHiddenTabs = Services.prefs.getBoolPref(
                           "browser.sessionstore.restore_hidden_tabs");
 
   function onLoad() {
     this.removeEventListener("load", onLoad, true);
     stillToLoad--;
     if (!stillToLoad)
-      callback();
+      executeSoon(callback);
   }
 
   for (let a = 0; a < win.gBrowser.tabs.length; a++) {
     let tab = win.gBrowser.tabs[a];
     let browser = tab.linkedBrowser;
 
     let isRestorable = !(tab.hidden && !restoreHiddenTabs &&
                          browser.__SS_restoreState &&
@@ -296,8 +296,26 @@ function newWindowWithState(state, callb
   whenWindowLoaded(win, function () {
     ss.setWindowState(win, JSON.stringify(state), true);
   });
 
   whenWindowStateReady(win, function () {
     afterAllTabsLoaded(function () callback(win), win);
   });
 }
+
+// ----------
+function restoreTab(callback, index, win) {
+  win = win || window;
+
+  let tab = win.undoCloseTab(index || 0);
+  let tabItem = tab._tabViewTabItem;
+
+  if (tabItem._reconnected) {
+    afterAllTabsLoaded(callback, win);
+    return;
+  }
+
+  tab._tabViewTabItem.addSubscriber(tab, "reconnected", function onReconnected() {
+    tab._tabViewTabItem.removeSubscriber(tab, "reconnected");
+    afterAllTabsLoaded(callback, win);
+  });
+}
--- a/configure.in
+++ b/configure.in
@@ -8402,16 +8402,17 @@ MOZ_CHECK_HEADERS(stdint.h inttypes.h sy
 if test "$MOZ_TREE_CAIRO"; then
     AC_DEFINE(MOZ_TREE_CAIRO)
 
     # For now we assume that we will have a uint64_t available through
     # one of the above headers or mozstdint.h.
     AC_DEFINE(HAVE_UINT64_T)
 
     # Define macros for cairo-features.h
+    TEE_SURFACE_FEATURE="#define CAIRO_HAS_TEE_SURFACE 1"
     if test "$MOZ_X11"; then
         XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
         XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
         PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="$FT2_CFLAGS"
     fi
@@ -8484,16 +8485,17 @@ if test "$MOZ_TREE_CAIRO"; then
     AC_SUBST(FT_FONT_FEATURE)
     AC_SUBST(FC_FONT_FEATURE)
     AC_SUBST(WIN32_FONT_FEATURE)
     AC_SUBST(WIN32_DWRITE_FONT_FEATURE)
     AC_SUBST(WIN32_D2D_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_FONT_FEATURE)
     AC_SUBST(PNG_FUNCTIONS_FEATURE)
     AC_SUBST(QT_SURFACE_FEATURE)
+    AC_SUBST(TEE_SURFACE_FEATURE)
 
     MOZ_CAIRO_LIBS='$(call EXPAND_LIBNAME_PATH,mozcairo,$(DEPTH)/gfx/cairo/cairo/src)'" $CAIRO_FT_LIBS"
 
     if test "$MOZ_TREE_PIXMAN"; then
         AC_DEFINE(MOZ_TREE_PIXMAN)
         MOZ_CAIRO_LIBS="$MOZ_CAIRO_LIBS"' $(call EXPAND_LIBNAME_PATH,mozlibpixman,$(DEPTH)/gfx/cairo/libpixman/src)'
     else
         PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.19.2)
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -65,77 +65,87 @@ endif
 
 
 CSRCS   = \
         cairo.c \
         cairo-analysis-surface.c \
         cairo-arc.c \
         cairo-array.c \
 	cairo-atomic.c \
+        cairo-base64-stream.c \
         cairo-bentley-ottmann.c \
 	cairo-bentley-ottmann-rectilinear.c \
 	cairo-bentley-ottmann-rectangular.c \
-        cairo-base64-stream.c \
+	cairo-botor-scan-converter.c \
+	cairo-boxes.c \
 	cairo-cache.c \
         cairo-clip.c \
         cairo-color.c \
+	cairo-composite-rectangles.c \
         cairo-debug.c \
         cairo-deflate-stream.c \
+	cairo-device.c \
         cairo-fixed.c \
 	cairo-font-face.c \
 	cairo-font-face-twin.c \
 	cairo-font-face-twin-data.c \
         cairo-font-options.c \
+	cairo-freed-pool.c \
         cairo-freelist.c \
         cairo-gstate.c \
         cairo-hash.c \
         cairo-hull.c \
 	cairo-image-info.c \
         cairo-image-surface.c \
         cairo-lzw.c \
         cairo-matrix.c \
 	cairo-misc.c \
 	cairo-mutex.c \
+	cairo-observer.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-rectangular-scan-converter.c \
         cairo-region.c \
         cairo-scaled-font.c \
         cairo-scaled-font-subsets.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-offset.c \
+	cairo-surface-snapshot.c \
+	cairo-surface-subsurface.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)
 
 EXPORTS_NAMESPACES = cairo
 
-EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
+EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h cairo-tee.h
 
 # cairo-type1-subset.c should be here, but it's only supported on freetype platforms
 
 PSPDF_BASE_CSRCS = \
 	cairo-base85-stream.c \
 	cairo-type1-fallback.c \
 	cairo-type3-glyph-surface.c \
 	cairo-truetype-subset.c \
@@ -148,16 +158,17 @@ PDF_CSRCS = \
 	$(NULL)
 
 PS_CSRCS = cairo-ps-surface.c
 
 PDF_EXPORTS = cairo-pdf.h
 PS_EXPORTS = cairo-ps.h
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+DEFINES += -DDISABLE_SOME_FLOATING_POINT
 CSRCS	+=	cairo-win32-surface.c
 
 ifndef WINCE
 ifdef MOZ_ENABLE_DWRITE_FONT
 CPPSRCS +=	cairo-dwrite-font.cpp
 endif
 ifdef MOZ_ENABLE_D2D_SURFACE
 CPPSRCS +=	cairo-d2d-surface.cpp
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
@@ -6,17 +6,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -32,16 +32,18 @@
  *      Keith Packard <keithp@keithp.com>
  */
 
 #ifndef CAIRO_ANALYSIS_SURFACE_H
 #define CAIRO_ANALYSIS_SURFACE_H
 
 #include "cairoint.h"
 
+CAIRO_BEGIN_DECLS
+
 cairo_private cairo_surface_t *
 _cairo_analysis_surface_create (cairo_surface_t		*target);
 
 cairo_private void
 _cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
 				 const cairo_matrix_t  *ctm);
 
 cairo_private void
@@ -66,9 +68,11 @@ cairo_private void
 
 cairo_private cairo_int_status_t
 _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
 				      cairo_int_status_t status_b);
 
 cairo_private cairo_surface_t *
 _cairo_null_surface_create (cairo_content_t content);
 
+CAIRO_END_DECLS
+
 #endif /* CAIRO_ANALYSIS_SURFACE_H */
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -32,18 +32,20 @@
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
  *      Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
 
 #include "cairo-analysis-surface-private.h"
+#include "cairo-error-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-recording-surface-private.h"
+#include "cairo-surface-subsurface-private.h"
 #include "cairo-region-private.h"
 
 typedef struct {
     cairo_surface_t base;
 
     cairo_surface_t *target;
 
     cairo_bool_t first_op;
@@ -94,33 +96,39 @@ cairo_int_status_t
 static cairo_int_status_t
 _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
 				    const cairo_pattern_t    *pattern)
 {
     const cairo_surface_pattern_t *surface_pattern;
     cairo_bool_t old_has_ctm;
     cairo_matrix_t old_ctm, p2d;
     cairo_status_t status;
+    cairo_surface_t *source;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
     surface_pattern = (const cairo_surface_pattern_t *) pattern;
-    assert (_cairo_surface_is_recording (surface_pattern->surface));
+    assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
 
     old_ctm = surface->ctm;
     old_has_ctm = surface->has_ctm;
 
     p2d = pattern->matrix;
     status = cairo_matrix_invert (&p2d);
     assert (status == CAIRO_STATUS_SUCCESS);
 
     cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
     surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
 
-    status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
-							    &surface->base);
+    source = surface_pattern->surface;
+    if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
+	cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
+	source = sub->target;
+    }
+
+    status = _cairo_recording_surface_replay_and_create_regions (source, &surface->base);
 
     surface->ctm = old_ctm;
     surface->has_ctm = old_has_ctm;
 
     return status;
 }
 
 static cairo_int_status_t
@@ -391,19 +399,19 @@ static cairo_int_status_t
     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,
+				const cairo_stroke_style_t	*style,
+				const cairo_matrix_t		*ctm,
+				const cairo_matrix_t		*ctm_inverse,
 				double			 tolerance,
 				cairo_antialias_t	 antialias,
 				cairo_clip_t		*clip)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     backend_status;
     cairo_rectangle_int_t    extents;
     cairo_bool_t             is_empty;
@@ -711,17 +719,19 @@ cairo_surface_t *
 	return _cairo_surface_create_in_error (status);
 
     surface = malloc (sizeof (cairo_analysis_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_surface_init (&surface->base,
+			 &cairo_analysis_surface_backend,
+			 NULL, /* device */
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     cairo_matrix_init_identity (&surface->ctm);
     surface->has_ctm = FALSE;
 
     surface->target = cairo_surface_reference (target);
     surface->first_op  = TRUE;
     surface->has_supported = FALSE;
@@ -826,19 +836,19 @@ typedef cairo_int_status_t
 				 const cairo_pattern_t	*mask,
 				 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,
+				 const cairo_stroke_style_t	*style,
+				 const cairo_matrix_t		*ctm,
+				 const cairo_matrix_t		*ctm_inverse,
 				 double			 tolerance,
 				 cairo_antialias_t	 antialias,
 				 cairo_clip_t		*clip);
 
 typedef cairo_int_status_t
 (*_fill_func)			(void			*surface,
 			         cairo_operator_t	 op,
 				 const cairo_pattern_t	*source,
@@ -901,12 +911,15 @@ cairo_surface_t *
 {
     cairo_surface_t *surface;
 
     surface = malloc (sizeof (cairo_surface_t));
     if (unlikely (surface == NULL)) {
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
-    _cairo_surface_init (surface, &cairo_null_surface_backend, content);
+    _cairo_surface_init (surface,
+			 &cairo_null_surface_backend,
+			 NULL, /* device */
+			 content);
 
     return surface;
 }
--- a/gfx/cairo/cairo/src/cairo-arc-private.h
+++ b/gfx/cairo/cairo/src/cairo-arc-private.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-arc.c
+++ b/gfx/cairo/cairo/src/cairo-arc.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-array.c
+++ b/gfx/cairo/cairo/src/cairo-array.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -31,16 +31,17 @@
  * California.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Carl Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
 
 /**
  * _cairo_array_init:
  *
  * Initialize a new #cairo_array_t object to store objects each of size
  * @element_size.
  *
  * The #cairo_array_t object provides grow-by-doubling storage. It
@@ -255,17 +256,17 @@ cairo_status_t
 		     const void		*element)
 {
     assert (! array->is_snapshot);
 
     return _cairo_array_append_multiple (array, element, 1);
 }
 
 /**
- * _cairo_array_append:
+ * _cairo_array_append_multiple:
  * @array: a #cairo_array_t
  *
  * Append one or more items onto the array by growing the array by
  * @num_elements, then copying @num_elements * element_size bytes from
  * @elements into the array.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful or
  * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
--- a/gfx/cairo/cairo/src/cairo-atomic-private.h
+++ b/gfx/cairo/cairo/src/cairo-atomic-private.h
@@ -1,23 +1,24 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2007 Chris Wilson
+ * Copyright © 2010 Andrea Canciani
  *
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -27,16 +28,17 @@
  *
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *	Chris Wilson <chris@chris-wilson.co.uk>
+ *	Andrea Canciani <ranma42@gmail.com>
  */
 
 #ifndef CAIRO_ATOMIC_PRIVATE_H
 #define CAIRO_ATOMIC_PRIVATE_H
 
 # include "cairo-compiler-private.h"
 
 #if HAVE_CONFIG_H
@@ -52,101 +54,204 @@
 CAIRO_BEGIN_DECLS
 
 #if HAVE_INTEL_ATOMIC_PRIMITIVES
 
 #define HAS_ATOMIC_OPS 1
 
 typedef int cairo_atomic_int_t;
 
+#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
+static cairo_always_inline cairo_atomic_int_t
+_cairo_atomic_int_get (cairo_atomic_int_t *x)
+{
+    __sync_synchronize ();
+    return *x;
+}
+
+static cairo_always_inline void *
+_cairo_atomic_ptr_get (void **x)
+{
+    __sync_synchronize ();
+    return *x;
+}
+#else
 # define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
+# define _cairo_atomic_ptr_get(x) (*x)
+#endif
 
 # 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)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
+# define _cairo_atomic_int_cmpxchg_return_old(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;
 #elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
 typedef long long cairo_atomic_intptr_t;
 #else
 #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)
+    __sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
+
+# define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
+    _cairo_atomic_intptr_to_voidptr (__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)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
 
 #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_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
 # 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)
+    _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
 
 #endif
 
+#if HAVE_OS_ATOMIC_OPS
+#include <libkern/OSAtomic.h>
+
+#define HAS_ATOMIC_OPS 1
+
+typedef int32_t cairo_atomic_int_t;
+
+# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
+
+# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
+# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
+
+#if SIZEOF_VOID_P==4
+typedef int32_t cairo_atomic_intptr_t;
+# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
+    OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
+
+#elif SIZEOF_VOID_P==8
+typedef int64_t cairo_atomic_intptr_t;
+# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
+    OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
+
+#else
+#error No matching integer pointer type
+#endif
+
+# define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
+
+#endif
 
 #ifndef HAS_ATOMIC_OPS
 
-typedef int cairo_atomic_int_t;
+#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
+
+typedef cairo_atomic_intptr_t cairo_atomic_int_t;
 
 cairo_private void
-_cairo_atomic_int_inc (int *x);
+_cairo_atomic_int_inc (cairo_atomic_int_t *x);
 
 cairo_private cairo_bool_t
-_cairo_atomic_int_dec_and_test (int *x);
+_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
 
-cairo_private int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
+cairo_private cairo_atomic_int_t
+_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv);
 
 cairo_private void *
-_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
+_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
+
+#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
+#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
 
 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
-
-# include "cairo-compiler-private.h"
-
-cairo_private int
-_cairo_atomic_int_get (int *x);
-
-cairo_private void
-_cairo_atomic_int_set (int *x, int value);
+cairo_private cairo_atomic_int_t
+_cairo_atomic_int_get (cairo_atomic_int_t *x);
+# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
+#else
+# define _cairo_atomic_int_get(x) (*x)
+# define _cairo_atomic_ptr_get(x) (*x)
+#endif
 
 #else
 
-# define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
+/* Workaround GCC complaining about casts */
+static cairo_always_inline void *
+_cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
+{
+  return (void *) x;
+}
+
+static cairo_always_inline cairo_atomic_int_t
+_cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
+{
+    cairo_atomic_int_t curr;
 
+    do {
+        curr = _cairo_atomic_int_get (x);
+    } while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
+
+    return curr;
+}
+
+static cairo_always_inline void *
+_cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
+{
+    void *curr;
+
+    do {
+        curr = _cairo_atomic_ptr_get (x);
+    } while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
+
+    return curr;
+}
 #endif
 
+#ifndef _cairo_atomic_int_cmpxchg_return_old
+#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
+#endif
+
+#ifndef _cairo_atomic_ptr_cmpxchg_return_old
+#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
+#endif
+
+#ifndef _cairo_atomic_int_cmpxchg
+#define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
+#endif
+
+#ifndef _cairo_atomic_ptr_cmpxchg
+#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
 #endif
 
 #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
 #define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \
     _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv)
 
 #define _cairo_status_set_error(status, err) do { \
     /* hide compiler warnings about cairo_status_t != int (gcc treats its as \
--- a/gfx/cairo/cairo/src/cairo-atomic.c
+++ b/gfx/cairo/cairo/src/cairo-atomic.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -37,77 +37,70 @@
 #include "cairo-mutex-private.h"
 
 #ifdef HAS_ATOMIC_OPS
 COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) ||
 		    sizeof(void*) == sizeof(long) ||
 		    sizeof(void*) == sizeof(long long));
 #else
 void
-_cairo_atomic_int_inc (int *x)
+_cairo_atomic_int_inc (cairo_atomic_intptr_t *x)
 {
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     *x += 1;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 }
 
 cairo_bool_t
-_cairo_atomic_int_dec_and_test (int *x)
+_cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x)
 {
     cairo_bool_t ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = --*x == 0;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
 
-int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
+cairo_atomic_intptr_t
+_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv)
 {
-    int ret;
+    cairo_atomic_intptr_t ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
     if (ret == oldv)
 	*x = newv;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
 
 void *
-_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
+_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv)
 {
     void *ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
     if (ret == oldv)
 	*x = newv;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
-#endif
 
 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
-int
-_cairo_atomic_int_get (int *x)
+cairo_atomic_intptr_t
+_cairo_atomic_int_get (cairo_atomic_intptr_t *x)
 {
-    int ret;
+    cairo_atomic_intptr_t ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
+#endif
 
-void
-_cairo_atomic_int_set (int *x, int value)
-{
-    CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
-    *x = value;
-    CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
-}
 #endif
--- a/gfx/cairo/cairo/src/cairo-base64-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base64-stream.c
@@ -9,17 +9,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -32,16 +32,17 @@
  * 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-error-private.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];
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -30,16 +30,17 @@
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Author(s):
  *	Kristian Høgsberg <krh@redhat.com>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
 #include "cairo-output-stream-private.h"
 
 typedef struct _cairo_base85_stream {
     cairo_output_stream_t base;
     cairo_output_stream_t *output;
     unsigned char four_tuple[4];
     int pending;
 } cairo_base85_stream_t;
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectangular.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectangular.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -33,62 +33,66 @@
  * 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-boxes-private.h"
+#include "cairo-error-private.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;
+#include <setjmp.h>
+
+typedef struct _rectangle rectangle_t;
+typedef struct _edge 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;
+struct _edge {
+    edge_t *next, *prev;
+    edge_t *right;
+    cairo_fixed_t x, top;
     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;
+struct _rectangle {
+    edge_t left, right;
+    int32_t top, bottom;
 };
 
+#define UNROLL3(x) x x x
+
 /* 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];
+    rectangle_t **elements;
+    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;
+typedef struct _sweep_line {
+    rectangle_t **rectangles;
+    pqueue_t pq;
+    edge_t head, tail;
+    edge_t *insert_left, *insert_right;
     int32_t current_y;
     int32_t last_y;
-} cairo_bo_sweep_line_t;
+
+    cairo_fill_rule_t fill_rule;
+
+    jmp_buf unwind;
+} sweep_line_t;
 
 #define DEBUG_TRAPS 0
 
 #if DEBUG_TRAPS
 static void
 dump_traps (cairo_traps_t *traps, const char *filename)
 {
     FILE *file;
@@ -116,588 +120,568 @@ dump_traps (cairo_traps_t *traps, const 
 	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)
+rectangle_compare_start (const rectangle_t *a,
+			 const 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)
+rectangle_compare_stop (const rectangle_t *a,
+			 const rectangle_t *b)
 {
     return a->bottom - b->bottom;
 }
 
 static inline void
-_pqueue_init (pqueue_t *pq)
+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)
+pqueue_fini (pqueue_t *pq)
 {
     if (pq->elements != pq->elements_embedded)
 	free (pq->elements);
 }
 
-static cairo_status_t
-_pqueue_grow (pqueue_t *pq)
+static cairo_bool_t
+pqueue_grow (pqueue_t *pq)
 {
-    cairo_bo_rectangle_t **new_elements;
+    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 *));
+					 sizeof (rectangle_t *));
 	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return FALSE;
 
 	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 *));
+					  sizeof (rectangle_t *));
 	if (unlikely (new_elements == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return FALSE;
     }
 
     pq->elements = new_elements;
-    return CAIRO_STATUS_SUCCESS;
+    return TRUE;
 }
 
-static inline cairo_status_t
-_pqueue_push (pqueue_t *pq, cairo_bo_rectangle_t *rectangle)
+static inline void
+pqueue_push (sweep_line_t *sweep, rectangle_t *rectangle)
 {
-    cairo_bo_rectangle_t **elements;
+    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;
+    if (unlikely (sweep->pq.size + 1 == sweep->pq.max_size)) {
+	if (unlikely (! pqueue_grow (&sweep->pq))) {
+	    longjmp (sweep->unwind,
+		     _cairo_error (CAIRO_STATUS_NO_MEMORY));
+	}
     }
 
-    elements = pq->elements;
-
-    for (i = ++pq->size;
+    elements = sweep->pq.elements;
+    for (i = ++sweep->pq.size;
 	 i != PQ_FIRST_ENTRY &&
-	 _cairo_bo_rectangle_compare_stop (rectangle,
-					   elements[parent = PQ_PARENT_INDEX (i)]) < 0;
+	 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)
+pqueue_pop (pqueue_t *pq)
 {
-    cairo_bo_rectangle_t **elements = pq->elements;
-    cairo_bo_rectangle_t *tail;
+    rectangle_t **elements = pq->elements;
+    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)
+	    rectangle_compare_stop (elements[child+1],
+				    elements[child]) < 0)
 	{
 	    child++;
 	}
 
-	if (_cairo_bo_rectangle_compare_stop (elements[child], tail) >= 0)
+	if (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)
+static inline rectangle_t *
+rectangle_pop_start (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)
+static inline rectangle_t *
+rectangle_peek_stop (sweep_line_t *sweep_line)
 {
-    return sweep_line->stop.elements[PQ_FIRST_ENTRY];
+    return sweep_line->pq.elements[PQ_FIRST_ENTRY];
 }
 
-CAIRO_COMBSORT_DECLARE (_cairo_bo_rectangle_sort,
-			cairo_bo_rectangle_t *,
-			cairo_bo_rectangle_compare_start)
+CAIRO_COMBSORT_DECLARE (_rectangle_sort,
+			rectangle_t *,
+			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)
+sweep_line_init (sweep_line_t	 *sweep_line,
+		 rectangle_t	**rectangles,
+		 int		  num_rectangles,
+		 cairo_fill_rule_t fill_rule)
 {
-    _cairo_bo_rectangle_sort (rectangles, num_rectangles);
+    _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->head.x = INT32_MIN;
+    sweep_line->head.right = NULL;
+    sweep_line->head.dir = 0;
+    sweep_line->head.next = &sweep_line->tail;
+    sweep_line->tail.x = INT32_MAX;
+    sweep_line->tail.right = NULL;
+    sweep_line->tail.dir = 0;
+    sweep_line->tail.prev = &sweep_line->head;
+
+    sweep_line->insert_left = &sweep_line->tail;
+    sweep_line->insert_right = &sweep_line->tail;
+
     sweep_line->current_y = INT32_MIN;
     sweep_line->last_y = INT32_MIN;
 
-    _pqueue_init (&sweep_line->stop);
+    sweep_line->fill_rule = fill_rule;
+
+    pqueue_init (&sweep_line->pq);
 }
 
 static void
-_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
+sweep_line_fini (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);
+    pqueue_fini (&sweep_line->pq);
 }
 
-static cairo_status_t
-_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
-			 int32_t		 bot,
-			 cairo_traps_t	        *traps)
+static void
+edge_end_box (sweep_line_t *sweep_line,
+	      edge_t	*left,
+	      int32_t		 bot,
+	      cairo_bool_t	 do_traps,
+	      void	        *container)
 {
-    cairo_bo_trap_t *trap = &left->deferred_trap;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     /* 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);
+    if (likely (left->top < bot)) {
+	if (do_traps) {
+	    cairo_line_t _left = {
+		{ left->x, left->top },
+		{ left->x, bot },
+	    }, _right = {
+		{ left->right->x, left->top },
+		{ left->right->x, bot },
+	    };
+	    _cairo_traps_add_trap (container, left->top, bot, &_left, &_right);
+	    status = _cairo_traps_status ((cairo_traps_t *) container);
+	} else {
+	    cairo_box_t box;
+
+	    box.p1.x = left->x;
+	    box.p1.y = left->top;
+	    box.p2.x = left->right->x;
+	    box.p2.y = bot;
+
+	    status = _cairo_boxes_add (container, &box);
+	}
     }
+    if (unlikely (status))
+	longjmp (sweep_line->unwind, status);
 
-    trap->right = NULL;
-
-    return _cairo_traps_status (traps);
+    left->right = NULL;
 }
 
 /* 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)
+static inline void
+edge_start_or_continue_box (sweep_line_t *sweep_line,
+			    edge_t	*left,
+			    edge_t	*right,
+			    int		 top,
+			    cairo_bool_t	 do_traps,
+			    void		*container)
 {
-    cairo_status_t status;
+    if (left->right == right)
+	return;
 
-    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) {
+    if (left->right != NULL) {
+	if (right != NULL && left->right->x == right->x) {
 	    /* continuation on right, so just swap edges */
-	    left->deferred_trap.right = right;
-	    return CAIRO_STATUS_SUCCESS;
+	    left->right = right;
+	    return;
 	}
 
-	status = _cairo_bo_edge_end_trap (left, top, traps);
-	if (unlikely (status))
-	    return status;
+	edge_end_box (sweep_line,
+		      left, top, do_traps, container);
     }
 
     if (right != NULL && left->x != right->x) {
-	left->deferred_trap.top = top;
-	left->deferred_trap.right = right;
+	left->top = top;
+	left->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)
+static inline void
+active_edges_to_traps (sweep_line_t	*sweep,
+		       cairo_bool_t	 do_traps,
+		       void		*container)
 {
     int top = sweep->current_y;
-    cairo_list_t *pos = &sweep->sweep;
-    cairo_status_t status;
+    edge_t *pos;
 
     if (sweep->last_y == sweep->current_y)
-	return CAIRO_STATUS_SUCCESS;
+	return;
 
-    if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-	do {
-	    cairo_bo_edge_t *left, *right;
-	    int in_out;
+    pos = sweep->head.next;
+    if (pos == &sweep->tail)
+	return;
 
-	    pos = pos->next;
-	    if (pos == &sweep->sweep)
-		break;
+    if (sweep->fill_rule == CAIRO_FILL_RULE_WINDING) {
+	do {
+	    edge_t *left, *right;
+	    int winding;
 
-	    left = link_to_edge (pos);
-	    in_out = left->dir;
+	    left = pos;
+	    winding = left->dir;
+
+	    right = left->next;
 
 	    /* Check if there is a co-linear edge with an existing trap */
-	    if (left->deferred_trap.right == NULL) {
-		right = link_to_edge (pos->next);
+	    if (left->right == NULL) {
 		while (unlikely (right->x == left->x)) {
-		    if (right->deferred_trap.right != NULL) {
+		    winding += right->dir;
+		    if (right->right != NULL) {
 			/* continuation on left */
-			left->deferred_trap = right->deferred_trap;
-			right->deferred_trap.right = NULL;
+			left->top = right->top;
+			left->right = right->right;
+			right->right = NULL;
+			winding -= right->dir;
 			break;
 		    }
 
-		    if (right->link.next == &sweep->sweep)
-			break;
-		    right = link_to_edge (right->link.next);
+		    right = right->next;
+		}
+
+		if (winding == 0) {
+		    pos = right;
+		    continue;
 		}
 	    }
 
 	    /* 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;
+		if (unlikely (right->right != NULL)) {
+		    edge_end_box (sweep,
+				  right, top, do_traps, container);
 		}
 
-		in_out += right->dir;
-		if (in_out == 0) {
+		winding += right->dir;
+		if (winding == 0) {
 		    /* skip co-linear edges */
-		    if (likely (right->link.next == &sweep->sweep ||
-				right->x != link_to_edge (right->link.next)->x))
-		    {
+		    if (likely (right->x != right->next->x))
 			break;
-		    }
 		}
 
-		right = link_to_edge (right->link.next);
+		right = right->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;
+	    edge_start_or_continue_box (sweep,
+					left, right, top,
+					do_traps, container);
 
-	    pos = pos->next;
-	    if (pos == &sweep->sweep)
-		break;
-
-	    left = link_to_edge (pos);
+	    pos = right->next;
+	} while (pos != &sweep->tail);
+    } else {
+	do {
+	    edge_t *right = pos->next;
+	    int count = 0;
 
-	    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;
+		/* End all subsumed traps */
+		if (unlikely (right->right != NULL)) {
+		    edge_end_box (sweep,
+				  right, top, do_traps, container);
 		}
 
-		if ((in_out++ & 1) == 0) {
-		    cairo_list_t *next;
-		    cairo_bool_t skip = FALSE;
-
+		if (++count & 1) {
 		    /* skip co-linear edges */
-		    next = pos->next;
-		    if (next != &sweep->sweep)
-			skip = right->x == link_to_edge (next)->x;
-
-		    if (! skip)
+		    if (likely (right->x != right->next->x))
 			break;
 		}
-		pos = pos->next;
+
+		right = right->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);
+	    edge_start_or_continue_box (sweep,
+					pos, right, top,
+					do_traps, container);
+
+	    pos = right->next;
+	} while (pos != &sweep->tail);
     }
 
     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)
+static inline void
+sweep_line_delete_edge (sweep_line_t *sweep_line,
+			edge_t *edge,
+			cairo_bool_t do_traps,
+			void *container)
 {
-    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;
+    if (edge->right != NULL) {
+	edge_t *next = edge->next;
+	if (next->x == edge->x) {
+	    next->top = edge->top;
+	    next->right = edge->right;
 	} else {
-	    cairo_status_t status;
-
-	    status = _cairo_bo_edge_end_trap (edge,
-		                              sweep_line->current_y,
-					      traps);
-	    if (unlikely (status))
-		return status;
+	    edge_end_box (sweep_line,
+			  edge,
+			  sweep_line->current_y,
+			  do_traps, container);
 	}
     }
 
-    if (sweep_line->current_left == &edge->link)
-	sweep_line->current_left = edge->link.prev;
+    if (sweep_line->insert_left == edge)
+	sweep_line->insert_left = edge->next;
+    if (sweep_line->insert_right == edge)
+	sweep_line->insert_right = edge->next;
 
-    if (sweep_line->current_right == &edge->link)
-	sweep_line->current_right = edge->link.next;
-
-    cairo_list_del (&edge->link);
-
-    return CAIRO_STATUS_SUCCESS;
+    edge->prev->next = edge->next;
+    edge->next->prev = edge->prev;
 }
 
-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)
+static inline cairo_bool_t
+sweep_line_delete (sweep_line_t	*sweep,
+		   rectangle_t	*rectangle,
+		   cairo_bool_t		 do_traps,
+		   void			*container)
 {
-    cairo_status_t status;
+    cairo_bool_t update;
 
-    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;
+    update = TRUE;
+    if (sweep->fill_rule == CAIRO_FILL_RULE_WINDING &&
+	rectangle->left.prev->dir == rectangle->left.dir)
+    {
+	update = rectangle->left.next != &rectangle->right;
     }
 
-    status = _cairo_bo_sweep_line_delete_edge (sweep_line,
-	                                       &rectangle->left,
-					       traps);
-    if (unlikely (status))
-	return status;
+    sweep_line_delete_edge (sweep,
+			    &rectangle->left,
+			    do_traps, container);
 
-    status = _cairo_bo_sweep_line_delete_edge (sweep_line,
-	                                       &rectangle->right,
-					       traps);
-    if (unlikely (status))
-	return status;
+    sweep_line_delete_edge (sweep,
+			    &rectangle->right,
+			    do_traps, container);
 
-    _pqueue_pop (&sweep_line->stop);
-    return CAIRO_STATUS_SUCCESS;
+    pqueue_pop (&sweep->pq);
+    return update;
 }
 
-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)
+static inline void
+insert_edge (edge_t *edge, edge_t *pos)
 {
-    cairo_list_t *pos;
-    cairo_status_t status;
-
-    if (rectangle->top != sweep_line->current_y) {
-	cairo_bo_rectangle_t *stop;
+    if (pos->x != edge->x) {
+	if (pos->x > edge->x) {
+	    do {
+		UNROLL3({
+		    if (pos->prev->x <= edge->x)
+			break;
+		    pos = pos->prev;
+		})
+	    } while (TRUE);
+	} else {
+	    do {
+		UNROLL3({
+		    pos = pos->next;
+		    if (pos->x >= edge->x)
+			break;
+		})
+	    } while (TRUE);
+	}
+    }
 
-	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;
+    pos->prev->next = edge;
+    edge->prev = pos->prev;
+    edge->next = pos;
+    pos->prev = edge;
+}
 
-	    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;
-    }
+static inline cairo_bool_t
+sweep_line_insert (sweep_line_t	*sweep,
+		   rectangle_t	*rectangle)
+{
+    edge_t *pos;
 
     /* 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));
+    pos = sweep->insert_right;
+    insert_edge (&rectangle->right, pos);
+    sweep->insert_right = &rectangle->right;
 
     /* left edge */
-    pos = sweep_line->current_left;
-    if (pos == &sweep_line->sweep)
-	pos = sweep_line->sweep.next;
-    if (pos != &sweep_line->sweep) {
-	int cmp;
+    pos = sweep->insert_left;
+    if (pos->x > sweep->insert_right->x)
+	pos = sweep->insert_right->prev;
+    insert_edge (&rectangle->left, pos);
+    sweep->insert_left = &rectangle->left;
 
-	if (link_to_edge (pos)->x >= rectangle->right.x) {
-	    pos = rectangle->right.link.prev;
-	    if (pos == &sweep_line->sweep)
-		goto left_done;
-	}
+    pqueue_push (sweep, rectangle);
 
-	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);
-	}
+    if (sweep->fill_rule == CAIRO_FILL_RULE_WINDING &&
+	rectangle->left.prev->dir == rectangle->left.dir)
+    {
+	return rectangle->left.next != &rectangle->right;
     }
-  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);
+    return TRUE;
 }
 
 static cairo_status_t
-_cairo_bentley_ottmann_tessellate_rectangular (cairo_bo_rectangle_t	**rectangles,
+_cairo_bentley_ottmann_tessellate_rectangular (rectangle_t	**rectangles,
 					       int			  num_rectangles,
 					       cairo_fill_rule_t	  fill_rule,
-					       cairo_traps_t		 *traps)
+					       cairo_bool_t		 do_traps,
+					       void			*container)
 {
-    cairo_bo_sweep_line_t sweep_line;
-    cairo_bo_rectangle_t *rectangle;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    sweep_line_t sweep_line;
+    rectangle_t *rectangle;
+    cairo_status_t status;
+    cairo_bool_t update = FALSE;
+
+    sweep_line_init (&sweep_line, rectangles, num_rectangles, fill_rule);
+    if ((status = setjmp (sweep_line.unwind)))
+	goto unwind;
+
+    rectangle = rectangle_pop_start (&sweep_line);
+    do {
+	if (rectangle->top != sweep_line.current_y) {
+	    rectangle_t *stop;
+
+	    stop = rectangle_peek_stop (&sweep_line);
+	    while (stop != NULL && stop->bottom < rectangle->top) {
+		if (stop->bottom != sweep_line.current_y) {
+		    if (update) {
+			active_edges_to_traps (&sweep_line,
+					       do_traps, container);
+			update = FALSE;
+		    }
 
-    _cairo_bo_sweep_line_init (&sweep_line, rectangles, num_rectangles);
+		    sweep_line.current_y = stop->bottom;
+		}
+
+		update |= sweep_line_delete (&sweep_line, stop, do_traps, container);
+
+		stop = rectangle_peek_stop (&sweep_line);
+	    }
+
+	    if (update) {
+		active_edges_to_traps (&sweep_line, do_traps, container);
+		update = FALSE;
+	    }
 
-    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;
+	    sweep_line.current_y = rectangle->top;
+	}
+
+	update |= sweep_line_insert (&sweep_line, rectangle);
+    } while ((rectangle = rectangle_pop_start (&sweep_line)) != NULL);
+
+    while ((rectangle = rectangle_peek_stop (&sweep_line)) != NULL) {
+	if (rectangle->bottom != sweep_line.current_y) {
+	    if (update) {
+		active_edges_to_traps (&sweep_line, do_traps, container);
+		update = FALSE;
+	    }
+
+	    sweep_line.current_y = rectangle->bottom;
+	}
+
+	update |= sweep_line_delete (&sweep_line, rectangle, do_traps, container);
     }
 
-    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);
+unwind:
+    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;
+    rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
+    rectangle_t *rectangles;
+    rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
+    rectangle_t **rectangles_ptrs;
     cairo_status_t status;
     int i;
 
-    if (unlikely (traps->num_traps == 0))
+    if (unlikely (traps->num_traps <= 1))
 	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 *));
+					  sizeof (rectangle_t) +
+					  sizeof (rectangle_t *),
+					  sizeof (rectangle_t *));
 	if (unlikely (rectangles == NULL))
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	rectangles_ptrs = (cairo_bo_rectangle_t **) (rectangles + traps->num_traps);
+	rectangles_ptrs = (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;
@@ -705,35 +689,99 @@ cairo_status_t
 	} 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].left.right = NULL;
+	rectangles[i].right.right = NULL;
 
 	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);
+							    TRUE, 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;
+}
+
+cairo_status_t
+_cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
+					 cairo_fill_rule_t fill_rule,
+					 cairo_boxes_t *out)
+{
+    rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
+    rectangle_t *rectangles;
+    rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
+    rectangle_t **rectangles_ptrs;
+    const struct _cairo_boxes_chunk *chunk;
+    cairo_status_t status;
+    int i, j;
+
+    if (unlikely (in->num_boxes <= 1))
+	return CAIRO_STATUS_SUCCESS;
+
+    rectangles = stack_rectangles;
+    rectangles_ptrs = stack_rectangles_ptrs;
+    if (in->num_boxes > ARRAY_LENGTH (stack_rectangles)) {
+	rectangles = _cairo_malloc_ab_plus_c (in->num_boxes,
+					  sizeof (rectangle_t) +
+					  sizeof (rectangle_t *),
+					  sizeof (rectangle_t *));
+	if (unlikely (rectangles == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	rectangles_ptrs = (rectangle_t **) (rectangles + in->num_boxes);
+    }
+
+    j = 0;
+    for (chunk = &in->chunks; chunk != NULL; chunk = chunk->next) {
+	const cairo_box_t *box = chunk->base;
+	for (i = 0; i < chunk->count; i++) {
+	    if (box[i].p1.x < box[i].p2.x) {
+		rectangles[j].left.x = box[i].p1.x;
+		rectangles[j].left.dir = 1;
+
+		rectangles[j].right.x = box[i].p2.x;
+		rectangles[j].right.dir = -1;
+	    } else {
+		rectangles[j].right.x = box[i].p1.x;
+		rectangles[j].right.dir = 1;
+
+		rectangles[j].left.x = box[i].p2.x;
+		rectangles[j].left.dir = -1;
+	    }
+
+	    rectangles[j].left.right = NULL;
+	    rectangles[j].right.right = NULL;
+
+	    rectangles[j].top = box[i].p1.y;
+	    rectangles[j].bottom = box[i].p2.y;
+
+	    rectangles_ptrs[j] = &rectangles[j];
+	    j++;
+	}
+    }
+
+    _cairo_boxes_clear (out);
+    status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs, j,
+							    fill_rule,
+							    FALSE, out);
+    if (rectangles != stack_rectangles)
+	free (rectangles);
 
     return status;
 }
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectilinear.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann-rectilinear.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -33,17 +33,19 @@
  * 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-boxes-private.h"
 #include "cairo-combsort-private.h"
+#include "cairo-error-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;
@@ -210,74 +212,89 @@ 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_bool_t		 do_traps,
+			 void			*container)
 {
     cairo_bo_trap_t *trap = &left->deferred_trap;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     /* 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 (do_traps) {
+	    _cairo_traps_add_trap (container,
+				   trap->top, bot,
+				   &left->edge.line, &trap->right->edge.line);
+	    status =  _cairo_traps_status ((cairo_traps_t *) container);
+	} else {
+	    cairo_box_t box;
+
+	    box.p1.x = left->edge.line.p1.x;
+	    box.p1.y = trap->top;
+	    box.p2.x = trap->right->edge.line.p1.x;
+	    box.p2.y = bot;
+	    status = _cairo_boxes_add (container, &box);
+	}
     }
 
     trap->right = NULL;
 
-    return _cairo_traps_status (traps);
+    return status;
 }
 
 /* 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_bool_t	 do_traps,
+				       void		*container)
 {
     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);
+	status = _cairo_bo_edge_end_trap (left, top, do_traps, container);
 	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_bool_t		 do_traps,
+			void			*container)
 {
     cairo_bo_edge_t *right;
     cairo_status_t status;
 
     if (fill_rule == CAIRO_FILL_RULE_WINDING) {
 	while (left != NULL) {
 	    int in_out;
 
@@ -298,17 +315,17 @@ static inline cairo_status_t
 		    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);
+		    status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
 		    if (unlikely (status))
 			return status;
 		}
 
 		in_out += right->edge.dir;
 		if (in_out == 0) {
 		    /* skip co-linear edges */
 		    if (right->next == NULL ||
@@ -316,33 +333,33 @@ static inline cairo_status_t
 		    {
 			break;
 		    }
 		}
 
 		right = right->next;
 	    }
 
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
+	    status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
+							    do_traps, container);
 	    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);
+		    status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
 		    if (unlikely (status))
 			return status;
 		}
 
 		if ((in_out++ & 1) == 0) {
 		    cairo_bo_edge_t *next;
 		    cairo_bool_t skip = FALSE;
 
@@ -353,47 +370,48 @@ static inline cairo_status_t
 
 		    if (! skip)
 			break;
 		}
 
 		right = right->next;
 	    }
 
-	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-							    top, traps);
+	    status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
+							    do_traps, container);
 	    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_bool_t		 do_traps,
+					       void			*container)
 {
     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);
+					     fill_rule, do_traps, container);
 	    if (unlikely (status))
 		return status;
 
 	    sweep_line.current_y = event->point.y;
 	}
 
 	switch (event->type) {
 	case CAIRO_BO_EVENT_TYPE_START:
@@ -401,17 +419,17 @@ static cairo_status_t
 	    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);
+						  do_traps, container);
 		if (unlikely (status))
 		    return status;
 	    }
 
 	    break;
 	}
     }
 
@@ -471,26 +489,93 @@ cairo_status_t
 	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);
+							    fill_rule,
+							    TRUE, traps);
     if (events != stack_events)
 	free (events);
 
     traps->is_rectilinear = TRUE;
 
     return status;
 }
 
 cairo_status_t
+_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon,
+								cairo_fill_rule_t	  fill_rule,
+								cairo_boxes_t *boxes)
+{
+    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,
+							    FALSE, boxes);
+    if (events != stack_events)
+	free (events);
+
+    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)];
@@ -567,16 +652,16 @@ cairo_status_t
 	events[j].edge = &edges[k];
 	j++;
 	k++;
     }
 
     _cairo_traps_clear (traps);
     status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
 							    fill_rule,
-							    traps);
+							    TRUE, 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
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -33,16 +33,17 @@
  * 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-error-private.h"
 #include "cairo-freelist-private.h"
 #include "cairo-combsort-private.h"
 
 #define DEBUG_PRINT_STATE 0
 #define DEBUG_EVENTS 0
 #define DEBUG_TRAPS 0
 
 typedef cairo_point_t cairo_bo_point32_t;
@@ -124,31 +125,35 @@ typedef struct _cairo_bo_sweep_line {
     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;
+    cairo_box_t extents;
     int n;
 
     if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
 	return;
 
+#if 0
     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);
     }
+#endif
+    _cairo_traps_extents (traps, &extents);
     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);
+	    extents.p1.x, extents.p1.y,
+	    extents.p2.x, 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,
--- a/gfx/cairo/cairo/src/cairo-beos.h
+++ b/gfx/cairo/cairo/src/cairo-beos.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-botor-scan-converter.c
@@ -0,0 +1,2199 @@
+/*
+ * Copyright © 2004 Carl Worth
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2007 David Turner
+ * Copyright © 2008 M Joonas Pihlaja
+ * Copyright © 2008 Chris Wilson
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
+ *      M Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+/* Provide definitions for standalone compilation */
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-list-private.h"
+#include "cairo-freelist-private.h"
+#include "cairo-combsort-private.h"
+
+#include <setjmp.h>
+
+#define STEP_X CAIRO_FIXED_ONE
+#define STEP_Y CAIRO_FIXED_ONE
+#define UNROLL3(x) x x x
+
+#define STEP_XY (2*STEP_X*STEP_Y) /* Unit area in the step. */
+#define AREA_TO_ALPHA(c)  (((c)*255 + STEP_XY/2) / STEP_XY)
+
+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;
+
+struct quorem {
+    cairo_fixed_t quo;
+    cairo_fixed_t rem;
+};
+
+struct run {
+    struct run *next;
+    int sign;
+    cairo_fixed_t y;
+};
+
+typedef struct edge {
+    cairo_list_t link;
+
+    cairo_edge_t edge;
+
+    /* Current x coordinate and advancement.
+     * Initialised to the x coordinate of the top of the
+     * edge. The quotient is in cairo_fixed_t units and the
+     * remainder is mod dy in cairo_fixed_t units.
+     */
+    cairo_fixed_t dy;
+    struct quorem x;
+    struct quorem dxdy;
+    struct quorem dxdy_full;
+
+    cairo_bool_t vertical;
+    unsigned int flags;
+
+    int current_sign;
+    struct run *runs;
+} edge_t;
+
+enum {
+    START = 0x1,
+    STOP = 0x2,
+};
+
+/* 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 {
+    EVENT_TYPE_STOP,
+    EVENT_TYPE_INTERSECTION,
+    EVENT_TYPE_START
+} event_type_t;
+
+typedef struct _event {
+    cairo_fixed_t y;
+    event_type_t type;
+} event_t;
+
+typedef struct _start_event {
+    cairo_fixed_t y;
+    event_type_t type;
+    edge_t *edge;
+} start_event_t;
+
+typedef struct _queue_event {
+    cairo_fixed_t y;
+    event_type_t type;
+    edge_t *e1;
+    edge_t *e2;
+} queue_event_t;
+
+typedef struct _pqueue {
+    int size, max_size;
+
+    event_t **elements;
+    event_t *elements_embedded[1024];
+} pqueue_t;
+
+struct cell {
+    struct cell	*prev;
+    struct cell	*next;
+    int		 x;
+    int		 uncovered_area;
+    int		 covered_height;
+};
+
+typedef struct _sweep_line {
+    cairo_list_t active;
+    cairo_list_t stopped;
+    cairo_list_t *insert_cursor;
+    cairo_bool_t is_vertical;
+
+    cairo_fixed_t current_row;
+    cairo_fixed_t current_subrow;
+
+    struct coverage {
+	struct cell head;
+	struct cell tail;
+
+	struct cell *cursor;
+	int count;
+
+	cairo_freepool_t pool;
+    } coverage;
+
+    struct event_queue {
+	pqueue_t pq;
+	event_t **start_events;
+
+	cairo_freepool_t pool;
+    } queue;
+
+    cairo_freepool_t runs;
+
+    jmp_buf unwind;
+} sweep_line_t;
+
+cairo_always_inline static struct quorem
+floored_divrem (int a, int b)
+{
+    struct quorem qr;
+    qr.quo = a/b;
+    qr.rem = a%b;
+    if ((a^b)<0 && qr.rem) {
+	qr.quo--;
+	qr.rem += b;
+    }
+    return qr;
+}
+
+static struct quorem
+floored_muldivrem(int x, int a, int b)
+{
+    struct quorem qr;
+    long long xa = (long long)x*a;
+    qr.quo = xa/b;
+    qr.rem = xa%b;
+    if ((xa>=0) != (b>=0) && qr.rem) {
+	qr.quo--;
+	qr.rem += b;
+    }
+    return qr;
+}
+
+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;
+}
+
+/*
+ * We need to compare the x-coordinates of a pair of lines for a particular y,
+ * without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ *   X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ *   A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
+ * where ∘ is our inequality operator.
+ *
+ * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ *   A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
+ *                                 - (Y - A_y) * A_dx * B_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
+ *
+ * (And put the burden of the work on developing fast 128 bit ops, which are
+ * required throughout the tessellator.)
+ *
+ * See the similar discussion for _slope_compare().
+ */
+static int
+edges_compare_x_for_y_general (const cairo_edge_t *a,
+			       const cairo_edge_t *b,
+			       int32_t y)
+{
+    /* XXX: We're assuming here that dx and dy will still fit in 32
+     * bits. That's not true in general as there could be overflow. We
+     * should prevent that before the tessellation algorithm
+     * begins.
+     */
+    int32_t dx;
+    int32_t adx, ady;
+    int32_t bdx, bdy;
+    enum {
+       HAVE_NONE    = 0x0,
+       HAVE_DX      = 0x1,
+       HAVE_ADX     = 0x2,
+       HAVE_DX_ADX  = HAVE_DX | HAVE_ADX,
+       HAVE_BDX     = 0x4,
+       HAVE_DX_BDX  = HAVE_DX | HAVE_BDX,
+       HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+       HAVE_ALL     = HAVE_DX | HAVE_ADX | HAVE_BDX
+    } have_dx_adx_bdx = HAVE_ALL;
+
+    /* 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->line.p1.x < a->line.p2.x) {
+                   amin = a->line.p1.x;
+                   amax = a->line.p2.x;
+           } else {
+                   amin = a->line.p2.x;
+                   amax = a->line.p1.x;
+           }
+           if (b->line.p1.x < b->line.p2.x) {
+                   bmin = b->line.p1.x;
+                   bmax = b->line.p2.x;
+           } else {
+                   bmin = b->line.p2.x;
+                   bmax = b->line.p1.x;
+           }
+           if (amax < bmin) return -1;
+           if (amin > bmax) return +1;
+    }
+
+    ady = a->line.p2.y - a->line.p1.y;
+    adx = a->line.p2.x - a->line.p1.x;
+    if (adx == 0)
+	have_dx_adx_bdx &= ~HAVE_ADX;
+
+    bdy = b->line.p2.y - b->line.p1.y;
+    bdx = b->line.p2.x - b->line.p1.x;
+    if (bdx == 0)
+	have_dx_adx_bdx &= ~HAVE_BDX;
+
+    dx = a->line.p1.x - b->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->line.p1.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->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:
+	/* 0 ∘  - (Y - A_y) * A_dx * B_dy */
+	return adx; /* bdy * (y - a->top.y) is positive definite */
+    case HAVE_BDX:
+	/* 0 ∘ (Y - B_y) * B_dx * A_dy */
+	return -bdx; /* ady * (y - b->top.y) is positive definite */
+    case HAVE_ADX_BDX:
+	/*  0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+	if ((adx ^ bdx) < 0) {
+	    return adx;
+	} else if (a->line.p1.y == b->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);
+	} else
+	    return _cairo_int128_cmp (A, B);
+    case HAVE_DX_ADX:
+	/* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
+	if ((-adx ^ dx) < 0) {
+	    return dx;
+	} else {
+	    cairo_int64_t ady_dx, dy_adx;
+
+	    ady_dx = _cairo_int32x32_64_mul (ady, dx);
+	    dy_adx = _cairo_int32x32_64_mul (a->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->line.p1.y, bdx);
+
+	    return _cairo_int64_cmp (bdy_dx, dy_bdx);
+	}
+    case HAVE_ALL:
+	/* XXX try comparing (a->line.p2.x - b->line.p2.x) et al */
+	return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+    }
+#undef B
+#undef A
+#undef L
+}
+
+/*
+ * We need to compare the x-coordinate of a line for a particular y wrt to a
+ * given x, without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ *   X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ *   A_x + (Y - A_y) * A_dx / A_dy ∘ X
+ * where ∘ is our inequality operator.
+ *
+ * By construction, we know that A_dy (and (Y - A_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ *   (Y - A_y) * A_dx ∘ (X - A_x) * A_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 64 bit arithmetic.
+ *
+ * See the similar discussion for _slope_compare() and
+ * edges_compare_x_for_y_general().
+ */
+static int
+edge_compare_for_y_against_x (const cairo_edge_t *a,
+			      int32_t y,
+			      int32_t x)
+{
+    int32_t adx, ady;
+    int32_t dx, dy;
+    cairo_int64_t L, R;
+
+    if (a->line.p1.x <= a->line.p2.x) {
+	if (x < a->line.p1.x)
+	    return 1;
+	if (x > a->line.p2.x)
+	    return -1;
+    } else {
+	if (x < a->line.p2.x)
+	    return 1;
+	if (x > a->line.p1.x)
+	    return -1;
+    }
+
+    adx = a->line.p2.x - a->line.p1.x;
+    dx = x - a->line.p1.x;
+
+    if (adx == 0)
+	return -dx;
+    if (dx == 0 || (adx ^ dx) < 0)
+	return adx;
+
+    dy = y - a->line.p1.y;
+    ady = a->line.p2.y - a->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
+edges_compare_x_for_y (const cairo_edge_t *a,
+		       const cairo_edge_t *b,
+		       int32_t y)
+{
+    /* If the sweep-line is currently on an end-point of a line,
+     * then we know its precise x value (and considering that we often need to
+     * compare events at end-points, this happens frequently enough to warrant
+     * special casing).
+     */
+    enum {
+       HAVE_NEITHER = 0x0,
+       HAVE_AX      = 0x1,
+       HAVE_BX      = 0x2,
+       HAVE_BOTH    = HAVE_AX | HAVE_BX
+    } have_ax_bx = HAVE_BOTH;
+    int32_t ax, bx;
+
+    /* XXX given we have x and dx? */
+
+    if (y == a->line.p1.y)
+	ax = a->line.p1.x;
+    else if (y == a->line.p2.y)
+	ax = a->line.p2.x;
+    else
+	have_ax_bx &= ~HAVE_AX;
+
+    if (y == b->line.p1.y)
+	bx = b->line.p1.x;
+    else if (y == b->line.p2.y)
+	bx = b->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 inline int
+slope_compare (const edge_t *a,
+	       const edge_t *b)
+{
+    cairo_int64_t L, R;
+    int cmp;
+
+    cmp = a->dxdy.quo - b->dxdy.quo;
+    if (cmp)
+	return cmp;
+
+    if (a->dxdy.rem == 0)
+	return -b->dxdy.rem;
+    if (b->dxdy.rem == 0)
+	return a->dxdy.rem;
+
+    L = _cairo_int32x32_64_mul (b->dy, a->dxdy.rem);
+    R = _cairo_int32x32_64_mul (a->dy, b->dxdy.rem);
+    return _cairo_int64_cmp (L, R);
+}
+
+static inline int
+line_equal (const cairo_line_t *a, const cairo_line_t *b)
+{
+    return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
+           a->p2.x == b->p2.x && a->p2.y == b->p2.y;
+}
+
+static inline int
+sweep_line_compare_edges (const edge_t	*a,
+			  const edge_t	*b,
+			  cairo_fixed_t y)
+{
+    int cmp;
+
+    if (line_equal (&a->edge.line, &b->edge.line))
+	return 0;
+
+    cmp = edges_compare_x_for_y (&a->edge, &b->edge, y);
+    if (cmp)
+	return cmp;
+
+    return slope_compare (a, b);
+}
+
+static inline cairo_int64_t
+det32_64 (int32_t a, int32_t b,
+	  int32_t c, int32_t d)
+{
+    /* det = a * d - b * c */
+    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)
+{
+    /* det = a * d - b * c */
+    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_bool_t
+intersect_lines (const edge_t *a, const edge_t *b,
+		 cairo_bo_intersect_point_t	*intersection)
+{
+    cairo_int64_t a_det, b_det;
+
+    /* XXX: We're assuming here that dx and dy will still fit in 32
+     * bits. That's not true in general as there could be overflow. We
+     * should prevent that before the tessellation algorithm begins.
+     * What we're doing to mitigate this is to perform clamping in
+     * cairo_bo_tessellate_polygon().
+     */
+    int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
+    int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
+
+    int32_t 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);
+
+     /* Q: Can we determine that the lines do not intersect (within range)
+      * much more cheaply than computing the intersection point i.e. by
+      * avoiding the division?
+      *
+      *   X = ax + t * adx = bx + s * bdx;
+      *   Y = ay + t * ady = by + s * bdy;
+      *   ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
+      *   => t * L = R
+      *
+      * Therefore we can reject any intersection (under the criteria for
+      * valid intersection events) if:
+      *   L^R < 0 => t < 0, or
+      *   L<R => t > 1
+      *
+      * (where top/bottom must at least extend to the line endpoints).
+      *
+      * A similar substitution can be performed for s, yielding:
+      *   s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
+      */
+    R = det32_64 (dx2, dy2,
+		  b->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 FALSE;
+    } else {
+	if (_cairo_int64_le (den_det, R))
+	    return FALSE;
+    }
+
+    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 FALSE;
+    } else {
+	if (_cairo_int64_le (den_det, R))
+	    return FALSE;
+    }
+
+    /* We now know that the two lines should intersect within range. */
+
+    a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
+		      a->edge.line.p2.x, a->edge.line.p2.y);
+    b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
+		      b->edge.line.p2.x, b->edge.line.p2.y);
+
+    /* x = det (a_det, dx1, b_det, dx2) / den_det */
+    qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
+						       b_det, dx2),
+					 den_det);
+    if (_cairo_int64_eq (qr.rem, den_det))
+	return FALSE;
+#if 0
+    intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+    intersection->x.exactness = EXACT;
+    if (! _cairo_int64_is_zero (qr.rem)) {
+	if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
+	    qr.rem = _cairo_int64_negate (qr.rem);
+	qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
+	if (_cairo_int64_ge (qr.rem, den_det)) {
+	    qr.quo = _cairo_int64_add (qr.quo,
+				       _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+	} else
+	    intersection->x.exactness = INEXACT;
+    }
+#endif
+    intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+    /* y = det (a_det, dy1, b_det, dy2) / den_det */
+    qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
+						       b_det, dy2),
+					 den_det);
+    if (_cairo_int64_eq (qr.rem, den_det))
+	return FALSE;
+#if 0
+    intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+    intersection->y.exactness = EXACT;
+    if (! _cairo_int64_is_zero (qr.rem)) {
+	/* compute ceiling away from zero */
+	qr.quo = _cairo_int64_add (qr.quo,
+				   _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+	intersection->y.exactness = INEXACT;
+    }
+#endif
+    intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+    return TRUE;
+}
+
+static int
+bo_intersect_ordinate_32_compare (int32_t a, int32_t b, int exactness)
+{
+    int cmp;
+
+    /* First compare the quotient */
+    cmp = a - b;
+    if (cmp)
+	return cmp;
+
+    /* With quotient identical, if remainder is 0 then compare equal */
+    /* Otherwise, the non-zero remainder makes a > b */
+    return -(INEXACT == exactness);
+}
+
+/* Does the given edge contain the given point. The point must already
+ * be known to be contained within the line determined by the edge,
+ * (most likely the point results from an intersection of this edge
+ * with another).
+ *
+ * If we had exact arithmetic, then this function would simply be a
+ * matter of examining whether the y value of the point lies within
+ * the range of y values of the edge. But since intersection points
+ * are not exact due to being rounded to the nearest integer within
+ * the available precision, we must also examine the x value of the
+ * point.
+ *
+ * The definition of "contains" here is that the given intersection
+ * point will be seen by the sweep line after the start event for the
+ * given edge and before the stop event for the edge. See the comments
+ * in the implementation for more details.
+ */
+static cairo_bool_t
+bo_edge_contains_intersect_point (const edge_t			*edge,
+				  cairo_bo_intersect_point_t	*point)
+{
+    int cmp_top, cmp_bottom;
+
+    /* 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 = bo_intersect_ordinate_32_compare (point->y.ordinate,
+						edge->edge.top,
+						point->y.exactness);
+    if (cmp_top < 0)
+	return FALSE;
+
+    cmp_bottom = bo_intersect_ordinate_32_compare (point->y.ordinate,
+						   edge->edge.bottom,
+						   point->y.exactness);
+    if (cmp_bottom > 0)
+	return FALSE;
+
+    if (cmp_top > 0 && cmp_bottom < 0)
+	return TRUE;
+
+    /* At this stage, the point lies on the same y value as either
+     * edge->top or edge->bottom, so we have to examine the x value in
+     * order to properly determine containment. */
+
+    /* If the y value of the point is the same as the y value of the
+     * top of the edge, then the x value of the point must be greater
+     * to be considered as inside the edge. Similarly, if the y value
+     * of the point is the same as the y value of the bottom of the
+     * edge, then the x value of the point must be less to be
+     * considered as inside. */
+
+    if (cmp_top == 0) {
+	cairo_fixed_t top_x;
+
+	top_x = line_compute_intersection_x_for_y (&edge->edge.line,
+						   edge->edge.top);
+	return bo_intersect_ordinate_32_compare (top_x, point->x.ordinate, point->x.exactness) < 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 bo_intersect_ordinate_32_compare (point->x.ordinate, bot_x, point->x.exactness) < 0;
+    }
+}
+
+static cairo_bool_t
+edge_intersect (const edge_t		*a,
+		const edge_t		*b,
+		cairo_point_t	*intersection)
+{
+    cairo_bo_intersect_point_t quorem;
+
+    if (! intersect_lines (a, b, &quorem))
+	return FALSE;
+
+    if (a->edge.top != a->edge.line.p1.y || a->edge.bottom != a->edge.line.p2.y) {
+	if (! bo_edge_contains_intersect_point (a, &quorem))
+	    return FALSE;
+    }
+
+    if (b->edge.top != b->edge.line.p1.y || b->edge.bottom != b->edge.line.p2.y) {
+	if (! bo_edge_contains_intersect_point (b, &quorem))
+	    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 TRUE;
+}
+
+static inline int
+event_compare (const event_t *a, const event_t *b)
+{
+    return a->y - b->y;
+}
+
+static void
+pqueue_init (pqueue_t *pq)
+{
+    pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
+    pq->size = 0;
+
+    pq->elements = pq->elements_embedded;
+}
+
+static void
+pqueue_fini (pqueue_t *pq)
+{
+    if (pq->elements != pq->elements_embedded)
+	free (pq->elements);
+}
+
+static cairo_bool_t
+pqueue_grow (pqueue_t *pq)
+{
+    event_t **new_elements;
+    pq->max_size *= 2;
+
+    if (pq->elements == pq->elements_embedded) {
+	new_elements = _cairo_malloc_ab (pq->max_size,
+					 sizeof (event_t *));
+	if (unlikely (new_elements == NULL))
+	    return FALSE;
+
+	memcpy (new_elements, pq->elements_embedded,
+		sizeof (pq->elements_embedded));
+    } else {
+	new_elements = _cairo_realloc_ab (pq->elements,
+					  pq->max_size,
+					  sizeof (event_t *));
+	if (unlikely (new_elements == NULL))
+	    return FALSE;
+    }
+
+    pq->elements = new_elements;
+    return TRUE;
+}
+
+static inline void
+pqueue_push (sweep_line_t *sweep_line, event_t *event)
+{
+    event_t **elements;
+    int i, parent;
+
+    if (unlikely (sweep_line->queue.pq.size + 1 == sweep_line->queue.pq.max_size)) {
+	if (unlikely (! pqueue_grow (&sweep_line->queue.pq))) {
+	    longjmp (sweep_line->unwind,
+		     _cairo_error (CAIRO_STATUS_NO_MEMORY));
+	}
+    }
+
+    elements = sweep_line->queue.pq.elements;
+    for (i = ++sweep_line->queue.pq.size;
+	 i != PQ_FIRST_ENTRY &&
+	 event_compare (event,
+			elements[parent = PQ_PARENT_INDEX (i)]) < 0;
+	 i = parent)
+    {
+	elements[i] = elements[parent];
+    }
+
+    elements[i] = event;
+}
+
+static inline void
+pqueue_pop (pqueue_t *pq)
+{
+    event_t **elements = pq->elements;
+    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 &&
+	    event_compare (elements[child+1],
+			   elements[child]) < 0)
+	{
+	    child++;
+	}
+
+	if (event_compare (elements[child], tail) >= 0)
+	    break;
+
+	elements[i] = elements[child];
+    }
+    elements[i] = tail;
+}
+
+static inline void
+event_insert (sweep_line_t	*sweep_line,
+	      event_type_t	 type,
+	      edge_t		*e1,
+	      edge_t		*e2,
+	      cairo_fixed_t	 y)
+{
+    queue_event_t *event;
+
+    event = _cairo_freepool_alloc (&sweep_line->queue.pool);
+    if (unlikely (event == NULL)) {
+	longjmp (sweep_line->unwind,
+		 _cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    event->y = y;
+    event->type = type;
+    event->e1 = e1;
+    event->e2 = e2;
+
+    pqueue_push (sweep_line, (event_t *) event);
+}
+
+static void
+event_delete (sweep_line_t	*sweep_line,
+	      event_t		*event)
+{
+    _cairo_freepool_free (&sweep_line->queue.pool, event);
+}
+
+static inline event_t *
+event_next (sweep_line_t *sweep_line)
+{
+    event_t *event, *cmp;
+
+    event = sweep_line->queue.pq.elements[PQ_FIRST_ENTRY];
+    cmp = *sweep_line->queue.start_events;
+    if (event == NULL ||
+	(cmp != NULL && event_compare (cmp, event) < 0))
+    {
+	event = cmp;
+	sweep_line->queue.start_events++;
+    }
+    else
+    {
+	pqueue_pop (&sweep_line->queue.pq);
+    }
+
+    return event;
+}
+
+CAIRO_COMBSORT_DECLARE (start_event_sort, event_t *, event_compare)
+
+static inline void
+event_insert_stop (sweep_line_t	*sweep_line,
+		   edge_t	*edge)
+{
+    event_insert (sweep_line,
+		  EVENT_TYPE_STOP,
+		  edge, NULL,
+		  edge->edge.bottom);
+}
+
+static inline void
+event_insert_if_intersect_below_current_y (sweep_line_t	*sweep_line,
+					   edge_t	*left,
+					   edge_t	*right)
+{
+    cairo_point_t intersection;
+
+    /* start points intersect */
+    if (left->edge.line.p1.x == right->edge.line.p1.x &&
+	left->edge.line.p1.y == right->edge.line.p1.y)
+    {
+	return;
+    }
+
+    /* end points intersect, process DELETE events first */
+    if (left->edge.line.p2.x == right->edge.line.p2.x &&
+	left->edge.line.p2.y == right->edge.line.p2.y)
+    {
+	return;
+    }
+
+    if (slope_compare (left, right) <= 0)
+	return;
+
+    if (! edge_intersect (left, right, &intersection))
+	return;
+
+    event_insert (sweep_line,
+		  EVENT_TYPE_INTERSECTION,
+		  left, right,
+		  intersection.y);
+}
+
+static inline edge_t *
+link_to_edge (cairo_list_t *link)
+{
+    return (edge_t *) link;
+}
+
+static void
+sweep_line_insert (sweep_line_t	*sweep_line,
+		   edge_t	*edge)
+{
+    cairo_list_t *pos;
+    cairo_fixed_t y = sweep_line->current_subrow;
+
+    pos = sweep_line->insert_cursor;
+    if (pos == &sweep_line->active)
+	pos = sweep_line->active.next;
+    if (pos != &sweep_line->active) {
+	int cmp;
+
+	cmp = sweep_line_compare_edges (link_to_edge (pos),
+					edge,
+					y);
+	if (cmp < 0) {
+	    while (pos->next != &sweep_line->active &&
+		   sweep_line_compare_edges (link_to_edge (pos->next),
+					     edge,
+					     y) < 0)
+	    {
+		pos = pos->next;
+	    }
+	} else if (cmp > 0) {
+	    do {
+		pos = pos->prev;
+	    } while (pos != &sweep_line->active &&
+		     sweep_line_compare_edges (link_to_edge (pos),
+					       edge,
+					       y) > 0);
+	}
+    }
+    cairo_list_add (&edge->link, pos);
+    sweep_line->insert_cursor = &edge->link;
+}
+
+inline static void
+coverage_rewind (struct coverage *cells)
+{
+    cells->cursor = &cells->head;
+}
+
+static void
+coverage_init (struct coverage *cells)
+{
+    _cairo_freepool_init (&cells->pool,
+			  sizeof (struct cell));
+    cells->head.prev = NULL;
+    cells->head.next = &cells->tail;
+    cells->head.x = INT_MIN;
+    cells->tail.prev = &cells->head;
+    cells->tail.next = NULL;
+    cells->tail.x = INT_MAX;
+    cells->count = 0;
+    coverage_rewind (cells);
+}
+
+static void
+coverage_fini (struct coverage *cells)
+{
+    _cairo_freepool_fini (&cells->pool);
+}
+
+inline static void
+coverage_reset (struct coverage *cells)
+{
+    cells->head.next = &cells->tail;
+    cells->tail.prev = &cells->head;
+    cells->count = 0;
+    _cairo_freepool_reset (&cells->pool);
+    coverage_rewind (cells);
+}
+
+inline static struct cell *
+coverage_alloc (sweep_line_t *sweep_line,
+		struct cell *tail,
+		int x)
+{
+    struct cell *cell;
+
+    cell = _cairo_freepool_alloc (&sweep_line->coverage.pool);
+    if (unlikely (NULL == cell)) {
+	longjmp (sweep_line->unwind,
+		 _cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    tail->prev->next = cell;
+    cell->prev = tail->prev;
+    cell->next = tail;
+    tail->prev = cell;
+    cell->x = x;
+    cell->uncovered_area = 0;
+    cell->covered_height = 0;
+    sweep_line->coverage.count++;
+    return cell;
+}
+
+inline static struct cell *
+coverage_find (sweep_line_t *sweep_line, int x)
+{
+    struct cell *cell;
+
+    cell = sweep_line->coverage.cursor;
+    if (unlikely (cell->x > x)) {
+	do {
+	    if (cell->prev->x < x)
+		break;
+	    cell = cell->prev;
+	} while (TRUE);
+    } else {
+	if (cell->x == x)
+	    return cell;
+
+	do {
+	    UNROLL3({
+		    cell = cell->next;
+		    if (cell->x >= x)
+			break;
+		    });
+	} while (TRUE);
+    }
+
+    if (cell->x != x)
+	cell = coverage_alloc (sweep_line, cell, x);
+
+    return sweep_line->coverage.cursor = cell;
+}
+
+static void
+coverage_render_cells (sweep_line_t *sweep_line,
+		       cairo_fixed_t left, cairo_fixed_t right,
+		       cairo_fixed_t y1, cairo_fixed_t y2,
+		       int sign)
+{
+    int fx1, fx2;
+    int ix1, ix2;
+    int dx, dy;
+
+    /* Orient the edge left-to-right. */
+    dx = right - left;
+    if (dx >= 0) {
+	ix1 = _cairo_fixed_integer_part (left);
+	fx1 = _cairo_fixed_fractional_part (left);
+
+	ix2 = _cairo_fixed_integer_part (right);
+	fx2 = _cairo_fixed_fractional_part (right);
+
+	dy = y2 - y1;
+    } else {
+	ix1 = _cairo_fixed_integer_part (right);
+	fx1 = _cairo_fixed_fractional_part (right);
+
+	ix2 = _cairo_fixed_integer_part (left);
+	fx2 = _cairo_fixed_fractional_part (left);
+
+	dx = -dx;
+	sign = -sign;
+	dy = y1 - y2;
+	y1 = y2 - dy;
+	y2 = y1 + dy;
+    }
+
+    /* Add coverage for all pixels [ix1,ix2] on this row crossed
+     * by the edge. */
+    {
+	struct quorem y = floored_divrem ((STEP_X - fx1)*dy, dx);
+	struct cell *cell;
+
+	cell = sweep_line->coverage.cursor;
+	if (cell->x != ix1) {
+	    if (unlikely (cell->x > ix1)) {
+		do {
+		    if (cell->prev->x < ix1)
+			break;
+		    cell = cell->prev;
+		} while (TRUE);
+	    } else do {
+		UNROLL3({
+			if (cell->x >= ix1)
+			    break;
+			cell = cell->next;
+			});
+	    } while (TRUE);
+
+	    if (cell->x != ix1)
+		cell = coverage_alloc (sweep_line, cell, ix1);
+	}
+
+	cell->uncovered_area += sign * y.quo * (STEP_X + fx1);
+	cell->covered_height += sign * y.quo;
+	y.quo += y1;
+
+	cell = cell->next;
+	if (cell->x != ++ix1)
+	    cell = coverage_alloc (sweep_line, cell, ix1);
+	if (ix1 < ix2) {
+	    struct quorem dydx_full = floored_divrem (STEP_X*dy, dx);
+
+	    do {
+		cairo_fixed_t y_skip = dydx_full.quo;
+		y.rem += dydx_full.rem;
+		if (y.rem >= dx) {
+		    ++y_skip;
+		    y.rem -= dx;
+		}
+
+		y.quo += y_skip;
+
+		y_skip *= sign;
+		cell->covered_height += y_skip;
+		cell->uncovered_area += y_skip*STEP_X;
+
+		cell = cell->next;
+		if (cell->x != ++ix1)
+		    cell = coverage_alloc (sweep_line, cell, ix1);
+	    } while (ix1 != ix2);
+	}
+	cell->uncovered_area += sign*(y2 - y.quo)*fx2;
+	cell->covered_height += sign*(y2 - y.quo);
+	sweep_line->coverage.cursor = cell;
+    }
+}
+
+inline static void
+full_inc_edge (edge_t *edge)
+{
+    edge->x.quo += edge->dxdy_full.quo;
+    edge->x.rem += edge->dxdy_full.rem;
+    if (edge->x.rem >= 0) {
+	++edge->x.quo;
+	edge->x.rem -= edge->dy;
+    }
+}
+
+static void
+full_add_edge (sweep_line_t *sweep_line, edge_t *edge, int sign)
+{
+    struct cell *cell;
+    cairo_fixed_t x1, x2;
+    int ix1, ix2;
+    int frac;
+
+    edge->current_sign = sign;
+
+    ix1 = _cairo_fixed_integer_part (edge->x.quo);
+
+    if (edge->vertical) {
+	frac = _cairo_fixed_fractional_part (edge->x.quo);
+	cell = coverage_find (sweep_line, ix1);
+	cell->covered_height += sign * STEP_Y;
+	cell->uncovered_area += sign * 2 * frac * STEP_Y;
+	return;
+    }
+
+    x1 = edge->x.quo;
+    full_inc_edge (edge);
+    x2 = edge->x.quo;
+
+    ix2 = _cairo_fixed_integer_part (edge->x.quo);
+
+    /* Edge is entirely within a column? */
+    if (likely (ix1 == ix2)) {
+	frac = _cairo_fixed_fractional_part (x1) +
+	       _cairo_fixed_fractional_part (x2);
+	cell = coverage_find (sweep_line, ix1);
+	cell->covered_height += sign * STEP_Y;
+	cell->uncovered_area += sign * frac * STEP_Y;
+	return;
+    }
+
+    coverage_render_cells (sweep_line, x1, x2, 0, STEP_Y, sign);
+}
+
+static void
+full_nonzero (sweep_line_t *sweep_line)
+{
+    cairo_list_t *pos;
+
+    sweep_line->is_vertical = TRUE;
+    pos = sweep_line->active.next;
+    do {
+	edge_t *left = link_to_edge (pos), *right;
+	int winding = left->edge.dir;
+
+	sweep_line->is_vertical &= left->vertical;
+
+	pos = left->link.next;
+	do {
+	    if (unlikely (pos == &sweep_line->active)) {
+		full_add_edge (sweep_line, left, +1);
+		return;
+	    }
+
+	    right = link_to_edge (pos);
+	    pos = pos->next;
+	    sweep_line->is_vertical &= right->vertical;
+
+	    winding += right->edge.dir;
+	    if (0 == winding) {
+		if (pos == &sweep_line->active ||
+		    link_to_edge (pos)->x.quo != right->x.quo)
+		{
+		    break;
+		}
+	    }
+
+	    if (! right->vertical)
+		full_inc_edge (right);
+	} while (TRUE);
+
+	full_add_edge (sweep_line, left,  +1);
+	full_add_edge (sweep_line, right, -1);
+    } while (pos != &sweep_line->active);
+}
+
+static void
+full_evenodd (sweep_line_t *sweep_line)
+{
+    cairo_list_t *pos;
+
+    sweep_line->is_vertical = TRUE;
+    pos = sweep_line->active.next;
+    do {
+	edge_t *left = link_to_edge (pos), *right;
+	int winding = 0;
+
+	sweep_line->is_vertical &= left->vertical;
+
+	pos = left->link.next;
+	do {
+	    if (pos == &sweep_line->active) {
+		full_add_edge (sweep_line, left, +1);
+		return;
+	    }
+
+	    right = link_to_edge (pos);
+	    pos = pos->next;
+	    sweep_line->is_vertical &= right->vertical;
+
+	    if (++winding & 1) {
+		if (pos == &sweep_line->active ||
+		    link_to_edge (pos)->x.quo != right->x.quo)
+		{
+		    break;
+		}
+	    }
+
+	    if (! right->vertical)
+		full_inc_edge (right);
+	} while (TRUE);
+
+	full_add_edge (sweep_line, left,  +1);
+	full_add_edge (sweep_line, right, -1);
+    } while (pos != &sweep_line->active);
+}
+
+static void
+render_rows (cairo_botor_scan_converter_t *self,
+	     sweep_line_t *sweep_line,
+	     int y, int height,
+	     cairo_span_renderer_t *renderer)
+{
+    cairo_half_open_span_t spans_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_half_open_span_t)];
+    cairo_half_open_span_t *spans = spans_stack;
+    struct cell *cell;
+    int prev_x, cover;
+    int num_spans;
+    cairo_status_t status;
+
+    if (unlikely (sweep_line->coverage.count == 0)) {
+	status = renderer->render_rows (renderer, y, height, NULL, 0);
+	if (unlikely (status))
+	    longjmp (sweep_line->unwind, status);
+	return;
+    }
+
+    /* Allocate enough spans for the row. */
+
+    num_spans = 2*sweep_line->coverage.count+2;
+    if (unlikely (num_spans > ARRAY_LENGTH (spans_stack))) {
+	spans = _cairo_malloc_ab (num_spans, sizeof (cairo_half_open_span_t));
+	if (unlikely (spans == NULL)) {
+	    longjmp (sweep_line->unwind,
+		     _cairo_error (CAIRO_STATUS_NO_MEMORY));
+	}
+    }
+
+    /* Form the spans from the coverage and areas. */
+    num_spans = 0;
+    prev_x = self->xmin;
+    cover = 0;
+    cell = sweep_line->coverage.head.next;
+    do {
+	int x = cell->x;
+	int area;
+
+	if (x > prev_x) {
+	    spans[num_spans].x = prev_x;
+	    spans[num_spans].coverage = AREA_TO_ALPHA (cover);
+	    ++num_spans;
+	}
+
+	cover += cell->covered_height*STEP_X*2;
+	area = cover - cell->uncovered_area;
+
+	spans[num_spans].x = x;
+	spans[num_spans].coverage = AREA_TO_ALPHA (area);
+	++num_spans;
+
+	prev_x = x + 1;
+    } while ((cell = cell->next) != &sweep_line->coverage.tail);
+
+    if (prev_x <= self->xmax) {
+	spans[num_spans].x = prev_x;
+	spans[num_spans].coverage = AREA_TO_ALPHA (cover);
+	++num_spans;
+    }
+
+    if (cover && prev_x < self->xmax) {
+	spans[num_spans].x = self->xmax;
+	spans[num_spans].coverage = 0;
+	++num_spans;
+    }
+
+    status = renderer->render_rows (renderer, y, height, spans, num_spans);
+
+    if (unlikely (spans != spans_stack))
+	free (spans);
+
+    coverage_reset (&sweep_line->coverage);
+
+    if (unlikely (status))
+	longjmp (sweep_line->unwind, status);
+}
+
+static void
+full_repeat (sweep_line_t *sweep)
+{
+    edge_t *edge;
+
+    cairo_list_foreach_entry (edge, edge_t, &sweep->active, link) {
+	if (edge->current_sign)
+	    full_add_edge (sweep, edge, edge->current_sign);
+	else if (! edge->vertical)
+	    full_inc_edge (edge);
+    }
+}
+
+static void
+full_reset (sweep_line_t *sweep)
+{
+    edge_t *edge;
+
+    cairo_list_foreach_entry (edge, edge_t, &sweep->active, link)
+	edge->current_sign = 0;
+}
+
+static void
+full_step (cairo_botor_scan_converter_t *self,
+	   sweep_line_t *sweep_line,
+	   cairo_fixed_t row,
+	   cairo_span_renderer_t *renderer)
+{
+    int top, bottom;
+
+    top = _cairo_fixed_integer_part (sweep_line->current_row);
+    bottom = _cairo_fixed_integer_part (row);
+    if (cairo_list_is_empty (&sweep_line->active)) {
+	cairo_status_t  status;
+
+	status = renderer->render_rows (renderer, top, bottom - top, NULL, 0);
+	if (unlikely (status))
+	    longjmp (sweep_line->unwind, status);
+
+	return;
+    }
+
+    if (self->fill_rule == CAIRO_FILL_RULE_WINDING)
+	full_nonzero (sweep_line);
+    else
+	full_evenodd (sweep_line);
+
+    if (sweep_line->is_vertical || bottom == top + 1) {
+	render_rows (self, sweep_line, top, bottom - top, renderer);
+	full_reset (sweep_line);
+	return;
+    }
+
+    render_rows (self, sweep_line, top++, 1, renderer);
+    do {
+	full_repeat (sweep_line);
+	render_rows (self, sweep_line, top, 1, renderer);
+    } while (++top != bottom);
+
+    full_reset (sweep_line);
+}
+
+cairo_always_inline static void
+sub_inc_edge (edge_t *edge,
+	      cairo_fixed_t height)
+{
+    if (height == 1) {
+	edge->x.quo += edge->dxdy.quo;
+	edge->x.rem += edge->dxdy.rem;
+	if (edge->x.rem >= 0) {
+	    ++edge->x.quo;
+	    edge->x.rem -= edge->dy;
+	}
+    } else {
+	edge->x.quo += height * edge->dxdy.quo;
+	edge->x.rem += height * edge->dxdy.rem;
+	if (edge->x.rem >= 0) {
+	    int carry = edge->x.rem / edge->dy + 1;
+	    edge->x.quo += carry;
+	    edge->x.rem -= carry * edge->dy;
+	}
+    }
+}
+
+static void
+sub_add_run (sweep_line_t *sweep_line, edge_t *edge, int y, int sign)
+{
+    struct run *run;
+
+    run = _cairo_freepool_alloc (&sweep_line->runs);
+    if (unlikely (run == NULL))
+	longjmp (sweep_line->unwind, _cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    run->y = y;
+    run->sign = sign;
+    run->next = edge->runs;
+    edge->runs = run;
+
+    edge->current_sign = sign;
+}
+
+inline static cairo_bool_t
+edges_coincident (edge_t *left, edge_t *right, cairo_fixed_t y)
+{
+    /* XXX is compare_x_for_y() worth executing during sub steps? */
+    return line_equal (&left->edge.line, &right->edge.line);
+    //edges_compare_x_for_y (&left->edge, &right->edge, y) >= 0;
+}
+
+static void
+sub_nonzero (sweep_line_t *sweep_line)
+{
+    cairo_fixed_t y = sweep_line->current_subrow;
+    cairo_fixed_t fy = _cairo_fixed_fractional_part (y);
+    cairo_list_t *pos;
+
+    pos = sweep_line->active.next;
+    do {
+	edge_t *left = link_to_edge (pos), *right;
+	int winding = left->edge.dir;
+
+	pos = left->link.next;
+	do {
+	    if (unlikely (pos == &sweep_line->active)) {
+		if (left->current_sign != +1)
+		    sub_add_run (sweep_line, left, fy, +1);
+		return;
+	    }
+
+	    right = link_to_edge (pos);
+	    pos = pos->next;
+
+	    winding += right->edge.dir;
+	    if (0 == winding) {
+		if (pos == &sweep_line->active ||
+		    ! edges_coincident (right, link_to_edge (pos), y))
+		{
+		    break;
+		}
+	    }
+
+	    if (right->current_sign)
+		sub_add_run (sweep_line, right, fy, 0);
+	} while (TRUE);
+
+	if (left->current_sign != +1)
+	    sub_add_run (sweep_line, left, fy, +1);
+	if (right->current_sign != -1)
+	    sub_add_run (sweep_line, right, fy, -1);
+    } while (pos != &sweep_line->active);
+}
+
+static void
+sub_evenodd (sweep_line_t *sweep_line)
+{
+    cairo_fixed_t y = sweep_line->current_subrow;
+    cairo_fixed_t fy = _cairo_fixed_fractional_part (y);
+    cairo_list_t *pos;
+
+    pos = sweep_line->active.next;
+    do {
+	edge_t *left = link_to_edge (pos), *right;
+	int winding = 0;
+
+	pos = left->link.next;
+	do {
+	    if (unlikely (pos == &sweep_line->active)) {
+		if (left->current_sign != +1)
+		    sub_add_run (sweep_line, left, fy, +1);
+		return;
+	    }
+
+	    right = link_to_edge (pos);
+	    pos = pos->next;
+
+	    if (++winding & 1) {
+		if (pos == &sweep_line->active ||
+		    ! edges_coincident (right, link_to_edge (pos), y))
+		{
+		    break;
+		}
+	    }
+
+	    if (right->current_sign)
+		sub_add_run (sweep_line, right, fy, 0);
+	} while (TRUE);
+
+	if (left->current_sign != +1)
+	    sub_add_run (sweep_line, left, fy, +1);
+	if (right->current_sign != -1)
+	    sub_add_run (sweep_line, right, fy, -1);
+    } while (pos != &sweep_line->active);
+}
+
+cairo_always_inline static void
+sub_step (cairo_botor_scan_converter_t *self,
+	  sweep_line_t *sweep_line)
+{
+    if (cairo_list_is_empty (&sweep_line->active))
+	return;
+
+    if (self->fill_rule == CAIRO_FILL_RULE_WINDING)
+	sub_nonzero (sweep_line);
+    else
+	sub_evenodd (sweep_line);
+}
+
+static void
+coverage_render_runs (sweep_line_t *sweep, edge_t *edge,
+		      cairo_fixed_t y1, cairo_fixed_t y2)
+{
+    struct run tail;
+    struct run *run = &tail;
+
+    tail.next = NULL;
+    tail.y = y2;
+
+    /* Order the runs top->bottom */
+    while (edge->runs) {
+	struct run *r;
+
+	r = edge->runs;
+	edge->runs = r->next;
+	r->next = run;
+	run = r;
+    }
+
+    if (run->y > y1)
+	sub_inc_edge (edge, run->y - y1);
+
+    do {
+	cairo_fixed_t x1, x2;
+
+	y1 = run->y;
+	y2 = run->next->y;
+
+	x1 = edge->x.quo;
+	if (y2 - y1 == STEP_Y)
+	    full_inc_edge (edge);
+	else
+	    sub_inc_edge (edge, y2 - y1);
+	x2 = edge->x.quo;
+
+	if (run->sign) {
+	    int ix1, ix2;
+
+	    ix1 = _cairo_fixed_integer_part (x1);
+	    ix2 = _cairo_fixed_integer_part (x2);
+
+	    /* Edge is entirely within a column? */
+	    if (likely (ix1 == ix2)) {
+		struct cell *cell;
+		int frac;
+
+		frac = _cairo_fixed_fractional_part (x1) +
+		       _cairo_fixed_fractional_part (x2);
+		cell = coverage_find (sweep, ix1);
+		cell->covered_height += run->sign * (y2 - y1);
+		cell->uncovered_area += run->sign * (y2 - y1) * frac;
+	    } else {
+		coverage_render_cells (sweep, x1, x2, y1, y2, run->sign);
+	    }
+	}
+
+	run = run->next;
+    } while (run->next != NULL);
+}
+
+static void
+coverage_render_vertical_runs (sweep_line_t *sweep, edge_t *edge, cairo_fixed_t y2)
+{
+    struct cell *cell;
+    struct run *run;
+    int height = 0;
+
+    for (run = edge->runs; run != NULL; run = run->next) {
+	if (run->sign)
+	    height += run->sign * (y2 - run->y);
+	y2 = run->y;
+    }
+
+    cell = coverage_find (sweep, _cairo_fixed_integer_part (edge->x.quo));
+    cell->covered_height += height;
+    cell->uncovered_area += 2 * _cairo_fixed_fractional_part (edge->x.quo) * height;
+}
+
+cairo_always_inline static void
+sub_emit (cairo_botor_scan_converter_t *self,
+	  sweep_line_t *sweep,
+	  cairo_span_renderer_t *renderer)
+{
+    edge_t *edge;
+
+    sub_step (self, sweep);
+
+    /* convert the runs into coverages */
+
+    cairo_list_foreach_entry (edge, edge_t, &sweep->active, link) {
+	if (edge->runs == NULL) {
+	    if (! edge->vertical) {
+		if (edge->flags & START) {
+		    sub_inc_edge (edge,
+				  STEP_Y - _cairo_fixed_fractional_part (edge->edge.top));
+		    edge->flags &= ~START;
+		} else
+		    full_inc_edge (edge);
+	    }
+	} else {
+	    if (edge->vertical) {
+		coverage_render_vertical_runs (sweep, edge, STEP_Y);
+	    } else {
+		int y1 = 0;
+		if (edge->flags & START) {
+		    y1 = _cairo_fixed_fractional_part (edge->edge.top);
+		    edge->flags &= ~START;
+		}
+		coverage_render_runs (sweep, edge, y1, STEP_Y);
+	    }
+	}
+	edge->current_sign = 0;
+	edge->runs = NULL;
+    }
+
+    cairo_list_foreach_entry (edge, edge_t, &sweep->stopped, link) {
+	int y2 = _cairo_fixed_fractional_part (edge->edge.bottom);
+	if (edge->vertical) {
+	    coverage_render_vertical_runs (sweep, edge, y2);
+	} else {
+	    int y1 = 0;
+	    if (edge->flags & START)
+		y1 = _cairo_fixed_fractional_part (edge->edge.top);
+	    coverage_render_runs (sweep, edge, y1, y2);
+	}
+    }
+    cairo_list_init (&sweep->stopped);
+
+    _cairo_freepool_reset (&sweep->runs);
+
+    render_rows (self, sweep,
+		 _cairo_fixed_integer_part (sweep->current_row), 1,
+		 renderer);
+}
+
+static void
+sweep_line_init (sweep_line_t	 *sweep_line,
+		 event_t	**start_events,
+		 int		  num_events)
+{
+    cairo_list_init (&sweep_line->active);
+    cairo_list_init (&sweep_line->stopped);
+    sweep_line->insert_cursor = &sweep_line->active;
+
+    sweep_line->current_row = INT32_MIN;
+    sweep_line->current_subrow = INT32_MIN;
+
+    coverage_init (&sweep_line->coverage);
+    _cairo_freepool_init (&sweep_line->runs, sizeof (struct run));
+
+    start_event_sort (start_events, num_events);
+    start_events[num_events] = NULL;
+
+    sweep_line->queue.start_events = start_events;
+
+    _cairo_freepool_init (&sweep_line->queue.pool,
+			  sizeof (queue_event_t));
+    pqueue_init (&sweep_line->queue.pq);
+    sweep_line->queue.pq.elements[PQ_FIRST_ENTRY] = NULL;
+}
+
+static void
+sweep_line_delete (sweep_line_t	*sweep_line,
+		   edge_t	*edge)
+{
+    if (sweep_line->insert_cursor == &edge->link)
+	sweep_line->insert_cursor = edge->link.prev;
+
+    cairo_list_del (&edge->link);
+    if (edge->runs)
+	cairo_list_add_tail (&edge->link, &sweep_line->stopped);
+    edge->flags |= STOP;
+}
+
+static void
+sweep_line_swap (sweep_line_t	*sweep_line,
+		 edge_t	*left,
+		 edge_t	*right)
+{
+    right->link.prev = left->link.prev;
+    left->link.next = right->link.next;
+    right->link.next = &left->link;
+    left->link.prev = &right->link;
+    left->link.next->prev = &left->link;
+    right->link.prev->next = &right->link;
+}
+
+static void
+sweep_line_fini (sweep_line_t *sweep_line)
+{
+    pqueue_fini (&sweep_line->queue.pq);
+    _cairo_freepool_fini (&sweep_line->queue.pool);
+    coverage_fini (&sweep_line->coverage);
+    _cairo_freepool_fini (&sweep_line->runs);
+}
+
+static cairo_status_t
+botor_generate (cairo_botor_scan_converter_t	 *self,
+		event_t				**start_events,
+		cairo_span_renderer_t		 *renderer)
+{
+    cairo_status_t status;
+    sweep_line_t sweep_line;
+    cairo_fixed_t ybot;
+    event_t *event;
+    cairo_list_t *left, *right;
+    edge_t *e1, *e2;
+    int bottom;
+
+    sweep_line_init (&sweep_line, start_events, self->num_edges);
+    if ((status = setjmp (sweep_line.unwind)))
+	goto unwind;
+
+    ybot = self->extents.p2.y;
+    sweep_line.current_subrow = self->extents.p1.y;
+    sweep_line.current_row = _cairo_fixed_floor (self->extents.p1.y);
+    event = *sweep_line.queue.start_events++;
+    do {
+	/* Can we process a full step in one go? */
+	if (event->y >= sweep_line.current_row + STEP_Y) {
+	    bottom = _cairo_fixed_floor (event->y);
+	    full_step (self, &sweep_line, bottom, renderer);
+	    sweep_line.current_row = bottom;
+	    sweep_line.current_subrow = bottom;
+	}
+
+	do {
+	    if (event->y > sweep_line.current_subrow) {
+		sub_step (self, &sweep_line);
+		sweep_line.current_subrow = event->y;
+	    }
+
+	    do {
+		/* Update the active list using Bentley-Ottmann */
+		switch (event->type) {
+		case EVENT_TYPE_START:
+		    e1 = ((start_event_t *) event)->edge;
+
+		    sweep_line_insert (&sweep_line, e1);
+		    event_insert_stop (&sweep_line, e1);
+
+		    left = e1->link.prev;
+		    right = e1->link.next;
+
+		    if (left != &sweep_line.active) {
+			event_insert_if_intersect_below_current_y (&sweep_line,
+								   link_to_edge (left), e1);
+		    }
+
+		    if (right != &sweep_line.active) {
+			event_insert_if_intersect_below_current_y (&sweep_line,
+								   e1, link_to_edge (right));
+		    }
+
+		    break;
+
+		case EVENT_TYPE_STOP:
+		    e1 = ((queue_event_t *) event)->e1;
+		    event_delete (&sweep_line, event);
+
+		    left = e1->link.prev;
+		    right = e1->link.next;
+
+		    sweep_line_delete (&sweep_line, e1);
+
+		    if (left != &sweep_line.active &&
+			right != &sweep_line.active)
+		    {
+			 event_insert_if_intersect_below_current_y (&sweep_line,
+								    link_to_edge (left),
+								    link_to_edge (right));
+		    }
+
+		    break;
+
+		case EVENT_TYPE_INTERSECTION:
+		    e1 = ((queue_event_t *) event)->e1;
+		    e2 = ((queue_event_t *) event)->e2;
+
+		    event_delete (&sweep_line, event);
+		    if (e1->flags & STOP)
+			break;
+		    if (e2->flags & STOP)
+			break;
+
+		    /* skip this intersection if its edges are not adjacent */
+		    if (&e2->link != e1->link.next)
+			break;
+
+		    left = e1->link.prev;
+		    right = e2->link.next;
+
+		    sweep_line_swap (&sweep_line, e1, e2);
+
+		    /* after the swap e2 is left of e1 */
+		    if (left != &sweep_line.active) {
+			event_insert_if_intersect_below_current_y (&sweep_line,
+								   link_to_edge (left), e2);
+		    }
+
+		    if (right != &sweep_line.active) {
+			event_insert_if_intersect_below_current_y (&sweep_line,
+								   e1, link_to_edge (right));
+		    }
+
+		    break;
+		}
+
+		event = event_next (&sweep_line);
+		if (event == NULL)
+		    goto end;
+	    } while (event->y == sweep_line.current_subrow);
+	} while (event->y < sweep_line.current_row + STEP_Y);
+
+	bottom = sweep_line.current_row + STEP_Y;
+	sub_emit (self, &sweep_line, renderer);
+	sweep_line.current_subrow = bottom;
+	sweep_line.current_row = sweep_line.current_subrow;
+    } while (TRUE);
+
+  end:
+    /* flush any partial spans */
+    if (sweep_line.current_subrow != sweep_line.current_row) {
+	sub_emit (self, &sweep_line, renderer);
+	sweep_line.current_row += STEP_Y;
+	sweep_line.current_subrow = sweep_line.current_row;
+    }
+    /* clear the rest */
+    if (sweep_line.current_subrow < ybot) {
+	bottom = _cairo_fixed_integer_part (sweep_line.current_row);
+	status = renderer->render_rows (renderer,
+					bottom, _cairo_fixed_integer_ceil (ybot) - bottom,
+					NULL, 0);
+    }
+
+ unwind:
+    sweep_line_fini (&sweep_line);
+
+    return status;
+}
+
+static cairo_status_t
+_cairo_botor_scan_converter_generate (void			*converter,
+				      cairo_span_renderer_t	*renderer)
+{
+    cairo_botor_scan_converter_t *self = converter;
+    start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (start_event_t)];
+    start_event_t *events;
+    event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
+    event_t **event_ptrs;
+    struct _cairo_botor_scan_converter_chunk *chunk;
+    cairo_status_t status;
+    int num_events;
+    int i, j;
+
+    num_events = self->num_edges;
+    if (unlikely (0 == num_events)) {
+	return renderer->render_rows (renderer,
+				      _cairo_fixed_integer_floor (self->extents.p1.y),
+				      _cairo_fixed_integer_ceil (self->extents.p2.y) -
+				      _cairo_fixed_integer_floor (self->extents.p1.y),
+				      NULL, 0);
+    }
+
+    events = stack_events;
+    event_ptrs = stack_event_ptrs;
+    if (unlikely (num_events >= ARRAY_LENGTH (stack_events))) {
+	events = _cairo_malloc_ab_plus_c (num_events,
+					  sizeof (start_event_t) + sizeof (event_t *),
+					  sizeof (event_t *));
+	if (unlikely (events == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	event_ptrs = (event_t **) (events + num_events);
+    }
+
+    j = 0;
+    for (chunk = &self->chunks; chunk != NULL; chunk = chunk->next) {
+	edge_t *edge;
+
+	edge = chunk->base;
+	for (i = 0; i < chunk->count; i++) {
+	    event_ptrs[j] = (event_t *) &events[j];
+
+	    events[j].y = edge->edge.top;
+	    events[j].type = EVENT_TYPE_START;
+	    events[j].edge = edge;
+
+	    edge++, j++;
+	}
+    }
+
+    status = botor_generate (self, event_ptrs, renderer);
+
+    if (events != stack_events)
+	free (events);
+
+    return status;
+}
+
+static edge_t *
+botor_allocate_edge (cairo_botor_scan_converter_t *self)
+{
+    struct _cairo_botor_scan_converter_chunk *chunk;
+
+    chunk = self->tail;
+    if (chunk->count == chunk->size) {
+	int size;
+
+	size = chunk->size * 2;
+	chunk->next = _cairo_malloc_ab_plus_c (size,
+					       sizeof (edge_t),
+					       sizeof (struct _cairo_botor_scan_converter_chunk));
+	if (unlikely (chunk->next == NULL))
+	    return NULL;
+
+	chunk = chunk->next;
+	chunk->next = NULL;
+	chunk->count = 0;
+	chunk->size = size;
+	chunk->base = chunk + 1;
+	self->tail = chunk;
+    }
+
+    return (edge_t *) chunk->base + chunk->count++;
+}
+
+static cairo_status_t
+botor_add_edge (cairo_botor_scan_converter_t *self,
+		const cairo_edge_t *edge)
+{
+    edge_t *e;
+    cairo_fixed_t dx, dy;
+
+    e = botor_allocate_edge (self);
+    if (unlikely (e == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    cairo_list_init (&e->link);
+    e->edge = *edge;
+
+    dx = edge->line.p2.x - edge->line.p1.x;
+    dy = edge->line.p2.y - edge->line.p1.y;
+    e->dy = dy;
+
+    if (dx == 0) {
+	e->vertical = TRUE;
+	e->x.quo = edge->line.p1.x;
+	e->x.rem = 0;
+	e->dxdy.quo = 0;
+	e->dxdy.rem = 0;
+	e->dxdy_full.quo = 0;
+	e->dxdy_full.rem = 0;
+    } else {
+	e->vertical = FALSE;
+	e->dxdy = floored_divrem (dx, dy);
+	if (edge->top == edge->line.p1.y) {
+	    e->x.quo = edge->line.p1.x;
+	    e->x.rem = 0;
+	} else {
+	    e->x = floored_muldivrem (edge->top - edge->line.p1.y,
+				      dx, dy);
+	    e->x.quo += edge->line.p1.x;
+	}
+
+	if (_cairo_fixed_integer_part (edge->bottom) - _cairo_fixed_integer_part (edge->top) > 1) {
+	    e->dxdy_full = floored_muldivrem (STEP_Y, dx, dy);
+	} else {
+	    e->dxdy_full.quo = 0;
+	    e->dxdy_full.rem = 0;
+	}
+    }
+
+    e->x.rem = -e->dy;
+    e->current_sign = 0;
+    e->runs = NULL;
+    e->flags = START;
+
+    self->num_edges++;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_botor_scan_converter_add_edge (void		*converter,
+				      const cairo_point_t *p1,
+				      const cairo_point_t *p2,
+				      int top, int bottom,
+				      int dir)
+{
+    cairo_botor_scan_converter_t *self = converter;
+    cairo_edge_t edge;
+
+    edge.line.p1 = *p1;
+    edge.line.p2 = *p2;
+    edge.top = top;
+    edge.bottom = bottom;
+    edge.dir = dir;
+
+    return botor_add_edge (self, &edge);
+}
+
+static cairo_status_t
+_cairo_botor_scan_converter_add_polygon (void		*converter,
+					 const cairo_polygon_t *polygon)
+{
+    cairo_botor_scan_converter_t *self = converter;
+    cairo_status_t status;
+    int i;
+
+    for (i = 0; i < polygon->num_edges; i++) {
+	status = botor_add_edge (self, &polygon->edges[i]);
+	if (unlikely (status))
+	    return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_botor_scan_converter_destroy (void *converter)
+{
+    cairo_botor_scan_converter_t *self = converter;
+    struct _cairo_botor_scan_converter_chunk *chunk, *next;
+
+    for (chunk = self->chunks.next; chunk != NULL; chunk = next) {
+	next = chunk->next;
+	free (chunk);
+    }
+}
+
+void
+_cairo_botor_scan_converter_init (cairo_botor_scan_converter_t *self,
+				  const cairo_box_t *extents,
+				  cairo_fill_rule_t fill_rule)
+{
+    self->base.destroy     = _cairo_botor_scan_converter_destroy;
+    self->base.add_edge    = _cairo_botor_scan_converter_add_edge;
+    self->base.add_polygon = _cairo_botor_scan_converter_add_polygon;
+    self->base.generate    = _cairo_botor_scan_converter_generate;
+
+    self->extents   = *extents;
+    self->fill_rule = fill_rule;
+
+    self->xmin = _cairo_fixed_integer_floor (extents->p1.x);
+    self->xmax = _cairo_fixed_integer_ceil (extents->p2.x);
+
+    self->chunks.base = self->buf;
+    self->chunks.next = NULL;
+    self->chunks.count = 0;
+    self->chunks.size = sizeof (self->buf) / sizeof (edge_t);
+    self->tail = &self->chunks;
+
+    self->num_edges = 0;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-boxes-private.h
@@ -0,0 +1,84 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#ifndef CAIRO_BOXES_H
+#define CAIRO_BOXES_H
+
+#include "cairo-types-private.h"
+#include "cairo-compiler-private.h"
+
+struct _cairo_boxes_t {
+    cairo_status_t status;
+    cairo_box_t limit;
+    const cairo_box_t *limits;
+    int num_limits;
+    int num_boxes;
+    unsigned int is_pixel_aligned : 1;
+
+    struct _cairo_boxes_chunk {
+	struct _cairo_boxes_chunk *next;
+	cairo_box_t *base;
+	int count;
+	int size;
+    } chunks, *tail;
+    cairo_box_t boxes_embedded[32];
+};
+
+cairo_private void
+_cairo_boxes_init (cairo_boxes_t *boxes);
+
+cairo_private void
+_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
+			     cairo_box_t *array,
+			     int num_boxes);
+
+cairo_private void
+_cairo_boxes_limit (cairo_boxes_t	*boxes,
+		    const cairo_box_t	*limits,
+		    int			 num_limits);
+
+cairo_private cairo_status_t
+_cairo_boxes_add (cairo_boxes_t *boxes,
+		  const cairo_box_t *box);
+
+cairo_private void
+_cairo_boxes_extents (const cairo_boxes_t *boxes,
+		      cairo_rectangle_int_t *extents);
+
+cairo_private void
+_cairo_boxes_clear (cairo_boxes_t *boxes);
+
+cairo_private void
+_cairo_boxes_fini (cairo_boxes_t *boxes);
+
+#endif /* CAIRO_BOXES_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-boxes.c
@@ -0,0 +1,300 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-boxes-private.h"
+#include "cairo-error-private.h"
+
+void
+_cairo_boxes_init (cairo_boxes_t *boxes)
+{
+    boxes->status = CAIRO_STATUS_SUCCESS;
+    boxes->num_limits = 0;
+    boxes->num_boxes = 0;
+
+    boxes->tail = &boxes->chunks;
+    boxes->chunks.next = NULL;
+    boxes->chunks.base = boxes->boxes_embedded;
+    boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
+    boxes->chunks.count = 0;
+
+    boxes->is_pixel_aligned = TRUE;
+}
+
+void
+_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
+			     cairo_box_t *array,
+			     int num_boxes)
+{
+    int n;
+
+    boxes->status = CAIRO_STATUS_SUCCESS;
+    boxes->num_limits = 0;
+    boxes->num_boxes = num_boxes;
+
+    boxes->tail = &boxes->chunks;
+    boxes->chunks.next = NULL;
+    boxes->chunks.base = array;
+    boxes->chunks.size = num_boxes;
+    boxes->chunks.count = num_boxes;
+
+    for (n = 0; n < num_boxes; n++) {
+	if (! _cairo_fixed_is_integer (array[n].p1.x) ||
+	    ! _cairo_fixed_is_integer (array[n].p1.y) ||
+	    ! _cairo_fixed_is_integer (array[n].p2.x) ||
+	    ! _cairo_fixed_is_integer (array[n].p2.y))
+	{
+	    break;
+	}
+    }
+
+    boxes->is_pixel_aligned = n == num_boxes;
+}
+
+void
+_cairo_boxes_limit (cairo_boxes_t	*boxes,
+		    const cairo_box_t	*limits,
+		    int			 num_limits)
+{
+    int n;
+
+    boxes->limits = limits;
+    boxes->num_limits = num_limits;
+
+    if (boxes->num_limits) {
+	boxes->limit = limits[0];
+	for (n = 1; n < num_limits; n++) {
+	    if (limits[n].p1.x < boxes->limit.p1.x)
+		boxes->limit.p1.x = limits[n].p1.x;
+
+	    if (limits[n].p1.y < boxes->limit.p1.y)
+		boxes->limit.p1.y = limits[n].p1.y;
+
+	    if (limits[n].p2.x > boxes->limit.p2.x)
+		boxes->limit.p2.x = limits[n].p2.x;
+
+	    if (limits[n].p2.y > boxes->limit.p2.y)
+		boxes->limit.p2.y = limits[n].p2.y;
+	}
+    }
+}
+
+static void
+_cairo_boxes_add_internal (cairo_boxes_t *boxes,
+			   const cairo_box_t *box)
+{
+    struct _cairo_boxes_chunk *chunk;
+
+    if (unlikely (boxes->status))
+	return;
+
+    chunk = boxes->tail;
+    if (unlikely (chunk->count == chunk->size)) {
+	int size;
+
+	size = chunk->size * 2;
+	chunk->next = _cairo_malloc_ab_plus_c (size,
+					       sizeof (cairo_box_t),
+					       sizeof (struct _cairo_boxes_chunk));
+
+	if (unlikely (chunk->next == NULL)) {
+	    boxes->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return;
+	}
+
+	chunk = chunk->next;
+	boxes->tail = chunk;
+
+	chunk->next = NULL;
+	chunk->count = 0;
+	chunk->size = size;
+	chunk->base = (cairo_box_t *) (chunk + 1);
+    }
+
+    chunk->base[chunk->count++] = *box;
+    boxes->num_boxes++;
+
+    if (boxes->is_pixel_aligned) {
+	boxes->is_pixel_aligned =
+	    _cairo_fixed_is_integer (box->p1.x) &&
+	    _cairo_fixed_is_integer (box->p1.y) &&
+	    _cairo_fixed_is_integer (box->p2.x) &&
+	    _cairo_fixed_is_integer (box->p2.y);
+    }
+}
+
+cairo_status_t
+_cairo_boxes_add (cairo_boxes_t *boxes,
+		  const cairo_box_t *box)
+{
+    if (box->p1.y == box->p2.y)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (box->p1.x == box->p2.x)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (boxes->num_limits) {
+	cairo_point_t p1, p2;
+	cairo_bool_t reversed = FALSE;
+	int n;
+
+	/* support counter-clockwise winding for rectangular tessellation */
+	if (box->p1.x < box->p2.x) {
+	    p1.x = box->p1.x;
+	    p2.x = box->p2.x;
+	} else {
+	    p2.x = box->p1.x;
+	    p1.x = box->p2.x;
+	    reversed = ! reversed;
+	}
+
+	if (p1.x >= boxes->limit.p2.x || p2.x <= boxes->limit.p1.x)
+	    return CAIRO_STATUS_SUCCESS;
+
+	if (box->p1.y < box->p2.y) {
+	    p1.y = box->p1.y;
+	    p2.y = box->p2.y;
+	} else {
+	    p2.y = box->p1.y;
+	    p1.y = box->p2.y;
+	    reversed = ! reversed;
+	}
+
+	if (p1.y >= boxes->limit.p2.y || p2.y <= boxes->limit.p1.y)
+	    return CAIRO_STATUS_SUCCESS;
+
+	for (n = 0; n < boxes->num_limits; n++) {
+	    const cairo_box_t *limits = &boxes->limits[n];
+	    cairo_box_t _box;
+	    cairo_point_t _p1, _p2;
+
+	    if (p1.x >= limits->p2.x || p2.x <= limits->p1.x)
+		continue;
+	    if (p1.y >= limits->p2.y || p2.y <= limits->p1.y)
+		continue;
+
+	    /* Otherwise, clip the box to the limits. */
+	    _p1 = p1;
+	    if (_p1.x < limits->p1.x)
+		_p1.x = limits->p1.x;
+	    if (_p1.y < limits->p1.y)
+		_p1.y = limits->p1.y;
+
+	    _p2 = p2;
+	    if (_p2.x > limits->p2.x)
+		_p2.x = limits->p2.x;
+	    if (_p2.y > limits->p2.y)
+		_p2.y = limits->p2.y;
+
+	    if (_p2.y <= _p1.y || _p2.x <= _p1.x)
+		continue;
+
+	    _box.p1.y = _p1.y;
+	    _box.p2.y = _p2.y;
+	    if (reversed) {
+		_box.p1.x = _p2.x;
+		_box.p2.x = _p1.x;
+	    } else {
+		_box.p1.x = _p1.x;
+		_box.p2.x = _p2.x;
+	    }
+
+	    _cairo_boxes_add_internal (boxes, &_box);
+	}
+    } else {
+	_cairo_boxes_add_internal (boxes, box);
+    }
+
+    return boxes->status;
+}
+
+void
+_cairo_boxes_extents (const cairo_boxes_t *boxes,
+		      cairo_rectangle_int_t *extents)
+{
+    const struct _cairo_boxes_chunk *chunk;
+    cairo_box_t box;
+    int i;
+
+    box.p1.y = box.p1.x = INT_MAX;
+    box.p2.y = box.p2.x = INT_MIN;
+
+    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+	const cairo_box_t *b = chunk->base;
+	for (i = 0; i < chunk->count; i++) {
+	    if (b[i].p1.x < box.p1.x)
+		box.p1.x = b[i].p1.x;
+
+	    if (b[i].p1.y < box.p1.y)
+		box.p1.y = b[i].p1.y;
+
+	    if (b[i].p2.x > box.p2.x)
+		box.p2.x = b[i].p2.x;
+
+	    if (b[i].p2.y > box.p2.y)
+		box.p2.y = b[i].p2.y;
+	}
+    }
+
+    _cairo_box_round_to_rectangle (&box, extents);
+}
+
+void
+_cairo_boxes_clear (cairo_boxes_t *boxes)
+{
+    struct _cairo_boxes_chunk *chunk, *next;
+
+    for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
+	next = chunk->next;
+	free (chunk);
+    }
+
+    boxes->tail = &boxes->chunks;
+    boxes->chunks.next = 0;
+    boxes->chunks.count = 0;
+    boxes->num_boxes = 0;
+
+    boxes->is_pixel_aligned = TRUE;
+}
+
+void
+_cairo_boxes_fini (cairo_boxes_t *boxes)
+{
+    struct _cairo_boxes_chunk *chunk, *next;
+
+    for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
+	next = chunk->next;
+	free (chunk);
+    }
+}
--- a/gfx/cairo/cairo/src/cairo-cache-private.h
+++ b/gfx/cairo/cairo/src/cairo-cache-private.h
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -32,16 +32,17 @@
  *
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
  *	Graydon Hoare <graydon@redhat.com>
  *	Carl Worth <cworth@cworth.org>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
 
 static void
 _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
 				    unsigned long  additional);
 
 static cairo_bool_t
 _cairo_cache_entry_is_non_zero (const void *entry)
 {
@@ -169,19 +170,17 @@ void
  * the cache until the cache is smaller than max_size. Also, the
  * automatic ejection of entries on _cairo_cache_insert() will resume.
  **/
 void
 _cairo_cache_thaw (cairo_cache_t *cache)
 {
     assert (cache->freeze_count > 0);
 
-    cache->freeze_count--;
-
-    if (cache->freeze_count == 0)
+    if (--cache->freeze_count == 0)
 	_cairo_cache_shrink_to_accommodate (cache, 0);
 }
 
 /**
  * _cairo_cache_lookup:
  * @cache: a cache
  * @key: the key of interest
  * @entry_return: pointer for return value
@@ -235,19 +234,16 @@ static cairo_bool_t
  * the cache is at least @additional bytes less than
  * cache->max_size. That is, make enough room to accommodate a new
  * entry of size @additional.
  **/
 static void
 _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
 				    unsigned long  additional)
 {
-    if (cache->freeze_count)
-	return;
-
     while (cache->size + additional > cache->max_size) {
 	if (! _cairo_cache_remove_random (cache))
 	    return;
     }
 }
 
 /**
  * _cairo_cache_insert:
@@ -262,17 +258,18 @@ static void
  * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
  **/
 cairo_status_t
 _cairo_cache_insert (cairo_cache_t	 *cache,
 		     cairo_cache_entry_t *entry)
 {
     cairo_status_t status;
 
-    _cairo_cache_shrink_to_accommodate (cache, entry->size);
+    if (entry->size && ! cache->freeze_count)
+	_cairo_cache_shrink_to_accommodate (cache, entry->size);
 
     status = _cairo_hash_table_insert (cache->hash_table,
 				       (cairo_hash_entry_t *) entry);
     if (unlikely (status))
 	return status;
 
     cache->size += entry->size;
 
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -36,16 +36,17 @@
 
 /*
  * Useful links:
  * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
  */
 
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
+#include "cairo-error-private.h"
 
 #if CAIRO_HAS_FONT_SUBSET
 
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 #include <string.h>
 
 /* CFF Dict Operators. If the high byte is 0 the command is encoded
@@ -112,16 +113,17 @@ typedef struct _cairo_cff_font {
     cairo_hash_table_t  *top_dict;
     cairo_hash_table_t  *private_dict;
     cairo_array_t        strings_index;
     cairo_array_t        charstrings_index;
     cairo_array_t        global_sub_index;
     cairo_array_t        local_sub_index;
     int                  num_glyphs;
     cairo_bool_t         is_cid;
+    int  		 units_per_em;
 
     /* CID Font Data */
     int                 *fdselect;
     unsigned int         num_fontdicts;
     cairo_hash_table_t **fd_dict;
     cairo_hash_table_t **fd_private_dict;
     cairo_array_t       *fd_local_sub_index;
 
@@ -1767,16 +1769,19 @@ static cairo_int_status_t
 	goto fail2;
     }
     font->x_min = (int16_t) be16_to_cpu (head.x_min);
     font->y_min = (int16_t) be16_to_cpu (head.y_min);
     font->x_max = (int16_t) be16_to_cpu (head.x_max);
     font->y_max = (int16_t) be16_to_cpu (head.y_max);
     font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
     font->descent = (int16_t) be16_to_cpu (hhea.descender);
+    font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
+    if (font->units_per_em == 0)
+        font->units_per_em = 1000;
 
     font->font_name = NULL;
     status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
 					     &font->ps_name,
 					     &font->font_name);
     if (_cairo_status_is_error (status))
 	goto fail3;
 
@@ -1950,30 +1955,30 @@ cairo_status_t
 	if (cff_subset->font_name == NULL) {
 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	    goto fail2;
 	}
     } else {
 	cff_subset->font_name = NULL;
     }
 
-    cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+    cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
     if (unlikely (cff_subset->widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail3;
     }
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
-        cff_subset->widths[i] = font->widths[i];
+        cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
 
-    cff_subset->x_min = font->x_min;
-    cff_subset->y_min = font->y_min;
-    cff_subset->x_max = font->x_max;
-    cff_subset->y_max = font->y_max;
-    cff_subset->ascent = font->ascent;
-    cff_subset->descent = font->descent;
+    cff_subset->x_min = (double)font->x_min/font->units_per_em;
+    cff_subset->y_min = (double)font->y_min/font->units_per_em;
+    cff_subset->x_max = (double)font->x_max/font->units_per_em;
+    cff_subset->y_max = (double)font->y_max/font->units_per_em;
+    cff_subset->ascent = (double)font->ascent/font->units_per_em;
+    cff_subset->descent = (double)font->descent/font->units_per_em;
 
     cff_subset->data = malloc (length);
     if (unlikely (cff_subset->data == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail4;
     }
 
     memcpy (cff_subset->data, data, length);
@@ -2207,31 +2212,31 @@ cairo_status_t
 
     cff_subset->font_name = NULL;
     cff_subset->ps_name = strdup (font->ps_name);
     if (unlikely (cff_subset->ps_name == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail2;
     }
 
-    cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+    cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
     if (unlikely (cff_subset->widths == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail3;
     }
 
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
-        cff_subset->widths[i] = type2_subset.widths[i];
+        cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
 
-    cff_subset->x_min = type2_subset.x_min;
-    cff_subset->y_min = type2_subset.y_min;
-    cff_subset->x_max = type2_subset.x_max;
-    cff_subset->y_max = type2_subset.y_max;
-    cff_subset->ascent = type2_subset.y_max;
-    cff_subset->descent = type2_subset.y_min;
+    cff_subset->x_min = (double)type2_subset.x_min/1000;
+    cff_subset->y_min = (double)type2_subset.y_min/1000;
+    cff_subset->x_max = (double)type2_subset.x_max/1000;
+    cff_subset->y_max = (double)type2_subset.y_max/1000;
+    cff_subset->ascent = (double)type2_subset.y_max/1000;
+    cff_subset->descent = (double)type2_subset.y_min/1000;
 
     cff_subset->data = malloc (length);
     if (unlikely (cff_subset->data == NULL)) {
 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	goto fail4;
     }
 
     memcpy (cff_subset->data, data, length);
--- a/gfx/cairo/cairo/src/cairo-clip-private.h
+++ b/gfx/cairo/cairo/src/cairo-clip-private.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -71,31 +71,31 @@ struct _cairo_clip {
 
     cairo_bool_t all_clipped;
 
 };
 
 cairo_private void
 _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_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);
 
+cairo_private cairo_bool_t
+_cairo_clip_equal (const cairo_clip_t *clip_a,
+		   const cairo_clip_t *clip_b);
+
 #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,
@@ -107,31 +107,45 @@ cairo_private cairo_status_t
 cairo_private cairo_status_t
 _cairo_clip_apply_clip (cairo_clip_t *clip,
 			const cairo_clip_t *other);
 
 cairo_private const cairo_rectangle_int_t *
 _cairo_clip_get_extents (const cairo_clip_t *clip);
 
 cairo_private cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst);
+_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
 
 cairo_private cairo_status_t
 _cairo_clip_combine_with_surface (cairo_clip_t *clip,
 				  cairo_surface_t *dst,
-				  const cairo_rectangle_int_t *extents);
+				  int dst_x, int dst_y);
 
 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 cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t **clip,
+		      cairo_composite_rectangles_t *extents,
+		      cairo_box_t **boxes,
+		      int *num_boxes);
+
+cairo_private cairo_bool_t
+_cairo_clip_contains_rectangle (cairo_clip_t *clip,
+				const cairo_rectangle_int_t *rect);
+
+cairo_private cairo_bool_t
+_cairo_clip_contains_extents (cairo_clip_t *clip,
+				const cairo_composite_rectangles_t *extents);
+
 cairo_private void
 _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
@@ -10,17 +10,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -36,105 +36,26 @@
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  *	Kristian Høgsberg <krh@redhat.com>
  *	Chris Wilson <chris@chris-wilson.co.uk>
  */
 
 #include "cairoint.h"
 #include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-gstate-private.h"
 #include "cairo-path-fixed-private.h"
+#include "cairo-composite-rectangles-private.h"
 #include "cairo-region-private.h"
 
-/* Keep a stash of recently freed clip_paths, since we need to
- * reallocate them frequently.
- */
-#define MAX_FREED_POOL_SIZE 4
-typedef struct {
-    void *pool[MAX_FREED_POOL_SIZE];
-    int top;
-} freed_pool_t;
-
+#if HAS_FREED_POOL
 static freed_pool_t clip_path_pool;
-
-static void *
-_atomic_fetch (void **slot)
-{
-    return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
-}
-
-static cairo_bool_t
-_atomic_store (void **slot, void *ptr)
-{
-    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
-}
-
-static void *
-_freed_pool_get (freed_pool_t *pool)
-{
-    void *ptr;
-    int i;
-
-    i = pool->top - 1;
-    if (i < 0)
-	i = 0;
-
-    ptr = _atomic_fetch (&pool->pool[i]);
-    if (ptr != NULL) {
-	pool->top = i;
-	return ptr;
-    }
-
-    /* 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
-_freed_pool_put (freed_pool_t *pool, void *ptr)
-{
-    int i = pool->top;
-
-    if (_atomic_store (&pool->pool[i], ptr)) {
-	pool->top = i + 1;
-	return;
-    }
-
-    /* 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;
-	}
-    }
-
-    /* full */
-    pool->top = ARRAY_LENGTH (pool->pool);
-    free (ptr);
-}
-
-static void
-_freed_pool_reset (freed_pool_t *pool)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
-	free (pool->pool[i]);
-	pool->pool[i] = NULL;
-    }
-}
+#endif
 
 static cairo_clip_path_t *
 _cairo_clip_path_create (cairo_clip_t *clip)
 {
     cairo_clip_path_t *clip_path;
 
     clip_path = _freed_pool_get (&clip_path_pool);
     if (unlikely (clip_path == NULL)) {
@@ -153,19 +74,16 @@ static cairo_clip_path_t *
     clip->path = clip_path;
 
     return clip_path;
 }
 
 static cairo_clip_path_t *
 _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
 {
-    if (clip_path == NULL)
-	return NULL;
-
     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
 
     _cairo_reference_count_inc (&clip_path->ref_count);
 
     return clip_path;
 }
 
 static void
@@ -242,57 +160,50 @@ static cairo_status_t
     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->antialias = CAIRO_ANTIALIAS_DEFAULT;
     clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
 
+    clip_path->extents = *rect;
+    if (clip_path->prev != NULL) {
+	if (! _cairo_rectangle_intersect (&clip_path->extents,
+					  &clip_path->prev->extents))
+	{
+	    _cairo_clip_set_all_clipped (clip);
+	}
+    }
+
     /* 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)
 {
     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;
+	if (other->path == NULL) {
+	    clip->path = NULL;
+	    if (! clip->all_clipped)
+		clip = NULL;
+	} else {
+	    clip->path = _cairo_clip_path_reference (other->path);
+	}
     } else {
 	_cairo_clip_init (clip);
+	clip = NULL;
     }
 
     return clip;
 }
 
 void
 _cairo_clip_reset (cairo_clip_t *clip)
 {
@@ -313,19 +224,18 @@ static cairo_status_t
     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)) &&
+	    (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) {
@@ -367,16 +277,48 @@ static cairo_status_t
     clip_path->tolerance = tolerance;
     clip_path->antialias = antialias;
     if (is_box)
 	clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+cairo_bool_t
+_cairo_clip_equal (const cairo_clip_t *clip_a,
+		   const cairo_clip_t *clip_b)
+{
+    const cairo_clip_path_t *clip_path_a, *clip_path_b;
+
+    clip_path_a = clip_a->path;
+    clip_path_b = clip_b->path;
+
+    while (clip_path_a && clip_path_b) {
+	if (clip_path_a == clip_path_b)
+	    return TRUE;
+
+	if (clip_path_a->fill_rule != clip_path_b->fill_rule)
+	    return FALSE;
+
+	if (clip_path_a->tolerance != clip_path_b->tolerance)
+	    return FALSE;
+
+	if (clip_path_a->antialias != clip_path_b->antialias)
+	    return FALSE;
+
+	if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
+	    return FALSE;
+
+	clip_path_a = clip_path_a->prev;
+	clip_path_b = clip_path_b->prev;
+    }
+
+    return clip_path_a == clip_path_b; /* ie both NULL */
+}
+
 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)
@@ -404,17 +346,17 @@ cairo_status_t
 	_cairo_clip_set_all_clipped (clip);
 	return CAIRO_STATUS_SUCCESS;
     }
 
     /* 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.y &&
-	    rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
+	    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;
 	}
     }
 
     return _cairo_clip_intersect_rectangle (clip, rectangle);
 }
@@ -438,16 +380,17 @@ static cairo_status_t
 
     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)) {
+	clip->path = clip->path->prev;
 	_cairo_clip_path_destroy (clip_path);
 	return status;
     }
 
     _cairo_path_fixed_transform (&clip_path->path, matrix);
     _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
 						&clip_path->extents);
     if (clip_path->prev != NULL) {
@@ -480,31 +423,39 @@ static cairo_status_t
 
     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)) {
+	clip->path = clip->path->prev;
 	_cairo_clip_path_destroy (clip_path);
 	return status;
     }
 
     _cairo_path_fixed_translate (&clip_path->path,
 				 _cairo_fixed_from_int (tx),
 				 _cairo_fixed_from_int (ty));
 
     clip_path->fill_rule = other_path->fill_rule;
     clip_path->tolerance = other_path->tolerance;
     clip_path->antialias = other_path->antialias;
 
     clip_path->flags = other_path->flags;
     if (other_path->region != NULL) {
 	clip_path->region = cairo_region_copy (other_path->region);
+	status = clip_path->region->status;
+	if (unlikely (status)) {
+	    clip->path = clip->path->prev;
+	    _cairo_clip_path_destroy (clip_path);
+	    return status;
+	}
+
 	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;
 
@@ -992,197 +943,224 @@ static cairo_int_status_t
 		return status;
 	}
     }
 
     *count = num_boxes;
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
-_combine_region (cairo_surface_t *surface,
-		 const cairo_region_t *region,
-		 const cairo_rectangle_int_t *extents)
+static cairo_surface_t *
+_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
+			      cairo_surface_t *target,
+			      int *tx, int *ty)
 {
-    cairo_region_t clear_region;
+    const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
+    cairo_bool_t need_translate;
+    cairo_surface_t *surface;
+    cairo_clip_path_t *prev;
     cairo_status_t status;
 
-    _cairo_region_init_rectangle (&clear_region, extents);
-    status = cairo_region_subtract (&clear_region, region);
-    if (unlikely (status))
-	return status;
-
-    if (! cairo_region_is_empty (&clear_region)) {
-	cairo_region_translate (&clear_region, -extents->x, -extents->y);
-	status = _cairo_surface_fill_region (surface,
-					     CAIRO_OPERATOR_CLEAR,
-					     CAIRO_COLOR_TRANSPARENT,
-					     &clear_region);
+    while (clip_path->prev != NULL &&
+	   clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
+	   clip_path->path.maybe_fill_region)
+    {
+	clip_path = clip_path->prev;
     }
-    _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;
-
+    clip_extents = &clip_path->extents;
     if (clip_path->surface != NULL &&
 	clip_path->surface->backend == target->backend)
     {
-	return cairo_surface_reference (clip_path->surface);
+	*tx = clip_extents->x;
+	*ty = clip_extents->y;
+	return clip_path->surface;
     }
 
-    surface = _cairo_surface_create_similar_solid (target,
-						   CAIRO_CONTENT_ALPHA,
-						   clip_extents->width,
-						   clip_extents->height,
-						   CAIRO_COLOR_TRANSPARENT,
-						   FALSE);
+    surface = _cairo_surface_create_similar_scratch (target,
+						     CAIRO_CONTENT_ALPHA,
+						     clip_extents->width,
+						     clip_extents->height);
     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);
+	surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
+					      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 (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
+	clip_path->path.maybe_fill_region)
+    {
+	status = _cairo_surface_paint (surface,
+				       CAIRO_OPERATOR_SOURCE,
+				       &_cairo_pattern_white.base,
+				       NULL);
+	if (unlikely (status))
+	    goto BAIL;
+    }
+    else
+    {
+	status = _cairo_surface_paint (surface,
+				       CAIRO_OPERATOR_CLEAR,
+				       &_cairo_pattern_clear.base,
+				       NULL);
 	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,
+				      CAIRO_OPERATOR_ADD,
+				      &_cairo_pattern_white.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;
     }
 
     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) {
+    while (prev != NULL) {
+	if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
+	    prev->path.maybe_fill_region)
+	{
 	    /* a simple box only affects the extents */
-	} else if (prev->path.is_rectilinear) {
+	}
+	else if (prev->path.is_rectilinear ||
+		prev->surface == NULL ||
+		prev->surface->backend != target->backend)
+	{
 	    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,
+					  &_cairo_pattern_white.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 {
+	}
+	else
+	{
+	    cairo_surface_pattern_t pattern;
 	    cairo_surface_t *prev_surface;
+	    int prev_tx, prev_ty;
 
-	    prev_surface = _cairo_clip_path_get_surface (prev, target);
-	    _cairo_pattern_init_for_surface (&pattern.surface, prev_surface);
-	    cairo_surface_destroy (prev_surface);
+	    prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
+	    status = prev_surface->status;
+	    if (unlikely (status))
+		goto BAIL;
 
+	    _cairo_pattern_init_for_surface (&pattern, prev_surface);
+	    pattern.base.filter = CAIRO_FILTER_NEAREST;
 	    cairo_matrix_init_translate (&pattern.base.matrix,
-					 -prev->extents.x + clip_extents->x,
-					 -prev->extents.y + clip_extents->y);
+					 clip_extents->x - prev_tx,
+					 clip_extents->y - prev_ty);
 	    status = _cairo_surface_paint (surface,
 					   CAIRO_OPERATOR_IN,
 					   &pattern.base,
 					   NULL);
 	    _cairo_pattern_fini (&pattern.base);
 
 	    if (unlikely (status))
 		goto BAIL;
+
+	    break;
 	}
+
+	prev = prev->prev;
     }
 
-  DONE:
+    *tx = clip_extents->x;
+    *ty = clip_extents->y;
     cairo_surface_destroy (clip_path->surface);
-    return clip_path->surface = cairo_surface_reference (surface);
+    return clip_path->surface = surface;
 
   BAIL:
     cairo_surface_destroy (surface);
     return _cairo_surface_create_in_error (status);
 }
 
+cairo_bool_t
+_cairo_clip_contains_rectangle (cairo_clip_t *clip,
+				const cairo_rectangle_int_t *rect)
+{
+    cairo_clip_path_t *clip_path;
+
+    if (clip == NULL)
+	return FALSE;
+
+    clip_path = clip->path;
+    if (clip_path->extents.x > rect->x ||
+	clip_path->extents.y > rect->y ||
+	clip_path->extents.x + clip_path->extents.width  < rect->x + rect->width ||
+	clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
+    {
+	return FALSE;
+    }
+
+    do {
+	cairo_box_t box;
+
+	if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
+	    return FALSE;
+
+	if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
+	    return FALSE;
+
+	if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
+	    box.p1.y > _cairo_fixed_from_int (rect->y) ||
+	    box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
+	    box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
+	{
+	    return FALSE;
+	}
+    } while ((clip_path = clip_path->prev) != NULL);
+
+    return TRUE;
+}
+
+cairo_bool_t
+_cairo_clip_contains_extents (cairo_clip_t *clip,
+			      const cairo_composite_rectangles_t *extents)
+{
+    const cairo_rectangle_int_t *rect;
+
+    if (clip == NULL)
+	return FALSE;
+
+    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
+    return _cairo_clip_contains_rectangle (clip, rect);
+}
+
 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;
@@ -1197,116 +1175,91 @@ void
 	fprintf (stream, "clip: empty\n");
 	return;
     }
 
     fprintf (stream, "clip:\n");
 
     clip_path = clip->path;
     do {
-	fprintf (stream, "path: has region? %s, has surface? %s: ",
+	fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
 		 clip_path->region == NULL ? "no" : "yes",
-		 clip_path->surface == NULL ? "no" : "yes");
+		 clip_path->surface == NULL ? "no" : "yes",
+		 clip_path->antialias,
+		 clip_path->tolerance,
+		 clip_path->fill_rule);
 	_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)
+_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty)
 {
+    /* XXX is_clear -> all_clipped */
     assert (clip->path != NULL);
-    return _cairo_clip_path_get_surface (clip->path, target);
+    return _cairo_clip_path_get_surface (clip->path, target, tx, ty);
 }
 
 cairo_status_t
 _cairo_clip_combine_with_surface (cairo_clip_t *clip,
 				  cairo_surface_t *dst,
-				  const cairo_rectangle_int_t *extents)
+				  int dst_x, int dst_y)
 {
-    cairo_pattern_union_t pattern;
     cairo_clip_path_t *clip_path = clip->path;
     cairo_bool_t need_translate;
     cairo_status_t status;
 
     assert (clip_path != NULL);
 
-    if (clip_path->surface != NULL &&
-	clip_path->surface->backend == dst->backend)
-    {
-	_cairo_pattern_init_for_surface (&pattern.surface,
-					 clip_path->surface);
-	cairo_matrix_init_translate (&pattern.base.matrix,
-				     extents->x - clip_path->extents.x,
-				     extents->y - clip_path->extents.y);
-	status = _cairo_surface_paint (dst,
-				       CAIRO_OPERATOR_IN,
-				       &pattern.base,
-				       NULL);
-
-	_cairo_pattern_fini (&pattern.base);
-
-	return status;
-    }
-
-    _cairo_pattern_init_solid (&pattern.solid,
-			       CAIRO_COLOR_WHITE,
-			       CAIRO_CONTENT_COLOR);
-
-    need_translate = extents->x | extents->y;
+    need_translate = dst_x | dst_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_surface_pattern_t pattern;
+
+	    _cairo_pattern_init_for_surface (&pattern, clip_path->surface);
 	    cairo_matrix_init_translate (&pattern.base.matrix,
-					 extents->x - clip_path->extents.x,
-					 extents->y - clip_path->extents.y);
+					 dst_x - clip_path->extents.x,
+					 dst_y - clip_path->extents.y);
+	    pattern.base.filter = CAIRO_FILTER_NEAREST;
 	    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;
+	if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
+	    clip_path->path.maybe_fill_region)
+	{
+	    continue;
+	}
 
-	    _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 (need_translate) {
+	    _cairo_path_fixed_translate (&clip_path->path,
+					 _cairo_fixed_from_int (-dst_x),
+					 _cairo_fixed_from_int (-dst_y));
+	}
+	status = _cairo_surface_fill (dst,
+				      CAIRO_OPERATOR_IN,
+				      &_cairo_pattern_white.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 (dst_x),
+					 _cairo_fixed_from_int (dst_y));
 	}
 
 	if (unlikely (status))
 	    return status;
     } while ((clip_path = clip_path->prev) != NULL);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1427,16 +1380,100 @@ cairo_int_status_t
     if (*count == 0) {
 	_cairo_clip_set_all_clipped (clip);
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+box_is_aligned (const cairo_box_t *box)
+{
+    return
+	_cairo_fixed_is_integer (box->p1.x) &&
+	_cairo_fixed_is_integer (box->p1.y) &&
+	_cairo_fixed_is_integer (box->p2.x) &&
+	_cairo_fixed_is_integer (box->p2.y);
+}
+
+static void
+intersect_with_boxes (cairo_composite_rectangles_t *extents,
+		      cairo_box_t *boxes,
+		      int num_boxes)
+{
+    cairo_rectangle_int_t rect;
+    cairo_box_t box;
+    cairo_bool_t is_empty;
+
+    box.p1.x = box.p1.y = INT_MIN;
+    box.p2.x = box.p2.y = INT_MAX;
+    while (num_boxes--) {
+	if (boxes->p1.x < box.p1.x)
+	    box.p1.x = boxes->p1.x;
+	if (boxes->p1.y < box.p1.y)
+	    box.p1.y = boxes->p1.y;
+
+	if (boxes->p2.x > box.p2.x)
+	    box.p2.x = boxes->p2.x;
+	if (boxes->p2.y > box.p2.y)
+	    box.p2.y = boxes->p2.y;
+    }
+
+    _cairo_box_round_to_rectangle (&box, &rect);
+    is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect);
+    is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect);
+}
+
+cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t **clip,
+		      cairo_composite_rectangles_t *extents,
+		      cairo_box_t **boxes,
+		      int *num_boxes)
+{
+    cairo_status_t status;
+    const cairo_rectangle_int_t *rect;
+
+    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
+
+    if (*clip == NULL)
+	goto EXTENTS;
+
+    status = _cairo_clip_rectangle (*clip, rect);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
+    switch ((int) status) {
+    case CAIRO_STATUS_SUCCESS:
+	intersect_with_boxes (extents, *boxes, *num_boxes);
+	if (rect->width == 0 || rect->height == 0 ||
+	    extents->is_bounded ||
+	    (*num_boxes == 1 && box_is_aligned (*boxes)))
+	{
+	    *clip = NULL;
+	}
+	goto DONE;
+
+    case CAIRO_INT_STATUS_UNSUPPORTED:
+	goto EXTENTS;
+
+    default:
+	return status;
+    }
+
+  EXTENTS:
+    status = CAIRO_STATUS_SUCCESS;
+    _cairo_box_from_rectangle (&(*boxes)[0], rect);
+    *num_boxes = 1;
+  DONE:
+    return status;
+}
+
+
 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)
--- a/gfx/cairo/cairo/src/cairo-color.c
+++ b/gfx/cairo/cairo/src/cairo-color.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -62,23 +62,24 @@ const cairo_color_t *
 {
     switch (stock) {
     case CAIRO_STOCK_WHITE:
 	return &cairo_color_white;
     case CAIRO_STOCK_BLACK:
 	return &cairo_color_black;
     case CAIRO_STOCK_TRANSPARENT:
 	return &cairo_color_transparent;
+
+    case CAIRO_STOCK_NUM_COLORS:
+    default:
+	ASSERT_NOT_REACHED;
+	/* If the user can get here somehow, give a color that indicates a
+	 * problem. */
+	return &cairo_color_magenta;
     }
-
-    ASSERT_NOT_REACHED;
-
-    /* If the user can get here somehow, give a color that indicates a
-     * problem. */
-    return &cairo_color_magenta;
 }
 
 void
 _cairo_color_init (cairo_color_t *color)
 {
     *color = cairo_color_white;
 }
 
@@ -156,20 +157,55 @@ void
 				     double	   *alpha)
 {
     *red   = color->red   * color->alpha;
     *green = color->green * color->alpha;
     *blue  = color->blue  * color->alpha;
     *alpha = color->alpha;
 }
 
+/* NB: This function works both for unmultiplied and premultiplied colors */
 cairo_bool_t
 _cairo_color_equal (const cairo_color_t *color_a,
 	            const cairo_color_t *color_b)
 {
     if (color_a == color_b)
 	return TRUE;
 
+    if (color_a->alpha_short != color_b->alpha_short)
+        return FALSE;
+
+    if (color_a->alpha_short == 0)
+        return TRUE;
+
     return color_a->red_short   == color_b->red_short   &&
            color_a->green_short == color_b->green_short &&
-           color_a->blue_short  == color_b->blue_short  &&
-           color_a->alpha_short == color_b->alpha_short;
+           color_a->blue_short  == color_b->blue_short;
+}
+
+cairo_bool_t
+_cairo_color_stop_equal (const cairo_color_stop_t *color_a,
+			 const cairo_color_stop_t *color_b)
+{
+    if (color_a == color_b)
+	return TRUE;
+
+    return color_a->alpha_short == color_b->alpha_short &&
+           color_a->red_short   == color_b->red_short   &&
+           color_a->green_short == color_b->green_short &&
+           color_a->blue_short  == color_b->blue_short;
 }
+
+cairo_content_t
+_cairo_color_get_content (const cairo_color_t *color)
+{
+    if (CAIRO_COLOR_IS_OPAQUE (color))
+        return CAIRO_CONTENT_COLOR;
+
+    if (color->red_short == 0 &&
+	color->green_short == 0 &&
+	color->blue_short == 0)
+    {
+        return CAIRO_CONTENT_ALPHA;
+    }
+
+    return CAIRO_CONTENT_COLOR_ALPHA;
+}
--- a/gfx/cairo/cairo/src/cairo-combsort-private.h
+++ b/gfx/cairo/cairo/src/cairo-combsort-private.h
@@ -6,17 +6,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -39,16 +39,55 @@
 #define CAIRO_COMPILER_PRIVATE_H
 
 #include "cairo.h"
 
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+/* Size in bytes of buffer to use off the stack per functions.
+ * Mostly used by text functions.  For larger allocations, they'll
+ * malloc(). */
+#ifndef CAIRO_STACK_BUFFER_SIZE
+#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
+#endif
+
+#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T))
+
+/*
+ * The goal of this block is to define the following macros for
+ * providing faster linkage to functions in the public API for calls
+ * from within cairo.
+ *
+ * slim_hidden_proto(f)
+ * slim_hidden_proto_no_warn(f)
+ *
+ *   Declares `f' as a library internal function and hides the
+ *   function from the global symbol table.  This macro must be
+ *   expanded after `f' has been declared with a prototype but before
+ *   any calls to the function are seen by the compiler.  The no_warn
+ *   variant inhibits warnings about the return value being unused at
+ *   call sites.  The macro works by renaming `f' to an internal name
+ *   in the symbol table and hiding that.  As far as cairo internal
+ *   calls are concerned they're calling a library internal function
+ *   and thus don't need to bounce via the PLT.
+ *
+ * slim_hidden_def(f)
+ *
+ *   Exports `f' back to the global symbol table.  This macro must be
+ *   expanded right after the function definition and only for symbols
+ *   hidden previously with slim_hidden_proto().  The macro works by
+ *   adding a global entry to the symbol table which points at the
+ *   internal name of `f' created by slim_hidden_proto().
+ *
+ * Functions in the public API which aren't called by the library
+ * don't need to be hidden and re-exported using the slim hidden
+ * macros.
+ */
 #if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
 # define slim_hidden_proto(name)		slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private
 # define slim_hidden_proto_no_warn(name)	slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn
 # define slim_hidden_def(name)			slim_hidden_def1(name, slim_hidden_int_name(name))
 # define slim_hidden_int_name(name) INT_##name
 # define slim_hidden_proto1(name, internal)				\
   extern __typeof (name) name						\
 	__asm__ (slim_hidden_asmname (internal))
@@ -129,19 +168,21 @@
  *
  * Both these function attributes allow gcc to perform CSE and
  * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents
  * do not change across the function call.
  */
 #if __GNUC__ >= 3
 #define cairo_pure __attribute__((pure))
 #define cairo_const __attribute__((const))
+#define cairo_always_inline inline __attribute__((always_inline))
 #else
 #define cairo_pure
 #define cairo_const
+#define cairo_always_inline inline
 #endif
 
 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
 #define _CAIRO_BOOLEAN_EXPR(expr)                   \
  __extension__ ({                               \
    int _cairo_boolean_var_;                         \
    if (expr)                                    \
       _cairo_boolean_var_ = 1;                      \
@@ -166,16 +207,36 @@
 #define popen _popen
 #define pclose _pclose
 #define hypot _hypot
 #endif
 
 #ifdef _MSC_VER
 #undef inline
 #define inline __inline
+
+/* there are currently linkage problems that arise when trying to include intrin.h in c++:
+ * D:\sdks\v7.0\include\winnt.h(3674) : error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed
+ * so avoid defining ffs in c++ code for now */
+#ifndef  __cplusplus
+/* Add a definition of ffs */
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+static __forceinline int
+ffs (int x)
+{
+    unsigned long i;
+
+    if (_BitScanForward(&i, x) != 0)
+	return i + 1;
+
+    return 0;
+}
+#endif
+
 #endif
 
 #if defined(_MSC_VER) && defined(_M_IX86)
 /* When compiling with /Gy and /OPT:ICF identical functions will be folded in together.
    The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and
    will never be folded into another one. Something like this might eventually
    be needed for GCC but it seems fine for now. */
 #define CAIRO_ENSURE_UNIQUE                       \
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-composite-rectangles-private.h
@@ -0,0 +1,105 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.u>
+ */
+
+#ifndef CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
+#define CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
+
+#include "cairo-types-private.h"
+
+CAIRO_BEGIN_DECLS
+
+/* Rectangles that take part in a composite operation.
+ *
+ * The source and mask track the extents of the respective patterns in device
+ * space. The unbounded rectangle is essentially the clip rectangle. And the
+ * intersection of all is the bounded rectangle, which is the minimum extents
+ * the operation may require. Whether or not the operation is actually bounded
+ * is tracked in the is_bounded boolean.
+ *
+ */
+struct _cairo_composite_rectangles {
+    cairo_rectangle_int_t source;
+    cairo_rectangle_int_t mask;
+    cairo_rectangle_int_t bounded; /* dst */
+    cairo_rectangle_int_t unbounded; /* clip */
+    uint32_t is_bounded;
+};
+
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
+					 const cairo_rectangle_int_t *surface_extents,
+					 cairo_operator_t	 op,
+					 const cairo_pattern_t	*source,
+					 cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
+					const cairo_rectangle_int_t *surface_extents,
+					cairo_operator_t	 op,
+					const cairo_pattern_t	*source,
+					const cairo_pattern_t	*mask,
+					cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
+					     const cairo_rectangle_int_t *surface_extents,
+					     cairo_operator_t	 op,
+					     const cairo_pattern_t	*source,
+					     cairo_path_fixed_t	*path,
+					     const cairo_stroke_style_t	*style,
+					     const cairo_matrix_t	*ctm,
+					     cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
+					   const cairo_rectangle_int_t *surface_extents,
+					   cairo_operator_t	 op,
+					   const cairo_pattern_t	*source,
+					   cairo_path_fixed_t	*path,
+					   cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
+					     const cairo_rectangle_int_t *surface_extents,
+					     cairo_operator_t		 op,
+					     const cairo_pattern_t	*source,
+					     cairo_scaled_font_t	*scaled_font,
+					     cairo_glyph_t		*glyphs,
+					     int			 num_glyphs,
+					     cairo_clip_t		*clip,
+					     cairo_bool_t		*overlap);
+
+#endif /* CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-composite-rectangles.c
@@ -0,0 +1,195 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
+ *
+ * Contributor(s):
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-composite-rectangles-private.h"
+
+/* A collection of routines to facilitate writing compositors. */
+
+static inline cairo_bool_t
+_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
+				  const cairo_rectangle_int_t *surface_extents,
+				  cairo_operator_t op,
+				  const cairo_pattern_t *source,
+				  cairo_clip_t *clip)
+{
+    extents->unbounded = *surface_extents;
+
+    if (clip != NULL) {
+	const cairo_rectangle_int_t *clip_extents;
+
+	clip_extents = _cairo_clip_get_extents (clip);
+	if (clip_extents == NULL)
+	    return FALSE;
+
+	if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
+	    return FALSE;
+    }
+
+    extents->bounded = extents->unbounded;
+    extents->is_bounded = _cairo_operator_bounded_by_either (op);
+
+    _cairo_pattern_get_extents (source, &extents->source);
+    if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
+	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+cairo_int_status_t
+_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
+					    const cairo_rectangle_int_t *surface_extents,
+					    cairo_operator_t		 op,
+					    const cairo_pattern_t	*source,
+					    cairo_clip_t		*clip)
+{
+    if (! _cairo_composite_rectangles_init (extents,
+					    surface_extents,
+					    op, source, clip))
+    {
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    extents->mask = extents->bounded;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
+{
+    cairo_bool_t ret;
+
+    ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
+    if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
+					   const cairo_rectangle_int_t *surface_extents,
+					   cairo_operator_t		 op,
+					   const cairo_pattern_t	*source,
+					   const cairo_pattern_t	*mask,
+					   cairo_clip_t			*clip)
+{
+    if (! _cairo_composite_rectangles_init (extents,
+					    surface_extents,
+					    op, source, clip))
+    {
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    _cairo_pattern_get_extents (mask, &extents->mask);
+
+    return _cairo_composite_rectangles_intersect (extents);
+}
+
+cairo_int_status_t
+_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
+					     const cairo_rectangle_int_t *surface_extents,
+					     cairo_operator_t		 op,
+					     const cairo_pattern_t	*source,
+					     cairo_path_fixed_t		*path,
+					     const cairo_stroke_style_t	*style,
+					     const cairo_matrix_t	*ctm,
+					     cairo_clip_t		*clip)
+{
+    if (! _cairo_composite_rectangles_init (extents,
+					    surface_extents,
+					    op, source, clip))
+    {
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
+
+    return _cairo_composite_rectangles_intersect (extents);
+}
+
+cairo_int_status_t
+_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
+					   const cairo_rectangle_int_t *surface_extents,
+					   cairo_operator_t		 op,
+					   const cairo_pattern_t	*source,
+					   cairo_path_fixed_t		*path,
+					   cairo_clip_t			*clip)
+{
+    if (! _cairo_composite_rectangles_init (extents,
+					    surface_extents,
+					    op, source, clip))
+    {
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    _cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
+
+    return _cairo_composite_rectangles_intersect (extents);
+}
+
+cairo_int_status_t
+_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
+					     const cairo_rectangle_int_t *surface_extents,
+					     cairo_operator_t		 op,
+					     const cairo_pattern_t	*source,
+					     cairo_scaled_font_t	*scaled_font,
+					     cairo_glyph_t		*glyphs,
+					     int			 num_glyphs,
+					     cairo_clip_t		*clip,
+					     cairo_bool_t		*overlap)
+{
+    cairo_status_t status;
+
+    if (! _cairo_composite_rectangles_init (extents,
+					    surface_extents,
+					    op, source, clip))
+    {
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+    }
+
+    status = _cairo_scaled_font_glyph_device_extents (scaled_font,
+						      glyphs, num_glyphs,
+						      &extents->mask,
+						      overlap);
+    if (unlikely (status))
+	return status;
+
+    return _cairo_composite_rectangles_intersect (extents);
+}
--- a/gfx/cairo/cairo/src/cairo-d2d-private.h
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.h
@@ -38,20 +38,18 @@
 
 #ifdef CAIRO_HAS_D2D_SURFACE
 
 #include <windows.h>
 #include <d2d1.h>
 #include <d3d10.h>
 #include <dxgi.h>
 
-extern "C" {
 #include "cairoint.h"
 #include "cairo-surface-clipper-private.h"
-}
 
 #include "cairo-win32-refptr.h"
 #include "cairo-d2d-private-fx.h"
 #include "cairo-win32.h"
 
 /* describes the type of the currently applied clip so that we can pop it */
 struct d2d_clip;
 
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -34,20 +34,19 @@
  *	Bas Schouten <bschouten@mozilla.com>
  */
 #define INITGUID
 
 #include "cairoint.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-error-private.h"
 
 // Required for using placement new.
 #include <new>
 
 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
 
 struct Vertex
 {
@@ -644,19 +643,19 @@ static cairo_bool_t
  * \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,
+		  const cairo_stroke_style_t	*style,
+		  const cairo_matrix_t	*ctm,
+		  const cairo_matrix_t	*ctm_inverse,
 		  double		 tolerance,
 		  cairo_antialias_t	 antialias,
 		  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 */
@@ -758,16 +757,26 @@ static void
 static int
 _cairo_d2d_compute_surface_mem_size(cairo_d2d_surface_t *surface)
 {
     int size = surface->rt->GetPixelSize().width * surface->rt->GetPixelSize().height;
     size *= surface->rt->GetPixelFormat().format == DXGI_FORMAT_A8_UNORM ? 1 : 4;
     return size;
 }
 
+static D2D1_COLOR_F
+_cairo_d2d_color_from_cairo_color_stop(const cairo_color_stop_t &color)
+{
+    return D2D1::ColorF((FLOAT)color.red, 
+			(FLOAT)color.green, 
+			(FLOAT)color.blue,
+			(FLOAT)color.alpha);
+}
+
+
 /**
  * Gets the surface buffer texture for window surfaces whose backbuffer
  * is not directly usable as a bitmap.
  *
  * \param surface D2D surface.
  * \return Buffer texture
  */
 static ID3D10Texture2D*
@@ -1430,40 +1439,40 @@ static RefPtr<ID2D1Brush>
 		    // Take the stop from the opposite side when reflected.
 		    stop = source_pattern->base.n_stops - stop - 1;
 		    // When reflected take 1 - offset as the offset.
 		    stops[i].position = (FLOAT)((repeat + 1.0f - source_pattern->base.stops[stop].offset) * stop_scale);
 		} else {
 		    stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
 		}
 		stops[i].color =
-		    _cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
+		    _cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
 	    }
 	} else {
 	    // Simple case, we don't need to reflect.
 	    for (int i = 0; i < num_stops; i++) {
 		// Calculate which repeat this is.
 		int repeat = i / source_pattern->base.n_stops;
 		// Calculate which stop this would be in the original pattern
 		cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
 		stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
-		stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+		stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	    }
 	}
     } else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
 	float offset_factor = (outer_radius - inner_radius) / outer_radius;
 	float global_offset = inner_radius / outer_radius;
 
 	stops = new D2D1_GRADIENT_STOP[num_stops];
 
 	// If the inner radius is not 0 we need to scale and offset the stops.
 	for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
 	    cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
 	    stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
-	    stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+	    stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	}
     } else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
 	float offset_factor = (outer_radius - inner_radius) / outer_radius;
 	float global_offset = inner_radius / outer_radius;
 
 	num_stops++; // Add a stop on the outer radius.
 	if (inner_radius != 0) {
 	    num_stops++; // Add a stop on the inner radius.
@@ -1477,17 +1486,17 @@ static RefPtr<ID2D1Brush>
 	if (inner_radius != 0) {
 	    stops[i].position = global_offset;
 	    stops[i].color = D2D1::ColorF(0, 0);
 	    i++;
 	}
 	for (unsigned int j = 0; j < source_pattern->base.n_stops; j++, i++) {
 	    cairo_gradient_stop_t *stop = &source_pattern->base.stops[j];
 	    stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
-	    stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+	    stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	}
 	stops[i].position = 1.0f;
 	stops[i].color = D2D1::ColorF(0, 0);
     } else {
 	return NULL;
     }
 
     RefPtr<ID2D1GradientStopCollection> stopCollection;
@@ -1509,17 +1518,17 @@ static RefPtr<ID2D1Brush>
 _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
 					cairo_linear_pattern_t *source_pattern)
 {
     if (source_pattern->p1.x == source_pattern->p2.x &&
 	source_pattern->p1.y == source_pattern->p2.y) {
 	// Cairo behavior in this situation is to draw a solid color the size of the last stop.
 	RefPtr<ID2D1SolidColorBrush> brush;
 	d2dsurf->rt->CreateSolidColorBrush(
-	    _cairo_d2d_color_from_cairo_color(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
+	    _cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
 	    &brush);
 	return brush;
     }
 
     cairo_matrix_t inv_mat = source_pattern->base.base.matrix;
     /**
      * Cairo views this matrix as the transformation of the destination
      * when the pattern is imposed. We see this differently, D2D transformation
@@ -1614,45 +1623,45 @@ static RefPtr<ID2D1Brush>
 		    // Take the stop from the opposite side when reflected.
 		    stop = source_pattern->base.n_stops - stop - 1;
 		    // When reflected take 1 - offset as the offset.
 		    stops[i].position = (FLOAT)((repeat + 1.0f - source_pattern->base.stops[stop].offset) * stop_scale);
 		} else {
 		    stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
 		}
 		stops[i].color =
-		    _cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
+		    _cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
 	    }
 	} else {
 	    // Simple case, we don't need to reflect.
 	    for (int i = 0; i < num_stops; i++) {
 		// Calculate which repeat this is.
 		int repeat = i / source_pattern->base.n_stops;
 		// Calculate which stop this would be in the original pattern
 		cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
 		stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
-		stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+		stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	    }
 	}
     } else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
 	stops = new D2D1_GRADIENT_STOP[source_pattern->base.n_stops];
 	for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
 	    cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
 	    stops[i].position = (FLOAT)stop->offset;
-	    stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+	    stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	}
     } else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
 	num_stops += 2;
 	stops = new D2D1_GRADIENT_STOP[num_stops];
 	stops[0].position = 0;
 	stops[0].color = D2D1::ColorF(0, 0);
 	for (unsigned int i = 1; i < source_pattern->base.n_stops + 1; i++) {
 	    cairo_gradient_stop_t *stop = &source_pattern->base.stops[i - 1];
 	    stops[i].position = (FLOAT)stop->offset;
-	    stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
+	    stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
 	}
 	stops[source_pattern->base.n_stops + 1].position = 1.0f;
 	stops[source_pattern->base.n_stops + 1].color = D2D1::ColorF(0, 0);
     }
     RefPtr<ID2D1GradientStopCollection> stopCollection;
     d2dsurf->rt->CreateGradientStopCollection(stops, num_stops, &stopCollection);
     RefPtr<ID2D1LinearGradientBrush> brush;
     d2dsurf->rt->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2D1::Point2F((FLOAT)p1.x, (FLOAT)p1.y),
@@ -2304,28 +2313,38 @@ static cairo_operator_t _cairo_d2d_simpl
 	    if (solidpattern->color.alpha == 1.0) {
 		return CAIRO_OPERATOR_OVER;
 	    }
 	}
     }
     return op;
 }
 
+void
+_cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_device, cairo_format_t format)
+{
+    newSurf->format = format;
+
+    newSurf->device = d2d_device;
+    cairo_addref_device(&d2d_device->base);
+    d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+}
+
 // Implementation
 static cairo_surface_t*
 _cairo_d2d_create_similar(void			*surface,
 			  cairo_content_t	 content,
 			  int			 width,
 			  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)));
     
     new (newSurf) cairo_d2d_surface_t();
-    _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
+    _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
 
 
     D2D1_SIZE_U sizePixels;
     D2D1_SIZE_F size;
     HRESULT hr;
 
     sizePixels.width = width;
     sizePixels.height = height;
@@ -2420,19 +2439,17 @@ static cairo_surface_t*
 	    goto FAIL_CREATESIMILAR;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
-    newSurf->device = d2dsurf->device;
-    cairo_addref_device(&newSurf->device->base);
-    newSurf->device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+    _cairo_d2d_surface_init(newSurf, d2dsurf->device, _cairo_format_from_content(content));
 
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATESIMILAR:
     /** Ensure we call our surfaces desctructor */
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
@@ -2496,18 +2513,18 @@ static cairo_status_t
     d2dsurf->device->mD3D10Device->CopyResource(softTexture, d2dsurf->surface);
 
     D3D10_MAPPED_TEXTURE2D data;
     hr = softTexture->Map(0, D3D10_MAP_READ_WRITE, 0, &data);
     if (FAILED(hr)) {
 	return _cairo_error(CAIRO_STATUS_NO_DEVICE);
     }
     *image_out = 
-	(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
-										  d2dsurf->base.content,
+	(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
+										  d2dsurf->format,
 										  size.width,
 										  size.height,
 										  data.RowPitch);
     *image_extra = softTexture.forget();
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -2568,18 +2585,18 @@ static cairo_status_t
     d2dsurf->device->mD3D10Device->CopyResource(softTexture, d2dsurf->surface);
 
     D3D10_MAPPED_TEXTURE2D data;
     hr = softTexture->Map(0, D3D10_MAP_READ_WRITE, 0, &data);
     if (FAILED(hr)) {
 	return _cairo_error(CAIRO_STATUS_NO_DEVICE);
     }
     *image_out = 
-	(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
-										  d2dsurf->base.content,
+	(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
+										  _cairo_format_from_content(d2dsurf->base.content),
 										  size.width,
 										  size.height,
 										  data.RowPitch);
     *image_extra = softTexture.forget();
 
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -3173,17 +3190,17 @@ static cairo_int_status_t
 	    return status;
 
     bool isSolidAlphaMask = false;
     float solidAlphaValue = 1.0f;
 
     if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
 	cairo_solid_pattern_t *solidPattern =
 	    (cairo_solid_pattern_t*)mask;
-	if (solidPattern->content = CAIRO_CONTENT_ALPHA) {
+	if (_cairo_color_get_content (&solidPattern->color) == CAIRO_CONTENT_ALPHA) {
 	    isSolidAlphaMask = true;
 	    solidAlphaValue = solidPattern->color.alpha;
 	}
     }
 
     cairo_box_t box;
     _cairo_box_from_rectangle(&box, &extents);
 
@@ -3316,19 +3333,19 @@ static cairo_int_status_t
     return CAIRO_INT_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,
+		  const cairo_stroke_style_t	*style,
+		  const cairo_matrix_t	*ctm,
+		  const cairo_matrix_t	*ctm_inverse,
 		  double		 tolerance,
 		  cairo_antialias_t	 antialias,
 		  cairo_clip_t		*clip)
 {
     cairo_int_status_t status;
 
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
 
@@ -3521,17 +3538,22 @@ static cairo_int_status_t
 	if (!brush) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
 	target_rt->FillGeometry(d2dpath, brush);
     }
 
     if (target_rt.get() != d2dsurf->rt.get()) {
 	double x1, y1, x2, y2;
-	_cairo_path_fixed_bounds(path, &x1, &y1, &x2, &y2);
+        cairo_box_t box;
+        _cairo_path_fixed_extents (path, &box);
+        x1 = _cairo_fixed_to_double (box.p1.x);
+        y1 = _cairo_fixed_to_double (box.p1.y);
+        x2 = _cairo_fixed_to_double (box.p2.x);
+        y2 = _cairo_fixed_to_double (box.p2.y);
 	cairo_rectangle_int_t bounds;
 	_cairo_d2d_round_out_to_int_rect(&bounds, x1, y1, x2, y2);
 	return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip, &bounds);
     }
 
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
@@ -4113,26 +4135,28 @@ static cairo_bool_t
     extents->width = size.width;
     extents->height = size.height;
     return TRUE;
 }
 
 
 /** Helper functions. */
 
+
+
 cairo_surface_t*
 cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
 				  HWND wnd,
 				  cairo_content_t content)
 {
     cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(cairo_device);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     new (newSurf) cairo_d2d_surface_t();
 
-    _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
+    _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
 
     RECT rc;
     HRESULT hr;
 
     newSurf->isDrawing = false;
     ::GetClientRect(wnd, &rc);
 
     FLOAT dpiX;
@@ -4224,28 +4248,28 @@ cairo_d2d_surface_create_for_hwnd(cairo_
 
     bitProps = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, 
 				      D2D1_ALPHA_MODE_PREMULTIPLIED));
     
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
-    newSurf->device = d2d_device;
-    cairo_addref_device(cairo_device);
-    d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+    _cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
 
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_HWND:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
+
+
 cairo_surface_t *
 cairo_d2d_surface_create(cairo_device_t *device,
 			 cairo_format_t format,
 			 int width,
 			 int height)
 {
     if (width == 0 || height == 0) {
 	return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE));
@@ -4253,22 +4277,22 @@ cairo_d2d_surface_create(cairo_device_t 
 
     cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     new (newSurf) cairo_d2d_surface_t();
 
     DXGI_FORMAT dxgiformat = DXGI_FORMAT_B8G8R8A8_UNORM;
     D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
     if (format == CAIRO_FORMAT_ARGB32) {
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR_ALPHA);
     } else if (format == CAIRO_FORMAT_RGB24) {
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
 	alpha = D2D1_ALPHA_MODE_IGNORE;
     } else {
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
 	dxgiformat = DXGI_FORMAT_A8_UNORM;
     }
 
 
     newSurf->format = format;
 
     D2D1_SIZE_U sizePixels;
     HRESULT hr;
@@ -4338,19 +4362,17 @@ cairo_d2d_surface_create(cairo_device_t 
 	    goto FAIL_CREATE;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
-    newSurf->device = d2d_device;
-    cairo_addref_device(device);
-    d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+    _cairo_d2d_surface_init(newSurf, d2d_device, format);
 
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATE:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
@@ -4393,26 +4415,26 @@ cairo_d2d_surface_create_for_handle(cair
     format = desc.Format;
     
     D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
     if (format == DXGI_FORMAT_B8G8R8A8_UNORM) {
 	if (content == CAIRO_CONTENT_ALPHA) {
 	    status = CAIRO_STATUS_INVALID_CONTENT;
 	    goto FAIL_CREATEHANDLE;
 	}
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
 	if (content == CAIRO_CONTENT_COLOR) {
 	    alpha = D2D1_ALPHA_MODE_IGNORE;
 	}
     } else if (format == DXGI_FORMAT_A8_UNORM) {
 	if (content != CAIRO_CONTENT_ALPHA) {
 	    status = CAIRO_STATUS_INVALID_CONTENT;
 	    goto FAIL_CREATEHANDLE;
 	}
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
     } else {
 	status = CAIRO_STATUS_INVALID_FORMAT;
 	// We don't know how to support this format!
 	goto FAIL_CREATEHANDLE;
     }
 
     props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
 					 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, alpha));
@@ -4439,19 +4461,17 @@ cairo_d2d_surface_create_for_handle(cair
 
 	if (FAILED(hr)) {
 	    goto FAIL_CREATEHANDLE;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
-    newSurf->device = d2d_device;
-    cairo_addref_device(device);
-    d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+    _cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
 
     return &newSurf->base;
    
 FAIL_CREATEHANDLE:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(status));
 }
@@ -4462,20 +4482,20 @@ cairo_d2d_surface_create_for_texture(cai
 				     cairo_content_t content)
 {
     cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     new (newSurf) cairo_d2d_surface_t();
 
     D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
     if (content == CAIRO_CONTENT_COLOR) {
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
 	alpha = D2D1_ALPHA_MODE_IGNORE;
     } else {
-	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
     }
 
     D2D1_SIZE_U sizePixels;
     HRESULT hr;
 
     D3D10_TEXTURE2D_DESC desc;
     RefPtr<IDXGISurface> dxgiSurface;
     D2D1_BITMAP_PROPERTIES bitProps;
@@ -4522,19 +4542,17 @@ cairo_d2d_surface_create_for_texture(cai
 
 	if (FAILED(hr)) {
 	    goto FAIL_CREATE;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
-    newSurf->device = d2d_device;
-    cairo_addref_device(device);
-    d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
+    _cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
 
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATE:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -72,20 +72,24 @@ cairo_debug_reset_static_data (void)
     _cairo_intern_string_reset_static_data ();
 
     _cairo_scaled_font_reset_static_data ();
 
     _cairo_pattern_reset_static_data ();
 
     _cairo_clip_reset_static_data ();
 
+    _cairo_image_reset_static_data ();
+
 #if CAIRO_HAS_DRM_SURFACE
     _cairo_drm_device_reset_static_data ();
 #endif
 
+    _cairo_reset_static_data ();
+
     CAIRO_MUTEX_FINALIZE ();
 }
 
 #if HAVE_VALGRIND
 void
 _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
 {
     const cairo_image_surface_t *image = (cairo_image_surface_t *) surface;
@@ -101,20 +105,24 @@ void
     bits = image->data;
     switch (image->format) {
     case CAIRO_FORMAT_A1:
 	width = (image->width + 7)/8;
 	break;
     case CAIRO_FORMAT_A8:
 	width = image->width;
 	break;
+    case CAIRO_FORMAT_RGB16_565:
+	width = image->width*2;
+	break;
     case CAIRO_FORMAT_RGB24:
     case CAIRO_FORMAT_ARGB32:
 	width = image->width*4;
 	break;
+    case CAIRO_FORMAT_INVALID:
     default:
 	/* XXX compute width from pixman bpp */
 	return;
     }
 
     for (row = 0; row < image->height; row++) {
 	VALGRIND_CHECK_MEM_IS_DEFINED (bits, width);
 	/* and then silence any future valgrind warnings */
@@ -216,16 +224,22 @@ static cairo_status_t
     return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
 
+    printf ("path: extents=(%f, %f), (%f, %f)\n",
+	    _cairo_fixed_to_double (path->extents.p1.x),
+	    _cairo_fixed_to_double (path->extents.p1.y),
+	    _cairo_fixed_to_double (path->extents.p2.x),
+	    _cairo_fixed_to_double (path->extents.p2.y));
+
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _print_move_to,
 					  _print_line_to,
 					  _print_curve_to,
 					  _print_close,
 					  stream);
     assert (status == CAIRO_STATUS_SUCCESS);
--- a/gfx/cairo/cairo/src/cairo-deflate-stream.c
+++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -30,16 +30,17 @@
  *
  * The Initial Developer of the Original Code is Adrian Johnson.
  *
  * Author(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
 #include "cairo-output-stream-private.h"
 #include <zlib.h>
 
 #define BUFFER_SIZE 16384
 
 typedef struct _cairo_deflate_stream {
     cairo_output_stream_t  base;
     cairo_output_stream_t *output;
--- a/gfx/cairo/cairo/src/cairo-deprecated.h
+++ b/gfx/cairo/cairo/src/cairo-deprecated.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -31,30 +31,16 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  */
 
 #ifndef CAIRO_DEPRECATED_H
 #define CAIRO_DEPRECATED_H
 
-/* The %CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part
- * of fixing cairo's xlib backend to work with X servers advertising a
- * 16-bit, 565 visual. But as it turned out, adding this format to
- * #cairo_format_t was not necessary, and was a mistake, (cairo's xlib
- * backend can work fine with 16-bit visuals in the same way it works
- * with BGR visuals without any BGR formats in
- * #cairo_format_t).
- *
- * Additionally, the support for the RGB16_565 format was never
- * completely implemented. So while this format value is currently
- * deprecated, it may eventually acquire complete support in the future.
- */
-/* #define CAIRO_FORMAT_RGB16_565 4 */
-
 #define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
 
 /* Obsolete functions. These definitions exist to coerce the compiler
  * into providing a little bit of guidance with its error
  * messages. The idea is to help users port their old code without
  * having to dig through lots of documentation.
  *
  * The first set of REPLACED_BY functions is for functions whose names
@@ -118,17 +104,16 @@
 #define cairo_surface_get_matrix	cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix
 #define cairo_surface_set_filter	cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter
 #define cairo_surface_get_filter	cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter
 #define cairo_matrix_create		cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t
 #define cairo_matrix_destroy		cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t
 #define cairo_matrix_copy		cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t
 #define cairo_matrix_get_affine		cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t
 #define cairo_set_target_surface	cairo_set_target_surface_DEPRECATED_BY_cairo_create
-#define cairo_set_target_glitz		cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create
 #define cairo_set_target_image		cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data
 #define cairo_set_target_pdf		cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create
 #define cairo_set_target_png		cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png
 #define cairo_set_target_ps		cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create
 #define cairo_set_target_quartz		cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create
 #define cairo_set_target_win32		cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create
 #define cairo_set_target_xcb		cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create
 #define cairo_set_target_drawable	cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-device-private.h
@@ -0,0 +1,86 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation.
+ *
+ * Contributors(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#ifndef _CAIRO_DEVICE_PRIVATE_H_
+#define _CAIRO_DEVICE_PRIVATE_H_
+
+#include "cairo-compiler-private.h"
+#include "cairo-mutex-private.h"
+#include "cairo-reference-count-private.h"
+#include "cairo-types-private.h"
+
+struct _cairo_device {
+    cairo_reference_count_t ref_count;
+    cairo_status_t status;
+    cairo_user_data_array_t user_data;
+
+    const cairo_device_backend_t *backend;
+
+    cairo_recursive_mutex_t mutex;
+    unsigned mutex_depth;
+
+    cairo_bool_t finished;
+};
+
+struct _cairo_device_backend {
+    cairo_device_type_t type;
+
+    void (*lock) (void *device);
+    void (*unlock) (void *device);
+
+    cairo_warn cairo_status_t (*flush) (void *device);
+    void (*finish) (void *device);
+    void (*destroy) (void *device);
+};
+
+cairo_private cairo_device_t *
+_cairo_device_create_in_error (cairo_status_t status);
+
+cairo_private void
+_cairo_device_init (cairo_device_t *device,
+		    const cairo_device_backend_t *backend);
+
+cairo_private cairo_status_t
+_cairo_device_set_error (cairo_device_t *device,
+		         cairo_status_t error);
+
+slim_hidden_proto_no_warn (cairo_device_reference);
+slim_hidden_proto (cairo_device_acquire);
+slim_hidden_proto (cairo_device_release);
+slim_hidden_proto (cairo_device_flush);
+slim_hidden_proto (cairo_device_finish);
+slim_hidden_proto (cairo_device_destroy);
+
+#endif /* _CAIRO_DEVICE_PRIVATE_H_ */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-device.c
@@ -0,0 +1,533 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation.
+ *
+ * Contributors(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+#include "cairo-device-private.h"
+#include "cairo-error-private.h"
+
+/**
+ * SECTION:cairo-device
+ * @Title: cairo_device_t
+ * @Short_Description: interface to underlying rendering system
+ * @See_Also: #cairo_surface_t
+ *
+ * Devices are the abstraction Cairo employs for the rendering system
+ * used by a #cairo_surface_t. You can get the device of a surface using
+ * cairo_surface_get_device().
+ *
+ * Devices are created using custom functions specific to the rendering
+ * system you want to use. See the documentation for the surface types
+ * for those functions.
+ *
+ * An important function that devices fulfill is sharing access to the
+ * rendering system between Cairo and your application. If you want to
+ * access a device directly that you used to draw to with Cairo, you must
+ * first call cairo_device_flush() to ensure that Cairo finishes all
+ * operations on the device and resets it to a clean state.
+ *
+ * Cairo also provides the functions cairo_device_acquire() and
+ * cairo_device_release() to synchronize access to the rendering system
+ * in a multithreaded environment. This is done internally, but can also
+ * be used by applications.
+ *
+ * Putting this all together, a function that works with devices should
+ * look something like this:
+ * <informalexample><programlisting>
+ * void
+ * my_device_modifying_function (cairo_device_t *device)
+ * {
+ *   cairo_status_t status;
+ *
+ *   // Ensure the device is properly reset
+ *   cairo_device_flush (device);
+ *   // Try to acquire the device
+ *   status = cairo_device_acquire (device);
+ *   if (status != CAIRO_STATUS_SUCCESS) {
+ *     printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
+ *     return;
+ *   }
+ *
+ *   // Do the custom operations on the device here.
+ *   // But do not call any Cairo functions that might acquire devices.
+ *   
+ *   // Release the device when done.
+ *   cairo_device_release (device);
+ * }
+ * </programlisting></informalexample>
+ *
+ * <note><para>Please refer to the documentation of each backend for
+ * additional usage requirements, guarantees provided, and
+ * interactions with existing surface API of the device functions for
+ * surfaces of that type.
+ * </para></note>
+ */
+
+static const cairo_device_t _nil_device = {
+    CAIRO_REFERENCE_COUNT_INVALID,
+    CAIRO_STATUS_NO_MEMORY,
+};
+
+static const cairo_device_t _mismatch_device = {
+    CAIRO_REFERENCE_COUNT_INVALID,
+    CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
+};
+
+static const cairo_device_t _invalid_device = {
+    CAIRO_REFERENCE_COUNT_INVALID,
+    CAIRO_STATUS_DEVICE_ERROR,
+};
+
+cairo_device_t *
+_cairo_device_create_in_error (cairo_status_t status)
+{
+    switch (status) {
+    case CAIRO_STATUS_NO_MEMORY:
+	return (cairo_device_t *) &_nil_device;
+    case CAIRO_STATUS_DEVICE_ERROR:
+	return (cairo_device_t *) &_invalid_device;
+    case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
+	return (cairo_device_t *) &_mismatch_device;
+
+    case CAIRO_STATUS_SUCCESS:
+    case CAIRO_STATUS_LAST_STATUS:
+	ASSERT_NOT_REACHED;
+	/* fall-through */
+    case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
+    case CAIRO_STATUS_INVALID_STATUS:
+    case CAIRO_STATUS_INVALID_FORMAT:
+    case CAIRO_STATUS_INVALID_VISUAL:
+    case CAIRO_STATUS_READ_ERROR:
+    case CAIRO_STATUS_WRITE_ERROR:
+    case CAIRO_STATUS_FILE_NOT_FOUND:
+    case CAIRO_STATUS_TEMP_FILE_ERROR:
+    case CAIRO_STATUS_INVALID_STRIDE:
+    case CAIRO_STATUS_INVALID_SIZE:
+    case CAIRO_STATUS_INVALID_RESTORE:
+    case CAIRO_STATUS_INVALID_POP_GROUP:
+    case CAIRO_STATUS_NO_CURRENT_POINT:
+    case CAIRO_STATUS_INVALID_MATRIX:
+    case CAIRO_STATUS_NULL_POINTER:
+    case CAIRO_STATUS_INVALID_STRING:
+    case CAIRO_STATUS_INVALID_PATH_DATA:
+    case CAIRO_STATUS_SURFACE_FINISHED:
+    case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
+    case CAIRO_STATUS_INVALID_DASH:
+    case CAIRO_STATUS_INVALID_DSC_COMMENT:
+    case CAIRO_STATUS_INVALID_INDEX:
+    case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
+    case CAIRO_STATUS_FONT_TYPE_MISMATCH:
+    case CAIRO_STATUS_USER_FONT_IMMUTABLE:
+    case CAIRO_STATUS_USER_FONT_ERROR:
+    case CAIRO_STATUS_NEGATIVE_COUNT:
+    case CAIRO_STATUS_INVALID_CLUSTERS:
+    case CAIRO_STATUS_INVALID_SLANT:
+    case CAIRO_STATUS_INVALID_WEIGHT:
+    case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
+    case CAIRO_STATUS_INVALID_CONTENT:
+    default:
+	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_device_t *) &_nil_device;
+    }
+}
+
+void
+_cairo_device_init (cairo_device_t *device,
+		    const cairo_device_backend_t *backend)
+{
+    CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
+    device->status = CAIRO_STATUS_SUCCESS;
+
+    device->backend = backend;
+
+    CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
+    device->mutex_depth = 0;
+
+    device->finished = FALSE;
+
+    _cairo_user_data_array_init (&device->user_data);
+}
+
+/**
+ * cairo_device_reference:
+ * @device: a #cairo_device_t
+ *
+ * Increases the reference count on @device by one. This prevents
+ * @device from being destroyed until a matching call to
+ * cairo_device_destroy() is made.
+ *
+ * The number of references to a #cairo_device_t can be get using
+ * cairo_device_get_reference_count().
+ *
+ * Return value: the referenced #cairo_device_t.
+ *
+ * Since: 1.10
+ **/
+cairo_device_t *
+cairo_device_reference (cairo_device_t *device)
+{
+    if (device == NULL ||
+	CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+    {
+	return device;
+    }
+
+    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
+    _cairo_reference_count_inc (&device->ref_count);
+
+    return device;
+}
+slim_hidden_def (cairo_device_reference);
+
+/**
+ * cairo_device_status:
+ * @device: a #cairo_device_t
+ *
+ * Checks whether an error has previously occurred for this
+ * device.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
+ *               the device is in an error state.
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_device_status (cairo_device_t *device)
+{
+    if (device == NULL)
+	return CAIRO_STATUS_NULL_POINTER;
+
+    return device->status;
+}
+
+/**
+ * cairo_device_flush:
+ * @device: a #cairo_device_t
+ *
+ * Finish any pending operations for the device and also restore any
+ * temporary modifications cairo has made to the device's state.
+ * This function must be called before switching from using the 
+ * device with Cairo to operating on it directly with native APIs.
+ * If the device doesn't support direct access, then this function
+ * does nothing.
+ *
+ * This function may acquire devices.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_device_flush (cairo_device_t *device)
+{
+    cairo_status_t status;
+
+    if (device == NULL || device->status)
+	return;
+
+    if (device->backend->flush != NULL) {
+	status = device->backend->flush (device);
+	if (unlikely (status))
+	    status = _cairo_device_set_error (device, status);
+    }
+}
+slim_hidden_def (cairo_device_flush);
+
+/**
+ * cairo_device_finish:
+ * @device: the #cairo_device_t to finish
+ *
+ * This function finishes the device and drops all references to
+ * external resources. All surfaces, fonts and other objects created
+ * for this @device will be finished, too.
+ * Further operations on the @device will not affect the @device but
+ * will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
+ *
+ * When the last call to cairo_device_destroy() decreases the
+ * reference count to zero, cairo will call cairo_device_finish() if
+ * it hasn't been called already, before freeing the resources
+ * associated with the device.
+ *
+ * This function may acquire devices.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_device_finish (cairo_device_t *device)
+{
+    if (device == NULL ||
+	CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+    {
+	return;
+    }
+
+    if (device->finished)
+	return;
+
+    cairo_device_flush (device);
+
+    device->finished = TRUE;
+
+    if (device->backend->finish != NULL)
+	device->backend->finish (device);
+}
+slim_hidden_def (cairo_device_finish);
+
+/**
+ * cairo_device_destroy:
+ * @device: a #cairo_device_t
+ *
+ * Decreases the reference count on @device by one. If the result is
+ * zero, then @device and all associated resources are freed.  See
+ * cairo_device_reference().
+ *
+ * This function may acquire devices if the last reference was dropped.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_device_destroy (cairo_device_t *device)
+{
+    cairo_user_data_array_t user_data;
+
+    if (device == NULL ||
+	CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+    {
+	return;
+    }
+
+    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
+    if (! _cairo_reference_count_dec_and_test (&device->ref_count))
+	return;
+
+    cairo_device_finish (device);
+
+    assert (device->mutex_depth == 0);
+    CAIRO_MUTEX_FINI (device->mutex);
+
+    user_data = device->user_data;
+
+    device->backend->destroy (device);
+
+    _cairo_user_data_array_fini (&user_data);
+
+}
+slim_hidden_def (cairo_device_destroy);
+
+/**
+ * cairo_device_get_type:
+ * @device: a #cairo_device_t
+ *
+ * This function returns the type of the device. See #cairo_device_type_t
+ * for available types.
+ *
+ * Return value: The type of @device.
+ *
+ * Since: 1.10
+ **/
+cairo_device_type_t
+cairo_device_get_type (cairo_device_t *device)
+{
+    if (device == NULL ||
+	CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+    {
+	return (cairo_device_type_t) -1;
+    }
+
+    return device->backend->type;
+}
+
+/**
+ * cairo_device_acquire:
+ * @device: a #cairo_device_t
+ *
+ * Acquires the @device for the current thread. This function will block
+ * until no other thread has acquired the device.
+ *
+ * If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
+ * device. From now on your thread owns the device and no other thread will be
+ * able to acquire it until a matching call to cairo_device_release(). It is
+ * allowed to recursively acquire the device multiple times from the same
+ * thread.
+ *
+ * <note><para>You must never acquire two different devices at the same time
+ * unless this is explicitly allowed. Otherwise the possibility of deadlocks
+ * exist.
+ *
+ * As various Cairo functions can acquire devices when called, these functions
+ * may also cause deadlocks when you call them with an acquired device. So you
+ * must not have a device acquired when calling them. These functions are
+ * marked in the documentation.
+ * </para></note>
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
+ *               the device is in an error state and could not be
+ *               acquired. After a successful call to cairo_device_acquire(),
+ *               a matching call to cairo_device_release() is required.
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_device_acquire (cairo_device_t *device)
+{
+    if (device == NULL)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (unlikely (device->status))
+	return device->status;
+
+    if (unlikely (device->finished))
+	return _cairo_device_set_error (device, CAIRO_STATUS_SURFACE_FINISHED); /* XXX */
+
+    CAIRO_MUTEX_LOCK (device->mutex);
+    if (device->mutex_depth++ == 0) {
+	if (device->backend->lock != NULL)
+	    device->backend->lock (device);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+slim_hidden_def (cairo_device_acquire);
+
+/**
+ * cairo_device_release:
+ * @device: a #cairo_device_t
+ *
+ * Releases a @device previously acquired using cairo_device_acquire(). See
+ * that function for details.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_device_release (cairo_device_t *device)
+{
+    if (device == NULL)
+	return;
+
+    assert (device->mutex_depth > 0);
+
+    if (--device->mutex_depth == 0) {
+	if (device->backend->unlock != NULL)
+	    device->backend->unlock (device);
+    }
+
+    CAIRO_MUTEX_UNLOCK (device->mutex);
+}
+slim_hidden_def (cairo_device_release);
+
+cairo_status_t
+_cairo_device_set_error (cairo_device_t *device,
+			 cairo_status_t  status)
+{
+    if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    /* Don't overwrite an existing error. This preserves the first
+     * error, which is the most significant. */
+    _cairo_status_set_error (&device->status, status);
+
+    return _cairo_error (status);
+}
+
+/**
+ * cairo_device_get_reference_count:
+ * @device: a #cairo_device_t
+ *
+ * Returns the current reference count of @device.
+ *
+ * Return value: the current reference count of @device.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.10
+ **/
+unsigned int
+cairo_device_get_reference_count (cairo_device_t *device)
+{
+    if (device == NULL ||
+	CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+	return 0;
+
+    return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
+}
+
+/**
+ * cairo_device_get_user_data:
+ * @device: a #cairo_device_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @device using the
+ * specified key.  If no user data has been attached with the given
+ * key this function returns %NULL.
+ *
+ * Return value: the user data previously attached or %NULL.
+ *
+ * Since: 1.10
+ **/
+void *
+cairo_device_get_user_data (cairo_device_t		 *device,
+			    const cairo_user_data_key_t *key)
+{
+    return _cairo_user_data_array_get_data (&device->user_data,
+					    key);
+}
+
+/**
+ * cairo_device_set_user_data:
+ * @device: a #cairo_device_t
+ * @key: the address of a #cairo_user_data_key_t to attach the user data to
+ * @user_data: the user data to attach to the #cairo_device_t
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * #cairo_t is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @device.  To remove user data from a surface,
+ * call this function with the key that was used to set it and %NULL
+ * for @data.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
+ * slot could not be allocated for the user data.
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_device_set_user_data (cairo_device_t		 *device,
+			    const cairo_user_data_key_t *key,
+			    void			 *user_data,
+			    cairo_destroy_func_t	  destroy)
+{
+    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
+	return device->status;
+
+    return _cairo_user_data_array_set_data (&device->user_data,
+					    key, user_data, destroy);
+}
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -34,16 +34,17 @@
  *    Michael Emmel <mike.emmel@gmail.com>
  *    Claudio Ciccani <klan@users.sf.net>
  */
 
 #include "cairoint.h"
 #include "cairo-directfb.h"
 
 #include "cairo-clip-private.h"
+#include "cairo-error-private.h"
 
 #include <pixman.h>
 
 #include <directfb.h>
 #include <direct/types.h>
 #include <direct/debug.h>
 #include <direct/memcpy.h>
 #include <direct/util.h>
@@ -559,16 +560,17 @@ static cairo_surface_t *
 	if (status) {
 	    free (surface);
 	    return _cairo_surface_create_in_error (status);
 	}
     }
 
     _cairo_surface_init (&surface->base,
 			 &_cairo_directfb_surface_backend,
+			 NULL, /* device */
 			 content);
     surface->pixman_format = _directfb_to_pixman_format (format);
     surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
 
     surface->width   = width;
     surface->height  = height;
     surface->local   = TRUE;
     surface->blit_premultiplied = TRUE;
@@ -757,24 +759,24 @@ static cairo_status_t
 						 width, height,
 						 data, pitch);
 	if (unlikely (pixman_image == NULL)) {
 	    DirectFBError ("IDirectFBSurface::Lock()", ret);
 	    cairo_surface_destroy (&clone->base);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
 
-	pixman_image_composite (PIXMAN_OP_SRC,
-				image_src->pixman_image,
-				NULL,
-				pixman_image,
-				src_x, src_y,
-				0, 0,
-				0, 0,
-				width, height);
+	pixman_image_composite32 (PIXMAN_OP_SRC,
+                                  image_src->pixman_image,
+                                  NULL,
+                                  pixman_image,
+                                  src_x, src_y,
+                                  0, 0,
+                                  0, 0,
+                                  width, height);
 
 	pixman_image_unref (pixman_image);
 
 	clone->dfbsurface->Unlock (clone->dfbsurface);
 
 	*clone_offset_x = src_x;
 	*clone_offset_y = src_y;
 	*clone_out = &clone->base;
@@ -1809,17 +1811,17 @@ static cairo_int_status_t
 					     cache->dfbsurface, rects, points, num));
 
     return CAIRO_STATUS_SUCCESS;
 }
 #endif /* DFB_SHOW_GLYPHS */
 
 
 static cairo_bool_t
-_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
+_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
 {
     cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
     cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
 
     return a->dfb == b->dfb;
 }
 
 static cairo_surface_backend_t
@@ -1950,12 +1952,13 @@ cairo_directfb_surface_create (IDirectFB
     surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
 
     dfbsurface->GetCapabilities (dfbsurface, &caps);
     if (caps & DSCAPS_PREMULTIPLIED)
 	surface->blit_premultiplied = TRUE;
 
     _cairo_surface_init (&surface->base,
                          &_cairo_directfb_surface_backend,
+			 NULL, /* device */
 			 _directfb_format_to_content (format));
 
     return &surface->base;
 }
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-drm.h
+++ b/gfx/cairo/cairo/src/cairo-drm.h
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -34,66 +34,51 @@
 #define CAIRO_DRM_H
 
 #include "cairo.h"
 
 #if CAIRO_HAS_DRM_SURFACE
 
 CAIRO_BEGIN_DECLS
 
-typedef struct _cairo_drm_device cairo_drm_device_t;
-
 struct udev_device;
 
-cairo_public cairo_drm_device_t *
+cairo_public cairo_device_t *
 cairo_drm_device_get (struct udev_device *device);
 
-cairo_public cairo_drm_device_t *
+cairo_public cairo_device_t *
 cairo_drm_device_get_for_fd (int fd);
 
-cairo_public cairo_drm_device_t *
+cairo_public cairo_device_t *
 cairo_drm_device_default (void);
 
-cairo_public cairo_drm_device_t *
-cairo_drm_device_reference (cairo_drm_device_t *device);
-
-cairo_public cairo_status_t
-cairo_drm_device_status (cairo_drm_device_t *device);
-
 cairo_public int
-cairo_drm_device_get_fd (cairo_drm_device_t *device);
+cairo_drm_device_get_fd (cairo_device_t *device);
 
 cairo_public void
-cairo_drm_device_throttle (cairo_drm_device_t *device);
-
-cairo_public void
-cairo_drm_device_destroy (cairo_drm_device_t *device);
-
+cairo_drm_device_throttle (cairo_device_t *device);
 
 cairo_public cairo_surface_t *
-cairo_drm_surface_create (cairo_drm_device_t *device,
-			  cairo_content_t content,
+cairo_drm_surface_create (cairo_device_t *device,
+			  cairo_format_t format,
 			  int width, int height);
 
 cairo_public cairo_surface_t *
-cairo_drm_surface_create_for_name (cairo_drm_device_t *device,
+cairo_drm_surface_create_for_name (cairo_device_t *device,
 				   unsigned int name,
 	                           cairo_format_t format,
 				   int width, int height, int stride);
 
 cairo_public cairo_surface_t *
-cairo_drm_surface_create_from_cacheable_image (cairo_drm_device_t *device,
+cairo_drm_surface_create_from_cacheable_image (cairo_device_t *device,
 	                                       cairo_surface_t *surface);
 
 cairo_public cairo_status_t
 cairo_drm_surface_enable_scan_out (cairo_surface_t *surface);
 
-cairo_public cairo_drm_device_t *
-cairo_drm_surface_get_device (cairo_surface_t *abstract_surface);
-
 cairo_public unsigned int
 cairo_drm_surface_get_handle (cairo_surface_t *surface);
 
 cairo_public unsigned int
 cairo_drm_surface_get_name (cairo_surface_t *surface);
 
 cairo_public cairo_format_t
 cairo_drm_surface_get_format (cairo_surface_t *surface);
@@ -115,17 +100,17 @@ cairo_drm_surface_get_stride (cairo_surf
  *   from the GPU, maps it into the CPU domain and gives you direct access to
  *   the pixels.  With the unmap(), the buffer is ready to be used again by the
  *   GPU and *until* the unmap(), all operations will be done in software.
  *
  *  (Technically calling cairo_surface_flush() on the underlying drm-surface
  *  will also disassociate the mapping.)
 */
 cairo_public cairo_surface_t *
-cairo_drm_surface_map (cairo_surface_t *surface);
+cairo_drm_surface_map_to_image (cairo_surface_t *surface);
 
 cairo_public void
 cairo_drm_surface_unmap (cairo_surface_t *drm_surface,
 	                 cairo_surface_t *image_surface);
 
 CAIRO_END_DECLS
 
 #else  /* CAIRO_HAS_DRM_SURFACE */
--- a/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
+++ b/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
@@ -29,23 +29,22 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is the Mozilla Foundation
  *
  * Contributor(s):
  *	Bas Schouten <bschouten@mozilla.com>
  */
 
-extern "C" {
 #include "cairoint.h"
 
 #include "cairo-win32-private.h"
 #include "cairo-surface-private.h"
 #include "cairo-clip-private.h"
-}
+
 #include "cairo-d2d-private.h"
 #include "cairo-dwrite-private.h"
 #include <float.h>
 
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     __in D2D1_FACTORY_TYPE factoryType,
     __in REFIID iid,
     __in_opt CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-error-private.h
@@ -0,0 +1,60 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth@cworth.org>
+ */
+
+#ifndef _CAIRO_ERROR_PRIVATE_H_
+#define _CAIRO_ERROR_PRIVATE_H_
+
+#include "cairo.h"
+#include "cairo-compiler-private.h"
+
+CAIRO_BEGIN_DECLS
+
+#define _cairo_status_is_error(status) \
+    (status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
+
+cairo_private cairo_status_t
+_cairo_error (cairo_status_t status);
+
+/* hide compiler warnings when discarding the return value */
+#define _cairo_error_throw(status) do { \
+    cairo_status_t status__ = _cairo_error (status); \
+    (void) status__; \
+} while (0)
+
+CAIRO_END_DECLS
+
+#endif /* _CAIRO_ERROR_PRIVATE_H_ */
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -84,12 +84,14 @@
 @WIN32_FONT_FEATURE@
 
 @WIN32_DWRITE_FONT_FEATURE@
 
 @WIN32_D2D_SURFACE_FEATURE@
 
 @QUARTZ_FONT_FEATURE@
 
+@TEE_SURFACE_FEATURE@
+
 @PNG_FUNCTIONS_FEATURE@
 
 @FC_FONT_FEATURE@
 #endif
--- a/gfx/cairo/cairo/src/cairo-fixed-private.h
+++ b/gfx/cairo/cairo/src/cairo-fixed-private.h
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -48,17 +48,17 @@
 # error To remove this limitation, you will have to fix the tesselator.
 #endif
 
 #define CAIRO_FIXED_ONE        ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
 #define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
 #define CAIRO_FIXED_ONE_FLOAT  ((float)(1 << CAIRO_FIXED_FRAC_BITS))
 #define CAIRO_FIXED_EPSILON    ((cairo_fixed_t)(1))
 
-#define CAIRO_FIXED_FRAC_MASK  (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))
+#define CAIRO_FIXED_FRAC_MASK  ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
 #define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
 
 static inline cairo_fixed_t
 _cairo_fixed_from_int (int i)
 {
     return i << CAIRO_FIXED_FRAC_BITS;
 }
 
@@ -131,16 +131,26 @@ static inline cairo_fixed_t
 {
 #if CAIRO_FIXED_FRAC_BITS > 6
     return i << (CAIRO_FIXED_FRAC_BITS - 6);
 #else
     return i >> (6 - CAIRO_FIXED_FRAC_BITS);
 #endif
 }
 
+static inline cairo_fixed_t
+_cairo_fixed_from_16_16 (uint32_t i)
+{
+#if CAIRO_FIXED_FRAC_BITS > 16
+    return i << (CAIRO_FIXED_FRAC_BITS - 16);
+#else
+    return i >> (16 - CAIRO_FIXED_FRAC_BITS);
+#endif
+}
+
 static inline double
 _cairo_fixed_to_double (cairo_fixed_t f)
 {
     return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
 }
 
 static inline float
 _cairo_fixed_to_float (cairo_fixed_t f)
@@ -149,23 +159,59 @@ static inline float
 }
 
 static inline int
 _cairo_fixed_is_integer (cairo_fixed_t f)
 {
     return (f & CAIRO_FIXED_FRAC_MASK) == 0;
 }
 
+static inline cairo_fixed_t
+_cairo_fixed_floor (cairo_fixed_t f)
+{
+    return f & ~CAIRO_FIXED_FRAC_MASK;
+}
+
+static inline cairo_fixed_t
+_cairo_fixed_round (cairo_fixed_t f)
+{
+    return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
+}
+
+static inline cairo_fixed_t
+_cairo_fixed_round_down (cairo_fixed_t f)
+{
+    return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
+}
+
 static inline int
 _cairo_fixed_integer_part (cairo_fixed_t f)
 {
     return f >> CAIRO_FIXED_FRAC_BITS;
 }
 
 static inline int
+_cairo_fixed_integer_round (cairo_fixed_t f)
+{
+    return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
+}
+
+static inline int
+_cairo_fixed_integer_round_down (cairo_fixed_t f)
+{
+    return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
+}
+
+static inline int
+_cairo_fixed_fractional_part (cairo_fixed_t f)
+{
+    return f & CAIRO_FIXED_FRAC_MASK;
+}
+
+static inline int
 _cairo_fixed_integer_floor (cairo_fixed_t f)
 {
     if (f >= 0)
         return f >> CAIRO_FIXED_FRAC_BITS;
     else
         return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1;
 }
 
@@ -220,22 +266,28 @@ static inline cairo_fixed_16_16_t
 #ifdef FLOAT_WORDS_BIGENDIAN
     return u.i[1];
 #else
     return u.i[0];
 #endif
 }
 
 static inline int
-_cairo_fixed_16_16_floor (cairo_fixed_t f)
+_cairo_fixed_16_16_floor (cairo_fixed_16_16_t f)
 {
     if (f >= 0)
-        return f >> 16;
+	return f >> 16;
     else
-        return -((-f - 1) >> 16) - 1;
+	return -((-f - 1) >> 16) - 1;
+}
+
+static inline double
+_cairo_fixed_16_16_to_double (cairo_fixed_16_16_t f)
+{
+    return ((double) f) / (double) (1 << 16);
 }
 
 #if CAIRO_FIXED_BITS == 32
 
 static inline cairo_fixed_t
 _cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
 {
     cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
--- a/gfx/cairo/cairo/src/cairo-fixed-type-private.h
+++ b/gfx/cairo/cairo/src/cairo-fixed-type-private.h
@@ -8,17 +8,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-fixed.c
+++ b/gfx/cairo/cairo/src/cairo-fixed.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
--- a/gfx/cairo/cairo/src/cairo-font-face-twin.c
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -30,16 +30,17 @@
  * The Initial Developer of the Original Code is Keith Packard
  *
  * Contributor(s):
  *      Keith Packard <keithp@keithp.com>
  *      Behdad Esfahbod <behdad@behdad.org>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
 
 #include <math.h>
 
 /*
  * This file implements a user-font rendering the descendant of the Hershey
  * font coded by Keith Packard for use in the Twin window system.
  * The actual font data is in cairo-font-face-twin-data.c
  *
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -9,17 +9,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -34,16 +34,34 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth@cworth.org>
  *      Graydon Hoare <graydon@redhat.com>
  *      Owen Taylor <otaylor@redhat.com>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
+
+/**
+ * SECTION:cairo-font-face
+ * @Title: cairo_font_face_t
+ * @Short_Description: Base class for font faces
+ * @See_Also: #cairo_scaled_font_t
+ *
+ * #cairo_font_face_t represents a particular font at a particular weight,
+ * slant, and other characteristic but no size, transformation, or size.
+ * 
+ * Font faces are created using <firstterm>font-backend</firstterm>-specific
+ * constructors, typically of the form
+ * cairo_<emphasis>backend</emphasis>_font_face_create(), or implicitly
+ * using the <firstterm>toy</firstterm> text API by way of 
+ * cairo_select_font_face().  The resulting face can be accessed using
+ * cairo_get_font_face().
+ */
 
 /* #cairo_font_face_t */
 
 const cairo_font_face_t _cairo_font_face_nil = {
     { 0 },				/* hash_entry */
     CAIRO_STATUS_NO_MEMORY,		/* status */
     CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
     { 0, 0, 0, NULL },			/* user_data */
--- a/gfx/cairo/cairo/src/cairo-font-options.c
+++ b/gfx/cairo/cairo/src/cairo-font-options.c
@@ -7,17 +7,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -30,47 +30,66 @@
  * The Initial Developer of the Original Code is University of Southern
  * California.
  *
  * Contributor(s):
  *      Owen Taylor <otaylor@redhat.com>
  */
 
 #include "cairoint.h"
+#include "cairo-error-private.h"
+
+/**
+ * SECTION:cairo-font-options
+ * @Title: cairo_font_options_t
+ * @Short_Description: How a font should be rendered
+ * @See_Also: #cairo_scaled_font_t
+ *
+ * The font options specify how fonts should be rendered.  Most of the 
+ * time the font options implied by a surface are just right and do not 
+ * need any changes, but for pixel-based targets tweaking font options 
+ * may result in superior output on a particular display.
+ */
 
 static const cairo_font_options_t _cairo_font_options_nil = {
     CAIRO_ANTIALIAS_DEFAULT,
     CAIRO_SUBPIXEL_ORDER_DEFAULT,
+    CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_HINT_STYLE_DEFAULT,
-    CAIRO_HINT_METRICS_DEFAULT
+    CAIRO_HINT_METRICS_DEFAULT,
+    CAIRO_ROUND_GLYPH_POS_DEFAULT
 };
 
 /**
  * _cairo_font_options_init_default:
  * @options: a #cairo_font_options_t
  *
  * Initializes all fields of the font options object to default values.
  **/
 void
 _cairo_font_options_init_default (cairo_font_options_t *options)
 {
     options->antialias = CAIRO_ANTIALIAS_DEFAULT;
     options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
     options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
     options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
+    options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT;
 }
 
 void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other)
 {
     options->antialias = other->antialias;
     options->subpixel_order = other->subpixel_order;
+    options->lcd_filter = other->lcd_filter;
     options->hint_style = other->hint_style;
     options->hint_metrics = other->hint_metrics;
+    options->round_glyph_positions = other->round_glyph_positions;
 }
 
 /**
  * cairo_font_options_create:
  *
  * Allocates a new font options object with all options initialized
  *  to default values.
  *
@@ -184,20 +203,24 @@ cairo_font_options_merge (cairo_font_opt
 
     if (cairo_font_options_status ((cairo_font_options_t *) other))
 	return;
 
     if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
 	options->antialias = other->antialias;
     if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
 	options->subpixel_order = other->subpixel_order;
+    if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
+	options->lcd_filter = other->lcd_filter;
     if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
 	options->hint_style = other->hint_style;
     if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
 	options->hint_metrics = other->hint_metrics;
+    if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT)
+	options->round_glyph_positions = other->round_glyph_positions;
 }
 slim_hidden_def (cairo_font_options_merge);
 
 /**
  * cairo_font_options_equal:
  * @options: a #cairo_font_options_t
  * @other: another #cairo_font_options_t
  *
@@ -216,18 +239,20 @@ cairo_font_options_equal (const cairo_fo
     if (cairo_font_options_status ((cairo_font_options_t *) other))
 	return FALSE;
 
     if (options == other)
 	return TRUE;
 
     return (options->antialias == other->antialias &&
 	    options->subpixel_order == other->subpixel_order &&
+	    options->lcd_filter == other->lcd_filter &&
 	    options->hint_style == other->hint_style &&
-	    options->hint_metrics == other->hint_metrics);
+	    options->hint_metrics == other->hint_metrics &&
+	    options->round_glyph_positions == other->round_glyph_positions);
 }
 slim_hidden_def (cairo_font_options_equal);
 
 /**
  * cairo_font_options_hash:
  * @options: a #cairo_font_options_t
  *
  * Compute a hash for the font options object; this value will
@@ -241,17 +266,18 @@ slim_hidden_def (cairo_font_options_equa
 unsigned long
 cairo_font_options_hash (const cairo_font_options_t *options)
 {
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	options = &_cairo_font_options_nil; /* force default values */
 
     return ((options->antialias) |
 	    (options->subpixel_order << 4) |
-	    (options->hint_style << 8) |
+	    (options->lcd_filter << 8) |
+	    (options->hint_style << 12) |
 	    (options->hint_metrics << 16));
 }
 slim_hidden_def (cairo_font_options_hash);
 
 /**
  * cairo_font_options_set_antialias:
  * @options: a #cairo_font_options_t
  * @antialias: the new antialiasing mode
@@ -323,16 +349,97 @@ cairo_font_options_get_subpixel_order (c
 {
     if (cairo_font_options_status ((cairo_font_options_t *) options))
 	return CAIRO_SUBPIXEL_ORDER_DEFAULT;
 
     return options->subpixel_order;
 }
 
 /**
+ * _cairo_font_options_set_lcd_filter:
+ * @options: a #cairo_font_options_t
+ * @lcd_filter: the new LCD filter
+ *
+ * Sets the LCD filter for the font options object. The LCD filter
+ * specifies how pixels are filtered when rendered with an antialiasing
+ * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
+ * #cairo_lcd_filter_t for full details.
+ *
+ * Since: 1.8
+ **/
+void
+_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
+				    cairo_lcd_filter_t    lcd_filter)
+{
+    if (cairo_font_options_status (options))
+	return;
+
+    options->lcd_filter = lcd_filter;
+}
+
+/**
+ * _cairo_font_options_get_lcd_filter:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the LCD filter for the font options object.
+ * See the documentation for #cairo_lcd_filter_t for full details.
+ *
+ * Return value: the LCD filter for the font options object
+ *
+ * Since: 1.8
+ **/
+cairo_lcd_filter_t
+_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
+{
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_LCD_FILTER_DEFAULT;
+
+    return options->lcd_filter;
+}
+
+/**
+ * _cairo_font_options_set_round_glyph_positions:
+ * @options: a #cairo_font_options_t
+ * @round: the new rounding value
+ *
+ * Sets the rounding options for the font options object. If rounding is set, a
+ * glyph's position will be rounded to integer values.
+ *
+ * Since: 1.12
+ **/
+void
+_cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
+					       cairo_round_glyph_positions_t  round)
+{
+    if (cairo_font_options_status (options))
+	return;
+
+    options->round_glyph_positions = round;
+}
+
+/**
+ * _cairo_font_options_get_round_glyph_positions:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the glyph position rounding option for the font options object.
+ *
+ * Return value: The round glyph posistions flag for the font options object.
+ *
+ * Since: 1.12
+ **/
+cairo_round_glyph_positions_t
+_cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *options)
+{
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_ROUND_GLYPH_POS_DEFAULT;
+
+    return options->round_glyph_positions;
+}
+
+/**
  * cairo_font_options_set_hint_style:
  * @options: a #cairo_font_options_t
  * @hint_style: the new hint style
  *
  * Sets the hint style for font outlines for the font options object.
  * This controls whether to fit font outlines to the pixel grid,
  * and if so, whether to optimize for fidelity or contrast.
  * See the documentation for #cairo_hint_style_t for full details.
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-fontconfig-private.h
@@ -0,0 +1,78 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2000 Keith Packard
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
+ *
+ * Contributor(s):
+ *      Graydon Hoare <graydon@redhat.com>
+ *	Owen Taylor <otaylor@redhat.com>
+ *      Keith Packard <keithp@keithp.com>
+ *      Carl Worth <cworth@cworth.org>
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#ifndef _CAIRO_FONTCONFIG_PRIVATE_H
+#define _CAIRO_FONTCONFIG_PRIVATE_H
+
+#include "cairo.h"
+
+#if CAIRO_HAS_FC_FONT
+#include <fontconfig/fontconfig.h>
+#include <fontconfig/fcfreetype.h>
+#endif
+
+/* sub-pixel order */
+#ifndef FC_RGBA_UNKNOWN
+#define FC_RGBA_UNKNOWN	    0
+#define FC_RGBA_RGB	    1
+#define FC_RGBA_BGR	    2
+#define FC_RGBA_VRGB	    3
+#define FC_RGBA_VBGR	    4
+#define FC_RGBA_NONE	    5
+#endif
+
+/* hinting style */
+#ifndef FC_HINT_NONE
+#define FC_HINT_NONE        0
+#define FC_HINT_SLIGHT      1
+#define FC_HINT_MEDIUM      2
+#define FC_HINT_FULL        3
+#endif
+
+/* LCD filter */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE	    0
+#define FC_LCD_DEFAULT	    1
+#define FC_LCD_LIGHT	    2
+#define FC_LCD_LEGACY	    3
+#endif
+
+#endif /* _CAIRO_FONTCONFIG_PRIVATE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-freed-pool-private.h
@@ -0,0 +1,129 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#ifndef CAIRO_FREED_POOL_H
+#define CAIRO_FREED_POOL_H
+
+#include "cairoint.h"
+#include "cairo-atomic-private.h"
+
+#if HAS_ATOMIC_OPS
+/* Keep a stash of recently freed clip_paths, since we need to
+ * reallocate them frequently.
+ */
+#define MAX_FREED_POOL_SIZE 4
+typedef struct {
+    void *pool[MAX_FREED_POOL_SIZE];
+    int top;
+} freed_pool_t;
+
+static cairo_always_inline void *
+_atomic_fetch (void **slot)
+{
+    void *ptr;
+
+    do {
+        ptr = _cairo_atomic_ptr_get (slot);
+    } while (! _cairo_atomic_ptr_cmpxchg (slot, ptr, NULL));
+
+    return ptr;
+}
+
+static cairo_always_inline cairo_bool_t
+_atomic_store (void **slot, void *ptr)
+{
+    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
+}
+
+cairo_private void *
+_freed_pool_get_search (freed_pool_t *pool);
+
+static inline void *
+_freed_pool_get (freed_pool_t *pool)
+{
+    void *ptr;
+    int i;
+
+    i = pool->top - 1;
+    if (i < 0)
+	i = 0;
+
+    ptr = _atomic_fetch (&pool->pool[i]);
+    if (likely (ptr != NULL)) {
+	pool->top = i;
+	return ptr;
+    }
+
+    /* either empty or contended */
+    return _freed_pool_get_search (pool);
+}
+
+cairo_private void
+_freed_pool_put_search (freed_pool_t *pool, void *ptr);
+
+static inline void
+_freed_pool_put (freed_pool_t *pool, void *ptr)
+{
+    int i;
+
+    i = pool->top;
+    if (likely (i < ARRAY_LENGTH (pool->pool) &&
+		_atomic_store (&pool->pool[i], ptr)))
+    {
+	pool->top = i + 1;
+	return;
+    }
+
+    /* either full or contended */
+    _freed_pool_put_search (pool, ptr);
+}
+
+cairo_private void
+_freed_pool_reset (freed_pool_t *pool);
+
+#define HAS_FREED_POOL 1
+
+#else
+
+typedef int freed_pool_t;
+
+#define _freed_pool_get(pool) NULL
+#define _freed_pool_put(pool, ptr) free(ptr)
+#define _freed_pool_reset(ptr)
+
+#endif
+
+#endif /* CAIRO_FREED_POOL_PRIVATE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-freed-pool.c
@@ -0,0 +1,93 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-freed-pool-private.h"
+
+#if HAS_FREED_POOL
+
+void *
+_freed_pool_get_search (freed_pool_t *pool)
+{
+    void *ptr;
+    int i;
+
+    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;
+}
+
+void
+_freed_pool_put_search (freed_pool_t *pool, void *ptr)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
+	if (_atomic_store (&pool->pool[i], ptr)) {
+	    pool->top = i + 1;
+	    return;
+	}
+    }
+
+    /* full */
+    pool->top = i;
+    free (ptr);
+}
+
+void
+_freed_pool_reset (freed_pool_t *pool)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
+	free (pool->pool[i]);
+	pool->pool[i] = NULL;
+    }
+
+    pool->top = 0;
+}
+
+#endif
--- a/gfx/cairo/cairo/src/cairo-freelist-private.h
+++ b/gfx/cairo/cairo/src/cairo-freelist-private.h
@@ -19,52 +19,27 @@
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  */
 #ifndef CAIRO_FREELIST_H
 #define CAIRO_FREELIST_H
 
 #include "cairo-types-private.h"
 #include "cairo-compiler-private.h"
+#include "cairo-freelist-type-private.h"
 
 /* for stand-alone compilation*/
 #ifndef VG
 #define VG(x)
 #endif
 
 #ifndef NULL
 #define NULL (void *) 0
 #endif
 
-typedef struct _cairo_freelist_node cairo_freelist_node_t;
-struct _cairo_freelist_node {
-    cairo_freelist_node_t *next;
-};
-
-typedef struct _cairo_freelist {
-    cairo_freelist_node_t *first_free_node;
-    unsigned nodesize;
-} cairo_freelist_t;
-
-typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
-struct _cairo_freelist_pool {
-    cairo_freelist_pool_t *next;
-    unsigned size, rem;
-    uint8_t *data;
-};
-
-typedef struct _cairo_freepool {
-    cairo_freelist_node_t *first_free_node;
-    cairo_freelist_pool_t *pools;
-    unsigned nodesize;
-    cairo_freelist_pool_t embedded_pool;
-    uint8_t embedded_data[1000];
-} cairo_freepool_t;
-
-
 /* Initialise a freelist that will be responsible for allocating
  * nodes of size nodesize. */
 cairo_private void
 _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize);
 
 /* Deallocate any nodes in the freelist. */
 cairo_private void
 _cairo_freelist_fini (cairo_freelist_t *freelist);
@@ -91,16 +66,30 @@ cairo_private void
 
 
 cairo_private void
 _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize);
 
 cairo_private void
 _cairo_freepool_fini (cairo_freepool_t *freepool);
 
+static inline void
+_cairo_freepool_reset (cairo_freepool_t *freepool)
+{
+    while (freepool->pools != &freepool->embedded_pool) {
+	cairo_freelist_pool_t *pool = freepool->pools;
+	freepool->pools = pool->next;
+	pool->next = freepool->freepools;
+	freepool->freepools = pool;
+    }
+
+    freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
+    freepool->embedded_pool.data = freepool->embedded_data;
+}
+
 cairo_private void *
 _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool);
 
 static inline void *
 _cairo_freepool_alloc_from_pool (cairo_freepool_t *freepool)
 {
     cairo_freelist_pool_t *pool;
     uint8_t *ptr;
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-freelist-type-private.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2010 Joonas Pihlaja
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#ifndef CAIRO_FREELIST_TYPE_H
+#define CAIRO_FREELIST_TYPE_H
+
+#include "cairo-types-private.h"
+#include "cairo-compiler-private.h"
+
+typedef struct _cairo_freelist_node cairo_freelist_node_t;
+struct _cairo_freelist_node {
+    cairo_freelist_node_t *next;
+};
+
+typedef struct _cairo_freelist {
+    cairo_freelist_node_t *first_free_node;
+    unsigned nodesize;
+} cairo_freelist_t;
+
+typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
+struct _cairo_freelist_pool {
+    cairo_freelist_pool_t *next;
+    unsigned size, rem;
+    uint8_t *data;
+};
+
+typedef struct _cairo_freepool {
+    cairo_freelist_node_t *first_free_node;
+    cairo_freelist_pool_t *pools;
+    cairo_freelist_pool_t *freepools;
+    unsigned nodesize;
+    cairo_freelist_pool_t embedded_pool;
+    uint8_t embedded_data[1000];
+} cairo_freepool_t;
+
+#endif /* CAIRO_FREELIST_TYPE_H */
--- a/gfx/cairo/cairo/src/cairo-freelist.c
+++ b/gfx/cairo/cairo/src/cairo-freelist.c
@@ -17,16 +17,17 @@
  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  */
 
 #include "cairoint.h"
 
+#include "cairo-error-private.h"
 #include "cairo-freelist-private.h"
 
 void
 _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
 {
     memset (freelist, 0, sizeof (cairo_freelist_t));
     freelist->nodesize = nodesize;
 }
@@ -78,68 +79,85 @@ void
     cairo_freelist_node_t *node = voidnode;
     if (node) {
 	node->next = freelist->first_free_node;
 	freelist->first_free_node = node;
 	VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
     }
 }
 
-
 void
 _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
 {
     freepool->first_free_node = NULL;
     freepool->pools = &freepool->embedded_pool;
+    freepool->freepools = NULL;
     freepool->nodesize = nodesize;
 
     freepool->embedded_pool.next = NULL;
     freepool->embedded_pool.size = sizeof (freepool->embedded_data);
     freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
     freepool->embedded_pool.data = freepool->embedded_data;
 
-    VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data,
-				    sizeof (freepool->embedded_data)));
+    VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
 }
 
 void
 _cairo_freepool_fini (cairo_freepool_t *freepool)
 {
-    cairo_freelist_pool_t *pool = freepool->pools;
+    cairo_freelist_pool_t *pool;
+
+    pool = freepool->pools;
     while (pool != &freepool->embedded_pool) {
 	cairo_freelist_pool_t *next = pool->next;
 	free (pool);
 	pool = next;
     }
+
+    pool = freepool->freepools;
+    while (pool != NULL) {
+	cairo_freelist_pool_t *next = pool->next;
+	free (pool);
+	pool = next;
+    }
+
     VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
 }
 
 void *
 _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
 {
     cairo_freelist_pool_t *pool;
     int poolsize;
 
-    if (freepool->pools != &freepool->embedded_pool)
-	poolsize = 2 * freepool->pools->size;
-    else
-	poolsize = (128 * freepool->nodesize + 8191) & -8192;
-    pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
-    if (unlikely (pool == NULL))
-	return pool;
+    if (freepool->freepools != NULL) {
+	pool = freepool->freepools;
+	freepool->freepools = pool->next;
+
+	poolsize = pool->size;
+    } else {
+	if (freepool->pools != &freepool->embedded_pool)
+	    poolsize = 2 * freepool->pools->size;
+	else
+	    poolsize = (128 * freepool->nodesize + 8191) & -8192;
+
+	pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
+	if (unlikely (pool == NULL))
+	    return pool;
+
+	pool->size = poolsize;
+    }
 
     pool->next = freepool->pools;
     freepool->pools = pool;
 
-    pool->size = poolsize;
     pool->rem = poolsize - freepool->nodesize;
     pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
 
-    VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, poolsize));
-    VG (VALGRIND_MAKE_MEM_UNDEFINED (pool->data, freepool->nodesize));
+    VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
 
     return pool + 1;
 }
 
 cairo_status_t
 _cairo_freepool_alloc_array (cairo_freepool_t *freepool,
 			     int count,
 			     void **array)
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -9,17 +9,17 @@
  * 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
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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/
  *
@@ -36,47 +36,93 @@
  *	Owen Taylor <otaylor@redhat.com>
  *      Keith Packard <keithp@keithp.com>
  *      Carl Worth <cworth@cworth.org>
  */
 
 #define _BSD_SOURCE /* for strdup() */
 #include "cairoint.h"
 
+#include "cairo-error-private.h"
 #include "cairo-ft-private.h"
 
 #include <float.h>
 
-#if CAIRO_HAS_FC_FONT
-#include <fontconfig/fontconfig.h>
-#include <fontconfig/fcfreetype.h>
-#endif
+#include "cairo-fontconfig-private.h"
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_IMAGE_H
 #include FT_TRUETYPE_TABLES_H
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 #include FT_SYNTHESIS_H
 #endif
 
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+#include FT_LCD_FILTER_H
+#endif
+
+/* Fontconfig version older than 2.6 didn't have these options */
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER	"lcdfilter"
+#endif
+/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE	0
+#define FC_LCD_DEFAULT	1
+#define FC_LCD_LIGHT	2
+#define FC_LCD_LEGACY	3
+#endif
+
+/* FreeType version older than 2.3.5(?) didn't have these options */
+#ifndef FT_LCD_FILTER_NONE
+#define FT_LCD_FILTER_NONE	0
+#define FT_LCD_FILTER_DEFAULT	1
+#define FT_LCD_FILTER_LIGHT	2
+#define FT_LCD_FILTER_LEGACY	16
+#endif
+
 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
 
 /* This is the max number of FT_face objects we keep open at once
  */
 #define MAX_OPEN_FACES 10
-
 /* This is the maximum font size we allow to be passed to FT_Set_Char_Size
  */
 #define MAX_FONT_SIZE 1000
 
+/**
+ * SECTION:cairo-ft
+ * @Title: FreeType Fonts
+ * @Short_Description: Font support for FreeType
+ * @See_Also: #cairo_font_face_t
+ *
+ * The FreeType font backend is primarily used to render text on GNU/Linux
+ * systems, but can be used on other platforms too.
+ */
+
+/**
+ * CAIRO_HAS_FT_FONT:
+ *
+ * Defined if the FreeType font backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ */
+
+/**
+ * CAIRO_HAS_FC_FONT:
+ *
+ * Defined if the Fontconfig-specific functions of the FreeType font backend
+ * are available.
+ * This macro can be used to conditionally compile backend-specific code.
+ */
+
 /*
  * The simple 2x2 matrix is converted into separate scale and shape
  * factors so that hinting works right
  */
 
 typedef struct _cairo_ft_font_transform {
     double  x_scale, y_scale;
     double  shape[2][2];
@@ -175,16 +221,17 @@ static cairo_font_face_t *
 typedef struct _cairo_ft_unscaled_font_map {
     cairo_hash_table_t *hash_table;
     FT_Library ft_library;
     int num_open_faces;
 } cairo_ft_unscaled_font_map_t;
 
 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
 
+
 static void
 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
 				  cairo_ft_unscaled_font_t *unscaled)
 {
     if (unscaled->face) {
 	FT_Done_Face (unscaled->face);
 	unscaled->face = NULL;
 	unscaled->have_scale = FALSE;
@@ -774,45 +821,302 @@ static cairo_status_t
 					unscaled->face->available_sizes[best_i].height);
 	if (error)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-/* Empirically-derived subpixel filtering values thanks to Keith
- * Packard and libXft. */
-static const int    filters[3][3] = {
-    /* red */
-#if 0
-    {    65538*4/7,65538*2/7,65538*1/7 },
-    /* green */
-    {    65536*1/4, 65536*2/4, 65537*1/4 },
-    /* blue */
-    {    65538*1/7,65538*2/7,65538*4/7 },
-#endif
-    {    65538*9/13,65538*3/13,65538*1/13 },
-    /* green */
-    {    65538*1/6, 65538*4/6, 65538*1/6 },
-    /* blue */
-    {    65538*1/13,65538*3/13,65538*9/13 },
-};
+/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
+ * into a different format. For example, we want to convert a
+ * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
+ * ARGB or ABGR bitmap.
+ *
+ * this function prepares a target descriptor for this operation.
+ *
+ * input :: target bitmap descriptor. The function will set its
+ *          'width', 'rows' and 'pitch' fields, and only these
+ *
+ * slot  :: the glyph slot containing the source bitmap. this
+ *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
+ *
+ * mode  :: the requested final rendering mode. supported values are
+ *          MONO, NORMAL (i.e. gray), LCD and LCD_V
+ *
+ * the function returns the size in bytes of the corresponding buffer,
+ * it's up to the caller to allocate the corresponding memory block
+ * before calling _fill_xrender_bitmap
+ *
+ * it also returns -1 in case of error (e.g. incompatible arguments,
+ * like trying to convert a gray bitmap into a monochrome one)
+ */
+static int
+_compute_xrender_bitmap_size(FT_Bitmap      *target,
+			     FT_GlyphSlot    slot,
+			     FT_Render_Mode  mode)
+{
+    FT_Bitmap *ftbit;
+    int width, height, pitch;
+
+    if (slot->format != FT_GLYPH_FORMAT_BITMAP)
+	return -1;
+
+    /* compute the size of the final bitmap */
+    ftbit = &slot->bitmap;
+
+    width = ftbit->width;
+    height = ftbit->rows;
+    pitch = (width + 3) & ~3;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (mode == FT_RENDER_MODE_MONO) {
+	    pitch = (((width + 31) & ~31) >> 3);
+	    break;
+	}
+	/* fall-through */
+
+    case FT_PIXEL_MODE_GRAY:
+	if (mode == FT_RENDER_MODE_LCD ||
+	    mode == FT_RENDER_MODE_LCD_V)
+	{
+	    /* each pixel is replicated into a 32-bit ARGB value */
+	    pitch = width * 4;
+	}
+	break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (mode != FT_RENDER_MODE_LCD)
+	    return -1;
+
+	/* horz pixel triplets are packed into 32-bit ARGB values */
+	width /= 3;
+	pitch = width * 4;
+	break;
+
+    case FT_PIXEL_MODE_LCD_V:
+	if (mode != FT_RENDER_MODE_LCD_V)
+	    return -1;
+
+	/* vert pixel triplets are packed into 32-bit ARGB values */
+	height /= 3;
+	pitch = width * 4;
+	break;
+
+    default:  /* unsupported source format */
+	return -1;
+    }
+
+    target->width = width;
+    target->rows = height;
+    target->pitch = pitch;
+    target->buffer = NULL;
+
+    return pitch * height;
+}
+
+/* this functions converts the glyph bitmap found in a FT_GlyphSlot
+ * into a different format (see _compute_xrender_bitmap_size)
+ *
+ * you should call this function after _compute_xrender_bitmap_size
+ *
+ * target :: target bitmap descriptor. Note that its 'buffer' pointer
+ *           must point to memory allocated by the caller
+ *
+ * slot   :: the glyph slot containing the source bitmap
+ *
+ * mode   :: the requested final rendering mode
+ *
+ * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
+ */
+static void
+_fill_xrender_bitmap(FT_Bitmap      *target,
+		     FT_GlyphSlot    slot,
+		     FT_Render_Mode  mode,
+		     int             bgr)
+{
+    FT_Bitmap *ftbit = &slot->bitmap;
+    unsigned char *srcLine = ftbit->buffer;
+    unsigned char *dstLine = target->buffer;
+    int src_pitch = ftbit->pitch;
+    int width = target->width;
+    int height = target->rows;
+    int pitch = target->pitch;
+    int subpixel;
+    int h;
+
+    subpixel = (mode == FT_RENDER_MODE_LCD ||
+		mode == FT_RENDER_MODE_LCD_V);
+
+    if (src_pitch < 0)
+	srcLine -= src_pitch * (ftbit->rows - 1);
+
+    target->pixel_mode = ftbit->pixel_mode;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (subpixel) {
+	    /* convert mono to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			((unsigned int *) dstLine)[x] = 0xffffffffU;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+
+	} else if (mode == FT_RENDER_MODE_NORMAL) {
+	    /* convert mono to 8-bit gray */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			dstLine[x] = 0xff;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_GRAY;
+
+	} else {
+	    /* copy mono to mono */
+
+	    int  bytes = (width + 7) >> 3;
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+		memcpy (dstLine, srcLine, bytes);
+	}
+	break;
+
+    case FT_PIXEL_MODE_GRAY:
+	if (subpixel) {
+	    /* convert gray to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++) {
+		    unsigned int pix = srcLine[x];
+
+		    pix |= (pix << 8);
+		    pix |= (pix << 16);
+
+		    dst[x] = pix;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+        } else {
+            /* copy gray into gray */
+
+            for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+                memcpy (dstLine, srcLine, width);
+        }
+        break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (!bgr) {
+	    /* convert horizontal RGB into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[0] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[2]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+	    /* convert horizontal BGR into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[2] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[0]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+	break;
+
+    default:  /* FT_PIXEL_MODE_LCD_V */
+	/* convert vertical RGB into ARGB32 */
+	if (!bgr) {
+
+	    for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char* src = srcLine;
+		unsigned int*  dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int pix;
+		    pix = ((unsigned int)src[0]           << 16) |
+			  ((unsigned int)src[src_pitch]   <<  8) |
+			  ((unsigned int)src[src_pitch*2]      ) |
+			  ((unsigned int)src[src_pitch]   << 24) ;
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+
+	    for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[src_pitch * 2] << 16) |
+			  ((unsigned int)src[src_pitch]     <<  8) |
+			  ((unsigned int)src[0]                  ) |
+			  ((unsigned int)src[src_pitch]     << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+    }
+}
+
 
 /* Fills in val->image with an image surface created from @bitmap
  */
 static cairo_status_t
 _get_bitmap_surface (FT_Bitmap		     *bitmap,
 		     cairo_bool_t	      own_buffer,
 		     cairo_font_options_t    *font_options,
 		     cairo_image_surface_t  **surface)
 {
     int width, height, stride;
     unsigned char *data;
     int format = CAIRO_FORMAT_A8;
+    cairo_image_surface_t *image;
 
     width = bitmap->width;
     height = bitmap->rows;
 
     if (width == 0 || height == 0) {
 	*surface = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	return (*surface)->base.status;
@@ -859,152 +1163,66 @@ static cairo_status_t
 	}
 #endif
 	format = CAIRO_FORMAT_A1;
 	break;
 
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
     case FT_PIXEL_MODE_GRAY:
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	case CAIRO_ANTIALIAS_NONE:
-	default:
+        if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
 	    stride = bitmap->pitch;
 	    if (own_buffer) {
 		data = bitmap->buffer;
 	    } else {
 		data = _cairo_malloc_ab (height, stride);
 		if (!data)
 		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 		memcpy (data, bitmap->buffer, stride * height);
 	    }
-	    format = CAIRO_FORMAT_A8;
-	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL: {
-	    int		    x, y;
-	    unsigned char   *in_line, *out_line, *in;
-	    unsigned int    *out;
-	    unsigned int    red, green, blue;
-	    int		    rf, gf, bf;
-	    int		    s;
-	    int		    o, os;
-	    unsigned char   *data_rgba;
-	    unsigned int    width_rgba, stride_rgba;
-	    int		    vmul = 1;
-	    int		    hmul = 1;
-
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    default:
-		width /= 3;
-		hmul = 3;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		vmul = 3;
-		height /= 3;
-		break;
-	    }
-	    /*
-	     * Filter the glyph to soften the color fringes
-	     */
-	    width_rgba = width;
-	    stride = bitmap->pitch;
-	    stride_rgba = (width_rgba * 4 + 3) & ~3;
-	    data_rgba = calloc (stride_rgba, height);
-	    if (unlikely (data_rgba == NULL)) {
-		if (own_buffer)
-		    free (bitmap->buffer);
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    }
-
-	    os = 1;
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    default:
-		rf = 0;
-		gf = 1;
-		bf = 2;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-		bf = 0;
-		gf = 1;
-		rf = 2;
-		break;
-	    }
-	    in_line = bitmap->buffer;
-	    out_line = data_rgba;
-	    for (y = 0; y < height; y++)
-	    {
-		in = in_line;
-		out = (unsigned int *) out_line;
-		in_line += stride * vmul;
-		out_line += stride_rgba;
-		for (x = 0; x < width * hmul; x += hmul)
-		{
-		    red = green = blue = 0;
-		    o = 0;
-		    for (s = 0; s < 3; s++)
-		    {
-			red += filters[rf][s]*in[x+o];
-			green += filters[gf][s]*in[x+o];
-			blue += filters[bf][s]*in[x+o];
-			o += os;
-		    }
-		    red = red / 65536;
-		    green = green / 65536;
-		    blue = blue / 65536;
-		    *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
-		}
-	    }
-
-	    /* Images here are stored in native format. The
-	     * backend must convert to its own format as needed
-	     */
-
-	    if (own_buffer)
-		free (bitmap->buffer);
-	    data = data_rgba;
-	    stride = stride_rgba;
-	    format = CAIRO_FORMAT_ARGB32;
-	    break;
-	}
+
+	format = CAIRO_FORMAT_A8;
+	} else {
+	    /* if we get there, the  data from the source bitmap
+	     * really comes from _fill_xrender_bitmap, and is
+	     * made of 32-bit ARGB or ABGR values */
+	    assert (own_buffer != 0);
+	    assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
+
+		data = bitmap->buffer;
+		stride = bitmap->pitch;
+		format = CAIRO_FORMAT_ARGB32;
 	}
 	break;
     case FT_PIXEL_MODE_GRAY2:
     case FT_PIXEL_MODE_GRAY4:
 	/* These could be triggered by very rare types of TrueType fonts */
     default:
 	if (own_buffer)
 	    free (bitmap->buffer);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    *surface = (cairo_image_surface_t *)
+    /* XXX */
+    *surface = image = (cairo_image_surface_t *)
 	cairo_image_surface_create_for_data (data,
 					     format,
 					     width, height, stride);
-    if ((*surface)->base.status) {
+    if (image->base.status) {
 	free (data);
 	return (*surface)->base.status;
     }
 
-    _cairo_image_surface_assume_ownership_of_data ((*surface));
-
-    _cairo_debug_check_image_surface_is_defined (&(*surface)->base);
+    if (format == CAIRO_FORMAT_ARGB32)
+	pixman_image_set_component_alpha (image->pixman_image, TRUE);
+
+    _cairo_image_surface_assume_ownership_of_data (image);
+
+    _cairo_debug_check_image_surface_is_defined (&image->base);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 /* Converts an outline FT_GlyphSlot into an image
  *
  * This could go through _render_glyph_bitmap as well, letting
  * FreeType convert the outline to a bitmap, but doing it ourselves
@@ -1019,129 +1237,172 @@ static cairo_status_t
  * when we add subpixel support. If so, we may want to eliminate
  * this version of the code path entirely.
  */
 static cairo_status_t
 _render_glyph_outline (FT_Face                    face,
 		       cairo_font_options_t	 *font_options,
 		       cairo_image_surface_t	**surface)
 {
+    int rgba = FC_RGBA_UNKNOWN;
+    int lcd_filter = FT_LCD_FILTER_LEGACY;
     FT_GlyphSlot glyphslot = face->glyph;
     FT_Outline *outline = &glyphslot->outline;
     FT_Bitmap bitmap;
     FT_BBox cbox;
-    FT_Matrix matrix;
-    int hmul = 1;
-    int vmul = 1;
-    unsigned int width, height, stride;
-    cairo_bool_t subpixel = FALSE;
+    unsigned int width, height;
     cairo_status_t status;
+    FT_Error fterror;
+    FT_Library library = glyphslot->library;
+    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
+
+    switch (font_options->antialias) {
+    case CAIRO_ANTIALIAS_NONE:
+	render_mode = FT_RENDER_MODE_MONO;
+	break;
+
+    case CAIRO_ANTIALIAS_SUBPIXEL:
+	switch (font_options->subpixel_order) {
+	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
+	    case CAIRO_SUBPIXEL_ORDER_RGB:
+	    case CAIRO_SUBPIXEL_ORDER_BGR:
+		render_mode = FT_RENDER_MODE_LCD;
+		break;
+
+	    case CAIRO_SUBPIXEL_ORDER_VRGB:
+	    case CAIRO_SUBPIXEL_ORDER_VBGR:
+		render_mode = FT_RENDER_MODE_LCD_V;
+		break;
+	}
+
+	switch (font_options->lcd_filter) {
+	case CAIRO_LCD_FILTER_NONE:
+	    lcd_filter = FT_LCD_FILTER_NONE;
+	    break;
+	case CAIRO_LCD_FILTER_DEFAULT:
+	case CAIRO_LCD_FILTER_INTRA_PIXEL:
+	    lcd_filter = FT_LCD_FILTER_LEGACY;
+	    break;
+	case CAIRO_LCD_FILTER_FIR3:
+	    lcd_filter = FT_LCD_FILTER_LIGHT;
+	    break;
+	case CAIRO_LCD_FILTER_FIR5:
+	    lcd_filter = FT_LCD_FILTER_DEFAULT;
+	    break;
+	}
+
+	break;
+
+    case CAIRO_ANTIALIAS_DEFAULT:
+    case CAIRO_ANTIALIAS_GRAY:
+	render_mode = FT_RENDER_MODE_NORMAL;
+    }
 
     FT_Outline_Get_CBox (outline, &cbox);
 
     cbox.xMin &= -64;
     cbox.yMin &= -64;
     cbox.xMax = (cbox.xMax + 63) & -64;
     cbox.yMax = (cbox.yMax + 63) & -64;
 
     width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
     height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
-    stride = (width * hmul + 3) & ~3;
 
     if (width * height == 0) {
 	cairo_format_t format;
 	/* Looks like fb handles zero-sized images just fine */
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
+	switch (render_mode) {
+	case FT_RENDER_MODE_MONO:
 	    format = CAIRO_FORMAT_A1;
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
+	case FT_RENDER_MODE_LCD:
+	case FT_RENDER_MODE_LCD_V:
 	    format= CAIRO_FORMAT_ARGB32;
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
 	default:
 	    format = CAIRO_FORMAT_A8;
 	    break;
 	}
 
 	(*surface) = (cairo_image_surface_t *)
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	if ((*surface)->base.status)
 	    return (*surface)->base.status;
-    } else  {
-
-	matrix.xx = matrix.yy = 0x10000L;
-	matrix.xy = matrix.yx = 0;
-
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
-	    bitmap.num_grays  = 1;
-	    stride = ((width + 31) & -32) >> 3;
+    } else {
+
+	int bitmap_size;
+
+	switch (render_mode) {
+	case FT_RENDER_MODE_LCD:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
+		rgba = FC_RGBA_BGR;
+	    } else {
+		rgba = FC_RGBA_RGB;
+	    }
+	case FT_RENDER_MODE_LCD_V:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
+		rgba = FC_RGBA_VBGR;
+	    } else {
+		rgba = FC_RGBA_VRGB;
+		}
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    bitmap.num_grays  = 256;
-	    stride = (width + 3) & -4;
+	case FT_RENDER_MODE_MONO:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
+	default:
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    default:
-		matrix.xx *= 3;
-		hmul = 3;
-		subpixel = TRUE;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		matrix.yy *= 3;
-		vmul = 3;
-		subpixel = TRUE;
-		break;
 	    }
-	    FT_Outline_Transform (outline, &matrix);
-
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    bitmap.num_grays  = 256;
-	    stride = (width * hmul + 3) & -4;
-	}
-
-	bitmap.pitch = stride;
-	bitmap.width = width * hmul;
-	bitmap.rows = height * vmul;
-	bitmap.buffer = calloc (stride, bitmap.rows);
-	if (unlikely (bitmap.buffer == NULL))
+
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+	FT_Library_SetLcdFilter (library, lcd_filter);
+#endif
+
+	fterror = FT_Render_Glyph (face->glyph, render_mode);