[cairo-commit] 3 commits - boilerplate/cairo-boilerplate.c configure.in perf/cairo-perf.c src/cairo-atsui-font.c src/cairo.h src/cairo-nquartz.h src/cairo-nquartz-surface.c src/cairo-quartz.h src/cairo-quartz-private.h src/cairo-quartz-surface.c src/Makefile.am test/caps-joins-alpha-nquartz-ref.png test/caps-joins-alpha-quartz-ref.png test/clip-nesting-nquartz-ref.png test/clip-nesting-nquartz-rgb24-ref.png test/clip-nesting-quartz-ref.png test/clip-nesting-quartz-rgb24-ref.png test/clip-push-group-nquartz-ref.png test/clip-push-group-quartz-ref.png test/clip-twice-nquartz-ref.png test/clip-twice-nquartz-rgb24-ref.png test/clip-twice-quartz-ref.png test/clip-twice-quartz-rgb24-ref.png test/dash-caps-joins-nquartz-ref.png test/dash-caps-joins-quartz-ref.png test/degenerate-path-nquartz-rgb24-ref.png test/degenerate-path-quartz-rgb24-ref.png test/fill-and-stroke-alpha-add-nquartz-ref.png test/fill-and-stroke-alpha-add-quartz-ref.png test/fill-and-stroke-alpha-nquartz-ref.png test/fill-and-stroke-alpha-quartz-ref.png test/fill-and-stroke-nquartz-ref.png test/fill-and-stroke-nquartz-rgb24-ref.png test/fill-and-stroke-quartz-ref.png test/fill-and-stroke-quartz-rgb24-ref.png test/fill-degenerate-sort-order-nquartz-ref.png test/fill-degenerate-sort-order-nquartz-rgb24-ref.png test/fill-degenerate-sort-order-quartz-ref.png test/fill-degenerate-sort-order-quartz-rgb24-ref.png test/fill-rule-nquartz-ref.png test/fill-rule-nquartz-rgb24-ref.png test/fill-rule-quartz-ref.png test/fill-rule-quartz-rgb24-ref.png test/get-clip.c test/new-sub-path-nquartz-ref.png test/new-sub-path-nquartz-rgb24-ref.png test/new-sub-path-quartz-ref.png test/new-sub-path-quartz-rgb24-ref.png test/operator-clear-nquartz-ref.png test/operator-clear-nquartz-rgb24-ref.png test/operator-clear-quartz-ref.png test/operator-clear-quartz-rgb24-ref.png test/random-intersections-nquartz-ref.png test/random-intersections-nquartz-rgb24-ref.png test/random-intersections-quartz-ref.png test/random-intersections-quartz-rgb24-ref.png test/rel-path-nquartz-ref.png test/rel-path-nquartz-rgb24-ref.png test/rel-path-quartz-ref.png test/rel-path-quartz-rgb24-ref.png test/source-clip-scale-nquartz-ref.png test/source-clip-scale-quartz-ref.png test/trap-clip-nquartz-ref.png test/trap-clip-nquartz-rgb24-ref.png test/trap-clip-quartz-ref.png test/trap-clip-quartz-rgb24-ref.png

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Tue Feb 20 14:45:18 PST 2007


 boilerplate/cairo-boilerplate.c     |   47 
 configure.in                        |    7 
 perf/cairo-perf.c                   |    1 
 src/Makefile.am                     |    6 
 src/cairo-atsui-font.c              |   33 
 src/cairo-nquartz-surface.c         | 1864 -----------------------------------
 src/cairo-nquartz.h                 |   80 -
 src/cairo-quartz-private.h          |   32 
 src/cairo-quartz-surface.c          | 1901 +++++++++++++++++++++++++++++++++---
 src/cairo-quartz.h                  |   33 
 src/cairo.h                         |    1 
 test/get-clip.c                     |    3 
 test/trap-clip-quartz-rgb24-ref.png |    0 
 13 files changed, 1819 insertions(+), 2189 deletions(-)

New commits:
diff-tree 28c1e46b8e082f65fc94c984ea3b66df5adaa529 (from be451cd83d8178bfaf28a1c7dec59601d97cff8d)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 20 13:22:11 2007 -0800

    [quartz] rename test override images from nquartz to quartz

diff --git a/test/caps-joins-alpha-nquartz-ref.png b/test/caps-joins-alpha-nquartz-ref.png
deleted file mode 100644
index 190c1e9..0000000
Binary files a/test/caps-joins-alpha-nquartz-ref.png and /dev/null differ
diff --git a/test/caps-joins-alpha-quartz-ref.png b/test/caps-joins-alpha-quartz-ref.png
new file mode 100644
index 0000000..190c1e9
Binary files /dev/null and b/test/caps-joins-alpha-quartz-ref.png differ
diff --git a/test/clip-nesting-nquartz-ref.png b/test/clip-nesting-nquartz-ref.png
deleted file mode 100644
index 5a3db7b..0000000
Binary files a/test/clip-nesting-nquartz-ref.png and /dev/null differ
diff --git a/test/clip-nesting-nquartz-rgb24-ref.png b/test/clip-nesting-nquartz-rgb24-ref.png
deleted file mode 100644
index b55d116..0000000
Binary files a/test/clip-nesting-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/clip-nesting-quartz-ref.png b/test/clip-nesting-quartz-ref.png
new file mode 100644
index 0000000..5a3db7b
Binary files /dev/null and b/test/clip-nesting-quartz-ref.png differ
diff --git a/test/clip-nesting-quartz-rgb24-ref.png b/test/clip-nesting-quartz-rgb24-ref.png
new file mode 100644
index 0000000..b55d116
Binary files /dev/null and b/test/clip-nesting-quartz-rgb24-ref.png differ
diff --git a/test/clip-push-group-nquartz-ref.png b/test/clip-push-group-nquartz-ref.png
deleted file mode 100644
index 93c5268..0000000
Binary files a/test/clip-push-group-nquartz-ref.png and /dev/null differ
diff --git a/test/clip-push-group-quartz-ref.png b/test/clip-push-group-quartz-ref.png
new file mode 100644
index 0000000..93c5268
Binary files /dev/null and b/test/clip-push-group-quartz-ref.png differ
diff --git a/test/clip-twice-nquartz-ref.png b/test/clip-twice-nquartz-ref.png
deleted file mode 100644
index f8231b3..0000000
Binary files a/test/clip-twice-nquartz-ref.png and /dev/null differ
diff --git a/test/clip-twice-nquartz-rgb24-ref.png b/test/clip-twice-nquartz-rgb24-ref.png
deleted file mode 100644
index 65cd80f..0000000
Binary files a/test/clip-twice-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/clip-twice-quartz-ref.png b/test/clip-twice-quartz-ref.png
new file mode 100644
index 0000000..f8231b3
Binary files /dev/null and b/test/clip-twice-quartz-ref.png differ
diff --git a/test/clip-twice-quartz-rgb24-ref.png b/test/clip-twice-quartz-rgb24-ref.png
new file mode 100644
index 0000000..65cd80f
Binary files /dev/null and b/test/clip-twice-quartz-rgb24-ref.png differ
diff --git a/test/dash-caps-joins-nquartz-ref.png b/test/dash-caps-joins-nquartz-ref.png
deleted file mode 100644
index 5e4aa76..0000000
Binary files a/test/dash-caps-joins-nquartz-ref.png and /dev/null differ
diff --git a/test/dash-caps-joins-quartz-ref.png b/test/dash-caps-joins-quartz-ref.png
new file mode 100644
index 0000000..5e4aa76
Binary files /dev/null and b/test/dash-caps-joins-quartz-ref.png differ
diff --git a/test/degenerate-path-nquartz-rgb24-ref.png b/test/degenerate-path-nquartz-rgb24-ref.png
deleted file mode 100644
index 6be052e..0000000
Binary files a/test/degenerate-path-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/degenerate-path-quartz-rgb24-ref.png b/test/degenerate-path-quartz-rgb24-ref.png
new file mode 100644
index 0000000..6be052e
Binary files /dev/null and b/test/degenerate-path-quartz-rgb24-ref.png differ
diff --git a/test/fill-and-stroke-alpha-add-nquartz-ref.png b/test/fill-and-stroke-alpha-add-nquartz-ref.png
deleted file mode 100644
index d648eec..0000000
Binary files a/test/fill-and-stroke-alpha-add-nquartz-ref.png and /dev/null differ
diff --git a/test/fill-and-stroke-alpha-add-quartz-ref.png b/test/fill-and-stroke-alpha-add-quartz-ref.png
new file mode 100644
index 0000000..d648eec
Binary files /dev/null and b/test/fill-and-stroke-alpha-add-quartz-ref.png differ
diff --git a/test/fill-and-stroke-alpha-nquartz-ref.png b/test/fill-and-stroke-alpha-nquartz-ref.png
deleted file mode 100644
index 0121479..0000000
Binary files a/test/fill-and-stroke-alpha-nquartz-ref.png and /dev/null differ
diff --git a/test/fill-and-stroke-alpha-quartz-ref.png b/test/fill-and-stroke-alpha-quartz-ref.png
new file mode 100644
index 0000000..0121479
Binary files /dev/null and b/test/fill-and-stroke-alpha-quartz-ref.png differ
diff --git a/test/fill-and-stroke-nquartz-ref.png b/test/fill-and-stroke-nquartz-ref.png
deleted file mode 100644
index 4c48d24..0000000
Binary files a/test/fill-and-stroke-nquartz-ref.png and /dev/null differ
diff --git a/test/fill-and-stroke-nquartz-rgb24-ref.png b/test/fill-and-stroke-nquartz-rgb24-ref.png
deleted file mode 100644
index 5972d56..0000000
Binary files a/test/fill-and-stroke-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/fill-and-stroke-quartz-ref.png b/test/fill-and-stroke-quartz-ref.png
new file mode 100644
index 0000000..4c48d24
Binary files /dev/null and b/test/fill-and-stroke-quartz-ref.png differ
diff --git a/test/fill-and-stroke-quartz-rgb24-ref.png b/test/fill-and-stroke-quartz-rgb24-ref.png
new file mode 100644
index 0000000..5972d56
Binary files /dev/null and b/test/fill-and-stroke-quartz-rgb24-ref.png differ
diff --git a/test/fill-degenerate-sort-order-nquartz-ref.png b/test/fill-degenerate-sort-order-nquartz-ref.png
deleted file mode 100644
index 0ea4a67..0000000
Binary files a/test/fill-degenerate-sort-order-nquartz-ref.png and /dev/null differ
diff --git a/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png b/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png
deleted file mode 100644
index 59e1cb6..0000000
Binary files a/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/fill-degenerate-sort-order-quartz-ref.png b/test/fill-degenerate-sort-order-quartz-ref.png
new file mode 100644
index 0000000..0ea4a67
Binary files /dev/null and b/test/fill-degenerate-sort-order-quartz-ref.png differ
diff --git a/test/fill-degenerate-sort-order-quartz-rgb24-ref.png b/test/fill-degenerate-sort-order-quartz-rgb24-ref.png
new file mode 100644
index 0000000..59e1cb6
Binary files /dev/null and b/test/fill-degenerate-sort-order-quartz-rgb24-ref.png differ
diff --git a/test/fill-rule-nquartz-ref.png b/test/fill-rule-nquartz-ref.png
deleted file mode 100644
index f7e616c..0000000
Binary files a/test/fill-rule-nquartz-ref.png and /dev/null differ
diff --git a/test/fill-rule-nquartz-rgb24-ref.png b/test/fill-rule-nquartz-rgb24-ref.png
deleted file mode 100644
index 8b180c5..0000000
Binary files a/test/fill-rule-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/fill-rule-quartz-ref.png b/test/fill-rule-quartz-ref.png
new file mode 100644
index 0000000..f7e616c
Binary files /dev/null and b/test/fill-rule-quartz-ref.png differ
diff --git a/test/fill-rule-quartz-rgb24-ref.png b/test/fill-rule-quartz-rgb24-ref.png
new file mode 100644
index 0000000..8b180c5
Binary files /dev/null and b/test/fill-rule-quartz-rgb24-ref.png differ
diff --git a/test/new-sub-path-nquartz-ref.png b/test/new-sub-path-nquartz-ref.png
deleted file mode 100644
index e9c40b9..0000000
Binary files a/test/new-sub-path-nquartz-ref.png and /dev/null differ
diff --git a/test/new-sub-path-nquartz-rgb24-ref.png b/test/new-sub-path-nquartz-rgb24-ref.png
deleted file mode 100644
index efc907e..0000000
Binary files a/test/new-sub-path-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/new-sub-path-quartz-ref.png b/test/new-sub-path-quartz-ref.png
new file mode 100644
index 0000000..e9c40b9
Binary files /dev/null and b/test/new-sub-path-quartz-ref.png differ
diff --git a/test/new-sub-path-quartz-rgb24-ref.png b/test/new-sub-path-quartz-rgb24-ref.png
new file mode 100644
index 0000000..efc907e
Binary files /dev/null and b/test/new-sub-path-quartz-rgb24-ref.png differ
diff --git a/test/operator-clear-nquartz-ref.png b/test/operator-clear-nquartz-ref.png
deleted file mode 100644
index d79d4c3..0000000
Binary files a/test/operator-clear-nquartz-ref.png and /dev/null differ
diff --git a/test/operator-clear-nquartz-rgb24-ref.png b/test/operator-clear-nquartz-rgb24-ref.png
deleted file mode 100644
index d47ce75..0000000
Binary files a/test/operator-clear-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/operator-clear-quartz-ref.png b/test/operator-clear-quartz-ref.png
new file mode 100644
index 0000000..d79d4c3
Binary files /dev/null and b/test/operator-clear-quartz-ref.png differ
diff --git a/test/operator-clear-quartz-rgb24-ref.png b/test/operator-clear-quartz-rgb24-ref.png
new file mode 100644
index 0000000..d47ce75
Binary files /dev/null and b/test/operator-clear-quartz-rgb24-ref.png differ
diff --git a/test/random-intersections-nquartz-ref.png b/test/random-intersections-nquartz-ref.png
deleted file mode 100644
index a687088..0000000
Binary files a/test/random-intersections-nquartz-ref.png and /dev/null differ
diff --git a/test/random-intersections-nquartz-rgb24-ref.png b/test/random-intersections-nquartz-rgb24-ref.png
deleted file mode 100644
index 77f73cd..0000000
Binary files a/test/random-intersections-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/random-intersections-quartz-ref.png b/test/random-intersections-quartz-ref.png
new file mode 100644
index 0000000..a687088
Binary files /dev/null and b/test/random-intersections-quartz-ref.png differ
diff --git a/test/random-intersections-quartz-rgb24-ref.png b/test/random-intersections-quartz-rgb24-ref.png
new file mode 100644
index 0000000..77f73cd
Binary files /dev/null and b/test/random-intersections-quartz-rgb24-ref.png differ
diff --git a/test/rel-path-nquartz-ref.png b/test/rel-path-nquartz-ref.png
deleted file mode 100644
index 5878ce4..0000000
Binary files a/test/rel-path-nquartz-ref.png and /dev/null differ
diff --git a/test/rel-path-nquartz-rgb24-ref.png b/test/rel-path-nquartz-rgb24-ref.png
deleted file mode 100644
index 0e33b66..0000000
Binary files a/test/rel-path-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/rel-path-quartz-ref.png b/test/rel-path-quartz-ref.png
new file mode 100644
index 0000000..5878ce4
Binary files /dev/null and b/test/rel-path-quartz-ref.png differ
diff --git a/test/rel-path-quartz-rgb24-ref.png b/test/rel-path-quartz-rgb24-ref.png
new file mode 100644
index 0000000..0e33b66
Binary files /dev/null and b/test/rel-path-quartz-rgb24-ref.png differ
diff --git a/test/source-clip-scale-nquartz-ref.png b/test/source-clip-scale-nquartz-ref.png
deleted file mode 100644
index f21ae4b..0000000
Binary files a/test/source-clip-scale-nquartz-ref.png and /dev/null differ
diff --git a/test/source-clip-scale-quartz-ref.png b/test/source-clip-scale-quartz-ref.png
new file mode 100644
index 0000000..f21ae4b
Binary files /dev/null and b/test/source-clip-scale-quartz-ref.png differ
diff --git a/test/trap-clip-nquartz-ref.png b/test/trap-clip-nquartz-ref.png
deleted file mode 100644
index 28f5977..0000000
Binary files a/test/trap-clip-nquartz-ref.png and /dev/null differ
diff --git a/test/trap-clip-nquartz-rgb24-ref.png b/test/trap-clip-nquartz-rgb24-ref.png
deleted file mode 100644
index 24da4b9..0000000
Binary files a/test/trap-clip-nquartz-rgb24-ref.png and /dev/null differ
diff --git a/test/trap-clip-quartz-ref.png b/test/trap-clip-quartz-ref.png
new file mode 100644
index 0000000..28f5977
Binary files /dev/null and b/test/trap-clip-quartz-ref.png differ
diff --git a/test/trap-clip-quartz-rgb24-ref.png b/test/trap-clip-quartz-rgb24-ref.png
new file mode 100644
index 0000000..24da4b9
Binary files /dev/null and b/test/trap-clip-quartz-rgb24-ref.png differ
diff-tree be451cd83d8178bfaf28a1c7dec59601d97cff8d (from 4c201723ce8139c2e6620881583bc08e3aa1bad7)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 20 12:54:03 2007 -0800

    [quartz] rename NQUARTZ -> QUARTZ in defines

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index c25b3d4..ae83690 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -72,7 +72,6 @@ target_is_measurable (cairo_boilerplate_
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR > 2)
-    case CAIRO_SURFACE_TYPE_NQUARTZ:
     case CAIRO_SURFACE_TYPE_OS2:
 #endif
 	return TRUE;
diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index f053bc0..862554f 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -1,6 +1,7 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Calum Robinson
+ * Copyright (C) 2006,2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -31,6 +32,7 @@
  *
  * Contributor(s):
  *    Calum Robinson <calumr at mac.com>
+ *    Vladimir Vukicevic <vladimir at mozilla.com>
  */
 
 #ifndef CAIRO_QUARTZ_PRIVATE_H
@@ -39,7 +41,7 @@
 #include <cairoint.h>
 #include <cairo-quartz.h>
 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
 #include <AGL/agl.h>
 #include <OpenGL/gl.h>
 
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 0745d89..2f86203 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -37,7 +37,7 @@
 #include <Carbon/Carbon.h>
 
 /* Support rendering to an OpenGL AGL context using CGGLContextCreate;
- * Apple has deprecated CGGLContext, so CAIRO_NQUARTZ_SUPPORT_AGL is
+ * Apple has deprecated CGGLContext, so CAIRO_QUARTZ_SUPPORT_AGL is
  * not defined by default.
  */
 
@@ -46,9 +46,9 @@
 
 #include "cairo-quartz-private.h"
 
-#undef NQUARTZ_DEBUG
+#undef QUARTZ_DEBUG
 
-#ifdef NQUARTZ_DEBUG
+#ifdef QUARTZ_DEBUG
 #define ND(_x)	fprintf _x
 #else
 #define ND(_x)	do {} while(0)
@@ -585,7 +585,7 @@ _cairo_nquartz_cairo_repeating_surface_p
      */
     ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM);
 
-#ifdef NQUARTZ_DEBUG
+#ifdef QUARTZ_DEBUG
     ND((stderr, "  pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height));
     ND((stderr, "  pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d));
     CGAffineTransform xform = CGContextGetCTM(dest->cgContext);
@@ -766,7 +766,7 @@ _cairo_nquartz_get_image (cairo_nquartz_
      * or a CCGBitmapContext, then we have no way
      * of doing this
      */
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
     if (surface->aglContext) {
 	AGLContext oldContext;
 	cairo_format_masks_t masks = { 32, 0xff << 24, 0xff << 16, 0xff << 8, 0xff << 0 };
@@ -898,7 +898,7 @@ _cairo_nquartz_surface_finish (void *abs
 
     ND((stderr, "_cairo_nquartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
     if (surface->aglContext)
 	aglSetCurrentContext(surface->aglContext);
 #endif
@@ -912,7 +912,7 @@ _cairo_nquartz_surface_finish (void *abs
 
     surface->cgContext = NULL;
 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
     if (surface->aglContext)
 	glFlush();
 
@@ -1571,7 +1571,7 @@ _cairo_nquartz_surface_create_internal (
     return surface;
 }
 					 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
 cairo_surface_t *
 cairo_quartz_surface_create_for_agl_context (AGLContext aglContext,
 					     unsigned int width,
@@ -1768,7 +1768,7 @@ cairo_quartz_surface_get_cg_context (cai
 
 /* Debug stuff */
 
-#ifdef NQUARTZ_DEBUG
+#ifdef QUARTZ_DEBUG
 
 #include <Movies.h>
 
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index d0d87c2..e4bed43 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -33,8 +33,8 @@
  *      Vladimir Vukicevic <vladimir at mozilla.com>
  */
 
-#ifndef CAIRO_NQUARTZ_H
-#define CAIRO_NQUARTZ_H
+#ifndef CAIRO_QUARTZ_H
+#define CAIRO_QUARTZ_H
 
 #include <cairo.h>
 
@@ -42,7 +42,7 @@
 
 #include <Carbon/Carbon.h>
 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
 #include <AGL/agl.h>
 #endif
 
@@ -53,7 +53,7 @@ cairo_quartz_surface_create (cairo_forma
                              unsigned int width,
                              unsigned int height);
 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#ifdef CAIRO_QUARTZ_SUPPORT_AGL
 cairo_public cairo_surface_t *
 cairo_quartz_surface_create_for_agl_context (AGLContext aglContext,
                                              unsigned int width,
@@ -74,4 +74,4 @@ CAIRO_END_DECLS
 # error Cairo was not compiled with support for the quartz backend
 #endif /* CAIRO_HAS_QUARTZ_SURFACE */
 
-#endif /* CAIRO_NQUARTZ_H */
+#endif /* CAIRO_QUARTZ_H */
diff-tree 4c201723ce8139c2e6620881583bc08e3aa1bad7 (from 641f0919d53691e561aa665d31cc43524d861215)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 20 12:15:35 2007 -0800

    [quartz] Rename nquartz to quartz

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 322a1c4..aff747e 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -700,31 +700,17 @@ cleanup_cairo_glitz_wgl (void *closure)
 
 #endif /* CAIRO_HAS_GLITZ_SURFACE */
 
-#if 0 && CAIRO_HAS_QUARTZ_SURFACE
-static cairo_surface_t *
-create_quartz_surface (int width, int height, void **closure)
-{
-#error Not yet implemented
-}
-
-static void
-cleanup_quartz (void *closure)
-{
-#error Not yet implemented
-}
-#endif
+#if CAIRO_HAS_QUARTZ_SURFACE
 
-#if CAIRO_HAS_NQUARTZ_SURFACE
-
-#include <cairo-nquartz.h>
+#include <cairo-quartz.h>
 
 static cairo_surface_t *
-create_nquartz_surface (const char		 *name,
-			cairo_content_t		  content,
-			int			  width,
-			int			  height,
-			cairo_boilerplate_mode_t  mode,
-			void **closure)
+create_quartz_surface (const char		*name,
+		       cairo_content_t		 content,
+		       int			 width,
+		       int			 height,
+		       cairo_boilerplate_mode_t  mode,
+		       void **closure)
 {
     cairo_format_t format;
 
@@ -739,11 +725,11 @@ create_nquartz_surface (const char		 *na
 
     *closure = NULL;
 
-    return cairo_nquartz_surface_create (format, width, height);
+    return cairo_quartz_surface_create (format, width, height);
 }
 
 static void
-cleanup_nquartz (void *closure)
+cleanup_quartz (void *closure)
 {
     /* nothing */
 }
@@ -1430,19 +1416,14 @@ cairo_boilerplate_target_t targets[] =
       cleanup_cairo_glitz_wgl },
 #endif
 #endif /* CAIRO_HAS_GLITZ_SURFACE */
-#if 0 && CAIRO_HAS_QUARTZ_SURFACE
+#if CAIRO_HAS_QUARTZ_SURFACE
+    { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
+      create_quartz_surface, cairo_surface_write_to_png,
+      cleanup_quartz },
     { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR, 0,
       create_quartz_surface, cairo_surface_write_to_png,
       cleanup_quartz },
 #endif
-#if CAIRO_HAS_NQUARTZ_SURFACE
-    { "nquartz", CAIRO_SURFACE_TYPE_NQUARTZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      create_nquartz_surface, cairo_surface_write_to_png,
-      cleanup_nquartz },
-    { "nquartz", CAIRO_SURFACE_TYPE_NQUARTZ, CAIRO_CONTENT_COLOR, 0,
-      create_nquartz_surface, cairo_surface_write_to_png,
-      cleanup_nquartz },
-#endif
 #if CAIRO_HAS_WIN32_SURFACE
     { "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 0,
       create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
diff --git a/configure.in b/configure.in
index fad10a6..b274a21 100644
--- a/configure.in
+++ b/configure.in
@@ -278,12 +278,6 @@ CAIRO_BACKEND_ENABLE(quartz, Quartz, qua
   quartz_LIBS="-Xlinker -framework -Xlinker Carbon"
 ])
 
-CAIRO_BACKEND_ENABLE(nquartz, NativeQuartz, nquartz, NQUARTZ_SURFACE, no, [
-  dnl There is no pkgconfig for quartz; lets do a header check
-  AC_CHECK_HEADER(Carbon/Carbon.h, , [use_nquartz="no (Carbon headers not found)"])
-  quartz_LIBS="-Xlinker -framework -Xlinker Carbon"
-])
-
 dnl ===========================================================================
 
 AC_MSG_CHECKING([for native Win32])
@@ -889,7 +883,6 @@ echo "  image:         yes (always built
 echo "  Xlib:          $use_xlib"
 echo "  Xlib Xrender:  $use_xlib_xrender"
 echo "  Quartz:        $use_quartz"
-echo "  Native Quartz: $use_nquartz"
 echo "  XCB:           $use_xcb"
 echo "  Win32:         $use_win32"
 echo "  OS2:           $use_os2"
diff --git a/src/Makefile.am b/src/Makefile.am
index 259a2f3..4a24ac2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,12 +66,6 @@ libcairo_quartz_sources = cairo-quartz-s
 backend_pkgconfigs += cairo-quartz.pc
 endif
 
-if CAIRO_HAS_NQUARTZ_SURFACE
-libcairo_nquartz_headers = cairo-nquartz.h
-libcairo_nquartz_sources = cairo-nquartz-surface.c cairo-quartz-private.h
-backend_pkgconfigs += cairo-nquartz.pc
-endif
-
 if OS_WIN32
 export_symbols = -export-symbols cairo.def
 cairo_def_dependency = cairo.def
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index f6eb3a9..fff7a22 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -935,7 +935,7 @@ _cairo_atsui_font_old_show_glyphs (void	
     CGFontRef cgFont;
     CGAffineTransform textTransform;
 
-    if (!_cairo_surface_is_quartz (generic_surface))
+    if (cairo_surface_get_type (generic_surface) != CAIRO_SURFACE_TYPE_QUARTZ)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* Check if we can draw directly to the destination surface */
@@ -961,7 +961,7 @@ _cairo_atsui_font_old_show_glyphs (void	
 	CGContextTranslateCTM(drawingContext, 0, destImageSurface->height);
 	CGContextScaleCTM(drawingContext, 1.0f, -1.0f);
     } else {
-	drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
+	drawingContext = ((cairo_quartz_surface_t *)generic_surface)->cgContext;
 	CGContextSaveGState (drawingContext);
     }
 
@@ -992,35 +992,6 @@ _cairo_atsui_font_old_show_glyphs (void	
 	CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
     }
 
-    if (surface->clip_region) {
-	pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
-	int num_boxes = pixman_region_num_rects (surface->clip_region);
-	CGRect stack_rects[10];
-	CGRect *rects;
-	int i;
-	
-	/* XXX: Return-value of malloc needs to be checked for
-	 * NULL. Can someone fix this who is more familiar with
-	 * the cleanup needed in this function?
-	 */
-	if (num_boxes > 10)
-	    rects = malloc (sizeof (CGRect) * num_boxes);
-	else
-	    rects = stack_rects;
-	
-	for (i = 0; i < num_boxes; i++) {
-	    rects[i].origin.x = boxes[i].x1;
-	    rects[i].origin.y = boxes[i].y1;
-	    rects[i].size.width = boxes[i].x2 - boxes[i].x1;
-	    rects[i].size.height = boxes[i].y2 - boxes[i].y1;
-	}
-	
-	CGContextClipToRects (drawingContext, rects, num_boxes);
-	
-	if (rects != stack_rects)
-	    free(rects);
-    }
-
     /* TODO - bold and italic text
      *
      * We could draw the text using ATSUI and get bold, italics
diff --git a/src/cairo-nquartz-surface.c b/src/cairo-nquartz-surface.c
deleted file mode 100644
index dd05c38..0000000
--- a/src/cairo-nquartz-surface.c
+++ /dev/null
@@ -1,1864 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2006 Mozilla 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Mozilla Corporation.
- *
- * Contributor(s):
- *	Vladimir Vukicevic <vladimir at mozilla.com>
- */
-
-#include <Carbon/Carbon.h>
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-#include <AGL/agl.h>
-#include <OpenGL/gl.h>
-#endif
-
-#include "cairoint.h"
-#include "cairo-private.h"
-#include "cairo-nquartz.h"
-
-#include "cairo-quartz-private.h"
-
-#undef NQUARTZ_DEBUG
-
-#ifdef NQUARTZ_DEBUG
-#define ND(_x)	fprintf _x
-#else
-#define ND(_x)	do {} while(0)
-#endif
-
-/* This method is private, but it exists.  Its params are are exposed
- * as args to the NS* method, but not as CG.
- */
-enum PrivateCGCompositeMode {
-    kPrivateCGCompositeClear		= 0,
-    kPrivateCGCompositeCopy		= 1,
-    kPrivateCGCompositeSourceOver	= 2,
-    kPrivateCGCompositeSourceIn		= 3,
-    kPrivateCGCompositeSourceOut	= 4,
-    kPrivateCGCompositeSourceAtop	= 5,
-    kPrivateCGCompositeDestinationOver	= 6,
-    kPrivateCGCompositeDestinationIn	= 7,
-    kPrivateCGCompositeDestinationOut	= 8,
-    kPrivateCGCompositeDestinationAtop	= 9,
-    kPrivateCGCompositeXOR		= 10,
-    kPrivateCGCompositePlusDarker	= 11, // (max (0, (1-d) + (1-s)))
-    kPrivateCGCompositePlusLighter	= 12, // (min (1, s + d))
-};
-typedef enum PrivateCGCompositeMode PrivateCGCompositeMode;
-CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
-CG_EXTERN void CGContextResetCTM (CGContextRef);
-CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform);
-CG_EXTERN void CGContextResetClip (CGContextRef);
-CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
-
-/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
- * has all the stuff we care about, just some of it isn't exported in the SDK.
- */ 
-#ifndef kCGBitmapByteOrder32Host
-#define USE_10_3_WORKAROUNDS
-#define kCGBitmapAlphaInfoMask 0x1F
-#define kCGBitmapByteOrderMask 0x7000
-#define kCGBitmapByteOrder32Host 0
-
-typedef uint32_t CGBitmapInfo;
-
-/* public in 10.4, present in 10.3.9 */
-CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
-CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
-#endif
-
-
-typedef struct cairo_nquartz_surface {
-    cairo_surface_t base;
-
-    void *imageData;
-
-    CGContextRef cgContext;
-    CGAffineTransform cgContextBaseCTM;
-
-    cairo_rectangle_int16_t extents;
-
-    /* These are stored while drawing operations are in place, set up
-     * by nquartz_setup_source() and nquartz_finish_source()
-     */
-    CGAffineTransform imageTransform;
-    CGImageRef sourceImage;
-    CGShadingRef sourceShading;
-    CGPatternRef sourcePattern;
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    AGLContext aglContext;
-#else
-    void *_unused;
-#endif
-} cairo_nquartz_surface_t;
-
-/**
- ** Utility functions
- **/
-
-void nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest);
-void nquartz_image_to_png (CGImageRef, char *dest);
-
-/*
- * Cairo path -> Quartz path conversion helpers
- */
-
-/* cairo path -> mutable path */
-static cairo_status_t
-_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
-{
-    CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
-		       _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
-{
-    CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
-			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
-{
-    CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
-			   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-			   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-			   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_path_close_path (void *closure)
-{
-    CGPathCloseSubpath ((CGMutablePathRef) closure);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* cairo path -> execute in context */
-static cairo_status_t
-_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
-{
-    //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    CGContextMoveToPoint ((CGContextRef) closure,
-			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
-{
-    //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    if (CGContextIsPathEmpty ((CGContextRef) closure))
-	CGContextMoveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    else
-	CGContextAddLineToPoint ((CGContextRef) closure,
-				 _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
-{
-    //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n",
-    //		   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-    //		   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-    //		   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
-
-    CGContextAddCurveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-			      _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-			      _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_path_to_quartz_context_close_path (void *closure)
-{
-    //ND((stderr, "closepath\n"));
-    CGContextClosePath ((CGContextRef) closure);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_nquartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
-					  CGMutablePathRef cgPath)
-{
-    return _cairo_path_fixed_interpret (path,
-					CAIRO_DIRECTION_FORWARD,
-					_cairo_path_to_quartz_path_move_to,
-					_cairo_path_to_quartz_path_line_to,
-					_cairo_path_to_quartz_path_curve_to,
-					_cairo_path_to_quartz_path_close_path,
-					cgPath);
-}
-
-static cairo_status_t
-_cairo_nquartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
-					     CGContextRef cgc)
-{
-    return _cairo_path_fixed_interpret (path,
-					CAIRO_DIRECTION_FORWARD,
-					_cairo_path_to_quartz_context_move_to,
-					_cairo_path_to_quartz_context_line_to,
-					_cairo_path_to_quartz_context_curve_to,
-					_cairo_path_to_quartz_context_close_path,
-					cgc);
-}
-
-/*
- * Misc helpers/callbacks
- */
-
-static PrivateCGCompositeMode
-_cairo_nquartz_cairo_operator_to_quartz (cairo_operator_t op)
-{
-    switch (op) {
-	case CAIRO_OPERATOR_CLEAR:
-	    return kPrivateCGCompositeClear;
-	case CAIRO_OPERATOR_SOURCE:
-	    return kPrivateCGCompositeCopy;
-	case CAIRO_OPERATOR_OVER:
-	    return kPrivateCGCompositeSourceOver;
-	case CAIRO_OPERATOR_IN:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeSourceIn;
-	case CAIRO_OPERATOR_OUT:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeSourceOut;
-	case CAIRO_OPERATOR_ATOP:
-	    return kPrivateCGCompositeSourceAtop;
-
-	case CAIRO_OPERATOR_DEST:
-	    /* XXX this is handled specially (noop)! */
-	    return kPrivateCGCompositeCopy;
-	case CAIRO_OPERATOR_DEST_OVER:
-	    return kPrivateCGCompositeDestinationOver;
-	case CAIRO_OPERATOR_DEST_IN:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeDestinationIn;
-	case CAIRO_OPERATOR_DEST_OUT:
-	    return kPrivateCGCompositeDestinationOut;
-	case CAIRO_OPERATOR_DEST_ATOP:
-	    /* XXX This doesn't match image output */
-	    return kPrivateCGCompositeDestinationAtop;
-
-	case CAIRO_OPERATOR_XOR:
-	    return kPrivateCGCompositeXOR; /* This will generate strange results */
-	case CAIRO_OPERATOR_ADD:
-	    return kPrivateCGCompositePlusLighter;
-	case CAIRO_OPERATOR_SATURATE:
-	    /* XXX This doesn't match image output for SATURATE; there's no equivalent */
-	    return kPrivateCGCompositePlusDarker;  /* ??? */
-    }
-
-
-    return kPrivateCGCompositeCopy;
-}
-
-static CGLineCap
-_cairo_nquartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap)
-{
-    switch (ccap) {
-	case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break;
-	case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break;
-	case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break;
-    }
-
-    return kCGLineCapButt;
-}
-
-static CGLineJoin
-_cairo_nquartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin)
-{
-    switch (cjoin) {
-	case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break;
-	case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break;
-	case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break;
-    }
-
-    return kCGLineJoinMiter;
-}
-
-static void
-_cairo_nquartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
-				       CGAffineTransform *dst)
-{
-    dst->a = src->xx;
-    dst->b = src->xy;
-    dst->c = src->yx;
-    dst->d = src->yy;
-    dst->tx = src->x0;
-    dst->ty = src->y0;
-}
-
-/**
- ** Source -> Quartz setup and finish functions
- **/
-
-static void
-ComputeGradientValue (void *info, const float *in, float *out)
-{
-    float fdist = *in; /* 0.0 .. 1.0 */
-    cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
-    cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
-    int i;
-
-    for (i = 0; i < grad->n_stops; i++) {
-	if (grad->stops[i].x > fdist_fix)
-	    break;
-    }
-
-    if (i == 0 || i == grad->n_stops) {
-	if (i == grad->n_stops)
-	    --i;
-	out[0] = grad->stops[i].color.red / 65535.;
-	out[1] = grad->stops[i].color.green / 65535.;
-	out[2] = grad->stops[i].color.blue / 65535.;
-	out[3] = grad->stops[i].color.alpha / 65535.;
-    } else {
-	float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
-	float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
-	float bp = (fdist - ax)/bx;
-	float ap = 1.0 - bp;
-
-	out[0] =
-	    (grad->stops[i-1].color.red / 65535.) * ap +
-	    (grad->stops[i].color.red / 65535.) * bp;
-	out[1] =
-	    (grad->stops[i-1].color.green / 65535.) * ap +
-	    (grad->stops[i].color.green / 65535.) * bp;
-	out[2] =
-	    (grad->stops[i-1].color.blue / 65535.) * ap +
-	    (grad->stops[i].color.blue / 65535.) * bp;
-	out[3] =
-	    (grad->stops[i-1].color.alpha / 65535.) * ap +
-	    (grad->stops[i].color.alpha / 65535.) * bp;
-    }
-}
-
-static CGFunctionRef
-CreateGradientFunction (cairo_gradient_pattern_t *gpat)
-{
-    static const float input_value_range[2] = { 0.f, 1.f };
-    static const float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f };
-    static const CGFunctionCallbacks callbacks = {
-	0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
-    };
-
-    return CGFunctionCreate (gpat,
-			     1,
-			     input_value_range,
-			     4,
-			     output_value_ranges,
-			     &callbacks);
-}
-
-static CGShadingRef
-_cairo_nquartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
-{
-    cairo_matrix_t mat;
-    double x0, y0;
-
-    if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
-	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
-	return NULL;
-
-    /* We can only do this if we have an identity pattern matrix;
-     * otherwise fall back through to the generic pattern case.
-     * XXXperf we could optimize this by creating a pattern with the shading;
-     * but we'd need to know the extents to do that.
-     * ... but we don't care; we can use the surface extents for it
-     * XXXtodo - implement gradients with non-identity pattern matrices
-     */
-    cairo_pattern_get_matrix (abspat, &mat);
-    if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
-	return NULL;
-
-    x0 = mat.x0;
-    y0 = mat.y0;
-
-    if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) {
-	cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat;
-	CGShadingRef shading;
-	CGPoint start, end;
-	CGFunctionRef gradFunc;
-	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
-
-	start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
-			     _cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
-	end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0,
-			   _cairo_fixed_to_double (lpat->gradient.p2.y) - y0);
-
-	cairo_pattern_reference (abspat);
-	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
-	shading = CGShadingCreateAxial (rgb,
-					start, end,
-					gradFunc,
-					true, true);
-	CGColorSpaceRelease(rgb);
-	CGFunctionRelease(gradFunc);
-
-	return shading;
-    }
-
-    if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) {
-	cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat;
-	CGShadingRef shading;
-	CGPoint start, end;
-	CGFunctionRef gradFunc;
-	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
-
-	start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.inner.x) - x0,
-			     _cairo_fixed_to_double (rpat->gradient.inner.y) - y0);
-	end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.outer.x) - x0,
-			   _cairo_fixed_to_double (rpat->gradient.outer.y) - y0);
-
-	cairo_pattern_reference (abspat);
-	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
-	shading = CGShadingCreateRadial (rgb,
-					 start,
-					 _cairo_fixed_to_double (rpat->gradient.inner.radius),
-					 end,
-					 _cairo_fixed_to_double (rpat->gradient.outer.radius),
-					 gradFunc,
-					 true, true);
-	CGColorSpaceRelease(rgb);
-	CGFunctionRelease(gradFunc);
-
-	return shading;
-    }
-
-    /* Shouldn't be reached */
-    ASSERT_NOT_REACHED;
-    return NULL;
-}
-
-
-/* Generic cairo_pattern -> CGPattern function */
-static void
-SurfacePatternDrawFunc (void *info, CGContextRef context)
-{
-    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
-    cairo_surface_t *pat_surf = spat->surface;
-    cairo_rectangle_int16_t extents;
-    cairo_status_t status;
-
-    cairo_nquartz_surface_t *quartz_surf = NULL;
-
-    cairo_bool_t flip = FALSE;
-
-    CGImageRef img;
-
-    if (!cairo_surface_is_nquartz (pat_surf)) {
-	ND((stderr, "-- source is not nquartz surface\n"));
-	/* This sucks; we should really store a dummy nquartz surface
-	 * for passing in here
-	 * XXXtodo store a dummy nquartz surface somewhere for handing off to clone_similar
-	 * XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
-	 * just create the CGImage directly!
-	 */
-
-	cairo_surface_t *dummy = cairo_nquartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-
-	cairo_rectangle_int16_t rect;
-	_cairo_surface_get_extents (pat_surf, &rect);
-
-	cairo_surface_t *new_surf = NULL;
-
-	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
-				      rect.width, rect.height, &new_surf);
-
-	cairo_surface_destroy(dummy);
-
-	quartz_surf = (cairo_nquartz_surface_t *) new_surf;
-    } else {
-	ND((stderr, "-- source is nquartz surface\n"));
-	/* If it's a nquartz surface, we can try to see if it's a CGBitmapContext;
-	 * we do this when we call CGBitmapContextCreateImage below.
-	 */
-	cairo_surface_reference (pat_surf);
-	quartz_surf = (cairo_nquartz_surface_t*) pat_surf;
-
-	/* XXXtodo WHY does this need to be flipped?  Writing this stuff
-	 * to disk shows that in both this path and the path above the source image
-	 * has an identical orientation, and the destination context at all times has a Y
-	 * flip.  So why do we need to flip in this case?
-	 */
-	flip = TRUE;
-    }
-
-    /* this is a 10.4 API, present in 10.3.9 */
-    CGContextFlush (quartz_surf->cgContext);
-    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
-
-    if (!img) {
-	// ... give up.
-	ND((stderr, "CGBitmapContextCreateImage failed\n"));
-	cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
-	return;
-    }
-
-    if (flip) {
-	CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
-	CGContextScaleCTM (context, 1, -1);
-    }
-
-    CGRect imageBounds;
-    imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
-    imageBounds.origin.x = 0;
-    imageBounds.origin.y = 0;
-
-    CGContextDrawImage (context, imageBounds, img);
-
-    CGImageRelease (img);
-
-    cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
-}
-
-/* Borrowed from cairo-meta-surface */
-static cairo_status_t
-_init_pattern_with_snapshot (cairo_pattern_t *pattern,
-			     const cairo_pattern_t *other)
-{
-    _cairo_pattern_init_copy (pattern, other);
-
-    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_pattern_t *surface_pattern =
-	    (cairo_surface_pattern_t *) pattern;
-	cairo_surface_t *surface = surface_pattern->surface;
-
-	surface_pattern->surface = _cairo_surface_snapshot (surface);
-
-	cairo_surface_destroy (surface);
-
-	if (surface_pattern->surface->status)
-	    return surface_pattern->surface->status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static CGPatternRef
-_cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_t *dest,
-							  cairo_pattern_t *abspat)
-{
-    cairo_surface_pattern_t *spat;
-    cairo_surface_t *pat_surf;
-    cairo_rectangle_int16_t extents;
-
-    CGRect pbounds;
-    CGAffineTransform ptransform, stransform;
-    CGPatternCallbacks cb = { 0,
-			      SurfacePatternDrawFunc,
-			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
-    CGPatternRef cgpat;
-    float rw, rh;
-
-    cairo_pattern_union_t *snap_pattern = NULL;
-    cairo_pattern_t *target_pattern = abspat;
-
-    /* SURFACE is the only type we'll handle here */
-    if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
-	return NULL;
-
-    spat = (cairo_surface_pattern_t *) abspat;
-    pat_surf = spat->surface;
-
-    _cairo_surface_get_extents (pat_surf, &extents);
-    pbounds.origin.x = 0;
-    pbounds.origin.y = 0;
-    pbounds.size.width = extents.width;
-    pbounds.size.height = extents.height;
-
-    cairo_matrix_t m = spat->base.matrix;
-    cairo_matrix_invert(&m);
-    _cairo_nquartz_cairo_matrix_to_quartz (&m, &stransform);
-
-    /* The pattern matrix is relative to the bottom left, again; the
-     * incoming cairo pattern matrix is relative to the upper left.
-     * So we take the pattern matrix and the original context matrix,
-     * which gives us the correct base translation/y flip.
-     */
-    ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM);
-
-#ifdef NQUARTZ_DEBUG
-    ND((stderr, "  pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height));
-    ND((stderr, "  pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d));
-    CGAffineTransform xform = CGContextGetCTM(dest->cgContext);
-    ND((stderr, "  context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
-#endif
-
-    // kjs seems to indicate this should work (setting to 0,0 to avoid
-    // tiling); however, the pattern CTM scaling ends up being NaN in
-    // the pattern draw function if either rw or rh are 0.
-    // XXXtodo get pattern drawing working with extend options
-    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
-#if 0
-    if (spat->base.extend == CAIRO_EXTEND_NONE) {
-	/* XXX wasteful; this will keep drawing the pattern in the
-	 * original location.  We need to set up the clip region
-	 * instead to do this right.
-	 */
-	rw = 0;
-	rh = 0;
-    } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
-	rw = extents.width;
-	rh = extents.height;
-    } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
-	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
-	 * and then tiling that
-	 */
-	rw = extents.width;
-	rh = extents.height;
-    } else {
-	/* CAIRO_EXTEND_PAD */
-	/* XXX broken. */
-	rw = 0;
-	rh = 0;
-    }
-#else
-    rw = extents.width;
-    rh = extents.height;
-#endif
-
-    /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
-       other block if it doesn't fafect performance */
-    if (1 /* context is for printing */) {
-	snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
-	target_pattern = (cairo_pattern_t*) snap_pattern;
-	_init_pattern_with_snapshot (snap_pattern, abspat);
-    } else {
-	cairo_pattern_reference (abspat);
-	target_pattern = abspat;
-    }
-
-    cgpat = CGPatternCreate (target_pattern,
-			     pbounds,
-			     ptransform,
-			     rw, rh,
-			     kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
-			     TRUE,
-			     &cb);
-    return cgpat;
-}
-
-typedef enum {
-    DO_SOLID,
-    DO_SHADING,
-    DO_PATTERN,
-    DO_UNSUPPORTED
-} cairo_nquartz_action_t;
-
-static cairo_nquartz_action_t
-_cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
-			     cairo_pattern_t *source)
-{
-    assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
-
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-
-	CGContextSetRGBStrokeColor (surface->cgContext,
-				    solid->color.red,
-				    solid->color.green,
-				    solid->color.blue,
-				    solid->color.alpha);
-	CGContextSetRGBFillColor (surface->cgContext,
-				  solid->color.red,
-				  solid->color.green,
-				  solid->color.blue,
-				  solid->color.alpha);
-
-	return DO_SOLID;
-    } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR ||
-	       source->type == CAIRO_PATTERN_TYPE_RADIAL)
-    {
-	CGShadingRef shading = _cairo_nquartz_cairo_gradient_pattern_to_quartz (source);
-	if (!shading)
-	    return DO_UNSUPPORTED;
-
-	surface->sourceShading = shading;
-
-	return DO_SHADING;
-    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-	CGPatternRef pattern = _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
-	if (!pattern)
-	    return DO_UNSUPPORTED;
-
-	float patternAlpha = 1.0f;
-
-	// Save before we change the pattern, colorspace, etc. so that
-	// we can restore and make sure that quartz releases our
-	// pattern (which may be stack allocated)
-	CGContextSaveGState(surface->cgContext);
-
-	CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
-	CGContextSetFillColorSpace (surface->cgContext, patternSpace);
-	CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
-	CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
-	CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha);
-	CGColorSpaceRelease (patternSpace);
-
-	/* Quartz likes to munge the pattern phase (as yet unexplained
-	 * why); force it to 0,0 as we've already baked in the correct
-	 * pattern translation into the pattern matrix
-	 */
-	CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0));
-
-	surface->sourcePattern = pattern;
-
-	return DO_PATTERN;
-    } else {
-	return DO_UNSUPPORTED;
-    }
-
-    ASSERT_NOT_REACHED;
-}
-
-static void
-_cairo_nquartz_teardown_source (cairo_nquartz_surface_t *surface,
-				cairo_pattern_t *source)
-{
-    if (surface->sourceImage) {
-	// nothing to do; we don't use sourceImage yet
-    }
-
-    if (surface->sourceShading) {
-	CGShadingRelease(surface->sourceShading);
-	surface->sourceShading = NULL;
-    }
-
-    if (surface->sourcePattern) {
-	CGPatternRelease(surface->sourcePattern);
-	// To tear down the pattern and colorspace
-	CGContextRestoreGState(surface->cgContext);
-
-	surface->sourcePattern = NULL;
-    }
-}
-
-/**
- ** get source/dest image implementation
- **/
-
-static void
-ImageDataReleaseFunc(void *info, const void *data, size_t size)
-{
-    if (data != NULL) {
-	free((void *) data);
-    }
-}
-
-/* Read the image from the surface's front buffer */
-static cairo_int_status_t
-_cairo_nquartz_get_image (cairo_nquartz_surface_t *surface,
-			  cairo_image_surface_t **image_out,
-			  unsigned char **data_out)
-{
-    unsigned char *imageData;
-    cairo_image_surface_t *isurf;
-
-    /* If we weren't constructed with an AGL Context
-     * or a CCGBitmapContext, then we have no way
-     * of doing this
-     */
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext) {
-	AGLContext oldContext;
-	cairo_format_masks_t masks = { 32, 0xff << 24, 0xff << 16, 0xff << 8, 0xff << 0 };
-	unsigned int i;
-
-	oldContext = aglGetCurrentContext();
-	if (oldContext != surface->aglContext)
-	    aglSetCurrentContext(surface->aglContext);
-
-	imageData = (unsigned char *) malloc (surface->extents.width * surface->extents.height * 4);
-	if (!imageData)
-	    return CAIRO_STATUS_NO_MEMORY;
-
-	glReadBuffer (GL_FRONT);
-	glReadPixels (0, 0, surface->extents.width, surface->extents.height,
-		      GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
-		      imageData);
-
-	/* swap lines */
-	/* XXX find some fast code to do this */
-	unsigned int lineSize = surface->extents.width * 4;
-	unsigned char *tmpLine = malloc(lineSize);
-	for (i = 0; i < surface->extents.height / 2; i++) {
-	    unsigned char *l0 = imageData + lineSize * i;
-	    unsigned char *l1 = imageData + (lineSize * (surface->extents.height - i - 1));
-	    memcpy (tmpLine, l0, lineSize);
-	    memcpy (l0, l1, lineSize);
-	    memcpy (l1, tmpLine, lineSize);
-	}
-	free (tmpLine);
-
-	if (oldContext && oldContext != surface->aglContext)
-	    aglSetCurrentContext(oldContext);
-
-	isurf = (cairo_image_surface_t *)_cairo_image_surface_create_with_masks
-	    (imageData,
-	     &masks,
-	     surface->extents.width,
-	     surface->extents.height,
-	     surface->extents.width * 4);
-
-	if (data_out)
-	    *data_out = imageData;
-	else
-	    _cairo_image_surface_assume_ownership_of_data (isurf);
-#else
-    /* no AGL */
-    if (0) {
-#endif
-    } else if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) {
-	unsigned int stride;
-	unsigned int bitinfo;
-	unsigned int bpc, bpp;
-	CGColorSpaceRef colorspace;
-	unsigned int color_comps;
-
-	imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
-#ifdef USE_10_3_WORKAROUNDS
-	bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
-#else
-	bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
-#endif
-	stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
-	bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
-	bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
-
-	// let's hope they don't add YUV under us
-	colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
-	color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
-
-	// XXX TODO: We can handle all of these by converting to
-	// pixman masks, including non-native-endian masks
-	if (bpc != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (bpp != 32 && bpp != 8)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (color_comps != 3 && color_comps != 1)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (bpp == 32 && color_comps == 3 &&
-	    (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
-	    (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_ARGB32,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 32 && color_comps == 3 &&
-		   (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
-		   (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_RGB24,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else if (bpp == 8 && color_comps == 1)
-	{
-	    isurf = (cairo_image_surface_t *)
-		cairo_image_surface_create_for_data (imageData,
-						     CAIRO_FORMAT_A8,
-						     surface->extents.width,
-						     surface->extents.height,
-						     stride);
-	} else {
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    *image_out = isurf;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/**
- ** Cairo surface backend implementations
- **/
-
-static cairo_status_t
-_cairo_nquartz_surface_finish (void *abstract_surface)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    ND((stderr, "_cairo_nquartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext)
-	aglSetCurrentContext(surface->aglContext);
-#endif
-
-    CGContextFlush (surface->cgContext);
-
-    /* Restore our saved gstate that we use to reset clipping */
-    CGContextRestoreGState (surface->cgContext);
-
-    CGContextRelease (surface->cgContext);
-
-    surface->cgContext = NULL;
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    if (surface->aglContext)
-	glFlush();
-
-    surface->aglContext = NULL;
-#endif
-
-    if (surface->imageData) {
-	free (surface->imageData);
-	surface->imageData = NULL;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_acquire_source_image (void *abstract_surface,
-					     cairo_image_surface_t **image_out,
-					     void **image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    //ND((stderr, "%p _cairo_nquartz_surface_acquire_source_image\n", surface));
-
-    *image_extra = NULL;
-
-    return _cairo_nquartz_get_image (surface, image_out, NULL);
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_acquire_dest_image (void *abstract_surface,
-					   cairo_rectangle_int16_t *interest_rect,
-					   cairo_image_surface_t **image_out,
-					   cairo_rectangle_int16_t *image_rect,
-					   void **image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t status;
-    unsigned char *data;
-
-    ND((stderr, "%p _cairo_nquartz_surface_acquire_dest_image\n", surface));
-
-    *image_rect = surface->extents;
-
-    status = _cairo_nquartz_get_image (surface, image_out, &data);
-    if (status)
-	return status;
-
-    *image_extra = data;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_nquartz_surface_release_dest_image (void *abstract_surface,
-					   cairo_rectangle_int16_t *interest_rect,
-					   cairo_image_surface_t *image,
-					   cairo_rectangle_int16_t *image_rect,
-					   void *image_extra)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    unsigned char *imageData = (unsigned char *) image_extra;
-
-    //ND((stderr, "%p _cairo_nquartz_surface_release_dest_image\n", surface));
-
-    if (!CGBitmapContextGetData (surface->cgContext)) {
-	CGDataProviderRef dataProvider;
-	CGImageRef img;
-
-	dataProvider = CGDataProviderCreateWithData (NULL, imageData,
-						     surface->extents.width * surface->extents.height * 4,
-						     ImageDataReleaseFunc);
-
-	img = CGImageCreate (surface->extents.width, surface->extents.height,
-			     8, 32,
-			     surface->extents.width * 4,
-			     CGColorSpaceCreateDeviceRGB(),
-			     kCGImageAlphaPremultipliedFirst,
-			     dataProvider,
-			     NULL,
-			     false,
-			     kCGRenderingIntentDefault);
-
-	CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy);
-
-	CGContextDrawImage (surface->cgContext,
-			    CGRectMake (0, 0, surface->extents.width, surface->extents.height),
-			    img);
-
-	CGImageRelease (img);
-	CGDataProviderRelease (dataProvider);
-
-	ND((stderr, "Image for surface %p was recovered from a bitmap\n", surface));
-    }
-
-    cairo_surface_destroy ((cairo_surface_t *) image);
-}
-
-static cairo_surface_t *
-_cairo_nquartz_surface_create_similar (void *abstract_surface,
-				       cairo_content_t content,
-				       int width,
-				       int height)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    cairo_format_t format;
-
-    if (content == CAIRO_CONTENT_COLOR_ALPHA)
-	format = CAIRO_FORMAT_ARGB32;
-    else if (content == CAIRO_CONTENT_COLOR)
-	format = CAIRO_FORMAT_RGB24;
-    else if (content == CAIRO_CONTENT_ALPHA)
-	format = CAIRO_FORMAT_A8;
-    else
-	return NULL;
-
-    return cairo_nquartz_surface_create (format, width, height);
-}
-
-static cairo_status_t
-_cairo_nquartz_surface_clone_similar (void *abstract_surface,
-				      cairo_surface_t *src,
-				      int              src_x,
-				      int              src_y,
-				      int              width,
-				      int              height,
-				      cairo_surface_t **clone_out)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_nquartz_surface_t *new_surface = NULL;
-    cairo_format_t new_format;
-
-    CGImageRef quartz_image = NULL;
-    cairo_surface_t *surface_to_release = NULL;
-
-    if (cairo_surface_is_nquartz (src)) {
-	cairo_nquartz_surface_t *qsurf = (cairo_nquartz_surface_t *) src;
-	quartz_image = CGBitmapContextCreateImage (qsurf->cgContext);
-	new_format = CAIRO_FORMAT_ARGB32;  /* XXX bogus; recover a real format from the image */
-    } else if (_cairo_surface_is_image (src)) {
-	cairo_image_surface_t *isurf = (cairo_image_surface_t *) src;
-	CGDataProviderRef dataProvider;
-	CGColorSpaceRef cgColorspace;
-	CGBitmapInfo bitinfo;
-	int bitsPerComponent, bitsPerPixel;
-
-	if (isurf->format == CAIRO_FORMAT_ARGB32) {
-	    cgColorspace = CGColorSpaceCreateDeviceRGB();
-	    bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 32;
-	} else if (isurf->format == CAIRO_FORMAT_RGB24) {
-	    cgColorspace = CGColorSpaceCreateDeviceRGB();
-	    bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 32;
-	} else if (isurf->format == CAIRO_FORMAT_A8) {
-	    cgColorspace = CGColorSpaceCreateDeviceGray();
-	    bitinfo = kCGImageAlphaNone;
-	    bitsPerComponent = 8;
-	    bitsPerPixel = 8;
-	} else {
-	    /* SUPPORT A1, maybe */
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-
-	new_format = isurf->format;
-
-	dataProvider = CGDataProviderCreateWithData (NULL,
-						     isurf->data,
-						     isurf->height * isurf->stride,
-						     NULL);
-
-	quartz_image = CGImageCreate (isurf->width, isurf->height,
-				      bitsPerComponent,
-				      bitsPerPixel,
-				      isurf->stride,
-				      cgColorspace,
-				      bitinfo,
-				      dataProvider,
-				      NULL,
-				      false,
-				      kCGRenderingIntentDefault);
-	CGDataProviderRelease (dataProvider);
-	CGColorSpaceRelease (cgColorspace);
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    if (!quartz_image)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    new_surface = (cairo_nquartz_surface_t *)
-	cairo_nquartz_surface_create (new_format,
-				      CGImageGetWidth (quartz_image),
-				      CGImageGetHeight (quartz_image));
-    if (!new_surface || new_surface->base.status)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    CGContextSetCompositeOperation (new_surface->cgContext,
-				    kPrivateCGCompositeCopy);
-
-    nquartz_image_to_png (quartz_image, NULL);
-
-    CGContextDrawImage (new_surface->cgContext,
-			CGRectMake (src_x, src_y, width, height),
-			quartz_image);
-    CGImageRelease (quartz_image);
-
-    *clone_out = (cairo_surface_t*) new_surface;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_get_extents (void *abstract_surface,
-				    cairo_rectangle_int16_t *extents)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    *extents = surface->extents;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_paint (void *abstract_surface,
-			      cairo_operator_t op,
-			      cairo_pattern_t *source)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_paint op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    CGRect bounds = CGContextGetClipBoundingBox (surface->cgContext);
-
-    action = _cairo_nquartz_setup_source (surface, source);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
-							  surface->extents.y,
-							  surface->extents.width,
-							  surface->extents.height));
-    } else if (action == DO_SHADING) {
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    ND((stderr, "-- paint\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_fill (void *abstract_surface,
-			     cairo_operator_t op,
-			     cairo_pattern_t *source,
-			     cairo_path_fixed_t *path,
-			     cairo_fill_rule_t fill_rule,
-			     double tolerance,
-			     cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_fill op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSaveGState (surface->cgContext);
-
-    CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_UNSUPPORTED) {
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    CGContextBeginPath (surface->cgContext);
-    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextFillPath (surface->cgContext);
-	else
-	    CGContextEOFillPath (surface->cgContext);
-    } else if (action == DO_SHADING) {
-
-	// we have to clip and then paint the shading; we can't fill
-	// with the shading
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextClip (surface->cgContext);
-	else
-	    CGContextEOClip (surface->cgContext);
-
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    ND((stderr, "-- fill\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_stroke (void *abstract_surface,
-			       cairo_operator_t op,
-			       cairo_pattern_t *source,
-			       cairo_path_fixed_t *path,
-			       cairo_stroke_style_t *style,
-			       cairo_matrix_t *ctm,
-			       cairo_matrix_t *ctm_inverse,
-			       double tolerance,
-			       cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-
-    ND((stderr, "%p _cairo_nquartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    CGContextSaveGState (surface->cgContext);
-
-    // Turning antialiasing off causes misrendering with
-    // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels)
-    //CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-    CGContextSetLineWidth (surface->cgContext, style->line_width);
-    CGContextSetLineCap (surface->cgContext, _cairo_nquartz_cairo_line_cap_to_quartz (style->line_cap));
-    CGContextSetLineJoin (surface->cgContext, _cairo_nquartz_cairo_line_join_to_quartz (style->line_join));
-    CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
-
-    if (style->dash && style->num_dashes) {
-#define STATIC_DASH 32
-	float sdash[STATIC_DASH];
-	float *fdash = sdash;
-	int k;
-	if (style->num_dashes > STATIC_DASH)
-	    fdash = malloc (sizeof(float)*style->num_dashes);
-
-	for (k = 0; k < style->num_dashes; k++)
-	    fdash[k] = (float) style->dash[k];
-	
-	CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, style->num_dashes);
-
-	if (fdash != sdash)
-	    free (fdash);
-    }
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_UNSUPPORTED) {
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    CGContextBeginPath (surface->cgContext);
-    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextStrokePath (surface->cgContext);
-    } else if (action == DO_SHADING) {
-	// we have to clip and then paint the shading; first we have to convert
-	// the stroke to a path that we can fill
-	CGContextReplacePathWithStrokedPath (surface->cgContext);
-	CGContextClip (surface->cgContext);
-
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    ND((stderr, "-- stroke\n"));
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_show_glyphs (void *abstract_surface,
-				    cairo_operator_t op,
-				    cairo_pattern_t *source,
-				    cairo_glyph_t *glyphs,
-				    int num_glyphs,
-				    cairo_scaled_font_t *scaled_font)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_nquartz_action_t action;
-    int i;
-
-    if (num_glyphs <= 0)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (op == CAIRO_OPERATOR_DEST)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (!_cairo_scaled_font_is_atsui (scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    CGContextSaveGState (surface->cgContext);
-
-    action = _cairo_nquartz_setup_source (surface, source);
-    if (action == DO_SOLID || action == DO_PATTERN) {
-	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-    } else if (action == DO_SHADING) {
-	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
-    } else {
-	/* Unsupported */
-	CGContextRestoreGState (surface->cgContext);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    double y_height = surface->extents.height;
-
-    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
-
-    ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
-    ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
-    CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
-
-    CGContextSetFont (surface->cgContext, cgfref);
-    CGFontRelease (cgfref);
-
-    /* So this should include the size; I don't know if I need to extract the
-     * size from this and call CGContextSetFontSize.. will I get crappy hinting
-     * with this 1.0 size business?  Or will CG just multiply that size into the
-     * text matrix?
-     */
-    //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
-    CGAffineTransform cairoTextTransform, textTransform;
-    _cairo_nquartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
-
-    textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
-    textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
-    textTransform = CGAffineTransformConcat (cairoTextTransform, textTransform);
-
-    CGContextSetTextMatrix (surface->cgContext, textTransform);
-    CGContextSetFontSize (surface->cgContext, 1.0);
-
-    // XXXtodo/perf: stack storage for glyphs/sizes
-#define STATIC_BUF_SIZE 64
-    CGGlyph glyphs_static[STATIC_BUF_SIZE];
-    CGSize cg_advances_static[STATIC_BUF_SIZE];
-    CGGlyph *cg_glyphs = &glyphs_static[0];
-    CGSize *cg_advances = &cg_advances_static[0];
-
-    if (num_glyphs > STATIC_BUF_SIZE) {
-	cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
-	cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
-    }
-
-    double xprev = glyphs[0].x;
-    double yprev = glyphs[0].y;
-
-    cg_glyphs[0] = glyphs[0].index;
-    cg_advances[0].width = 0;
-    cg_advances[0].height = 0;
-
-    for (i = 1; i < num_glyphs; i++) {
-	cg_glyphs[i] = glyphs[i].index;
-	cg_advances[i-1].width = glyphs[i].x - xprev;
-	cg_advances[i-1].height = glyphs[i].y - yprev;
-	xprev = glyphs[i].x;
-	yprev = glyphs[i].y;
-    }
-
-#if 0
-    for (i = 0; i < num_glyphs; i++) {
-	ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height));
-    }
-#endif
-
-    CGContextShowGlyphsWithAdvances (surface->cgContext,
-				     cg_glyphs,
-				     cg_advances,
-				     num_glyphs);
-
-    if (cg_glyphs != &glyphs_static[0]) {
-	free (cg_glyphs);
-	free (cg_advances);
-    }
-
-    if (action == DO_SHADING)
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-
-    _cairo_nquartz_teardown_source (surface, source);
-
-    CGContextRestoreGState (surface->cgContext);
-
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_mask (void *abstract_surface,
-			     cairo_operator_t op,
-			     cairo_pattern_t *source,
-			     cairo_pattern_t *mask)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-
-    ND((stderr, "%p _cairo_nquartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type));
-
-    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
-	/* This is easy; we just need to paint with the alpha. */
-	cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
-
-	CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha);
-    } else {
-	/* So, CGContextClipToMask is not present in 10.3.9, so we're
-	 * doomed; if we have imageData, we can do fallback, otherwise
-	 * just pretend success.
-	 */
-	if (surface->imageData)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    rv = _cairo_nquartz_surface_paint (surface, op, source);
-
-    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
-	CGContextSetAlpha (surface->cgContext, 1.0);
-    }
-
-    ND((stderr, "-- mask\n"));
-
-    return rv;
-}
-
-static cairo_int_status_t
-_cairo_nquartz_surface_intersect_clip_path (void *abstract_surface,
-					    cairo_path_fixed_t *path,
-					    cairo_fill_rule_t fill_rule,
-					    double tolerance,
-					    cairo_antialias_t antialias)
-{
-    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
-
-    ND((stderr, "%p _cairo_nquartz_surface_intersect_clip_path path: %p\n", surface, path));
-
-    if (path == NULL) {
-	/* If we're being asked to reset the clip, we can only do it
-	 * by restoring the gstate to our previous saved one, and
-	 * saving it again.
-	 *
-	 * Note that this assumes that ALL nquartz surface creation
-	 * functions will do a SaveGState first; we do this in create_internal.
-	 */
-	CGContextRestoreGState (surface->cgContext);
-	CGContextSaveGState (surface->cgContext);
-    } else {
-	CGContextBeginPath (surface->cgContext);
-	_cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextClip (surface->cgContext);
-	else
-	    CGContextEOClip (surface->cgContext);
-    }
-
-    ND((stderr, "-- intersect_clip_path\n"));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-// XXXtodo implement show_page; need to figure out how to handle begin/end
-
-static const struct _cairo_surface_backend cairo_nquartz_surface_backend = {
-    CAIRO_SURFACE_TYPE_NQUARTZ,
-    _cairo_nquartz_surface_create_similar,
-    _cairo_nquartz_surface_finish,
-    _cairo_nquartz_surface_acquire_source_image,
-    NULL, /* release_source_image */
-    _cairo_nquartz_surface_acquire_dest_image,
-    _cairo_nquartz_surface_release_dest_image,
-    _cairo_nquartz_surface_clone_similar,
-    NULL, /* composite */
-    NULL, /* fill_rectangles */
-    NULL, /* composite_trapezoids */
-    NULL, /* copy_page */
-    NULL, /* show_page */
-    NULL, /* set_clip_region */
-    _cairo_nquartz_surface_intersect_clip_path,
-    _cairo_nquartz_surface_get_extents,
-    NULL, /* old_show_glyphs */
-    NULL, /* get_font_options */
-    NULL, /* flush */
-    NULL, /* mark_dirty_rectangle */
-    NULL, /* scaled_font_fini */
-    NULL, /* scaled_glyph_fini */
-
-    _cairo_nquartz_surface_paint,
-    _cairo_nquartz_surface_mask,
-    _cairo_nquartz_surface_stroke,
-    _cairo_nquartz_surface_fill,
-    _cairo_nquartz_surface_show_glyphs,
-
-    NULL, /* snapshot */
-};
-
-cairo_bool_t
-cairo_surface_is_nquartz (cairo_surface_t *surf)
-{
-    return (surf->backend == &cairo_nquartz_surface_backend);
-}
-
-static cairo_nquartz_surface_t *
-_cairo_nquartz_surface_create_internal (CGContextRef cgContext,
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-					AGLContext aglContext,
-#else
-					void * unused,
-#endif
-					cairo_content_t content,
-					unsigned int width,
-					unsigned int height,
-					cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surface;
-
-    /* Init the base surface */
-    surface = malloc(sizeof(cairo_nquartz_surface_t));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return NULL;
-    }
-
-    memset(surface, 0, sizeof(cairo_nquartz_surface_t));
-
-    _cairo_surface_init(&surface->base, &cairo_nquartz_surface_backend,
-			content);
-
-    /* Save our extents */
-    surface->extents.x = surface->extents.y = 0;
-    surface->extents.width = width;
-    surface->extents.height = height;
-
-    if (!y_grows_down) {
-	/* Then make the CGContext sane */
-	CGContextTranslateCTM (cgContext, 0.0, surface->extents.height);
-	CGContextScaleCTM (cgContext, 1.0, -1.0);
-    }
-
-    /* Save so we can always get back to a known-good CGContext -- this is
-     * required for proper behaviour of intersect_clip_path(NULL)
-     */
-    CGContextSaveGState (cgContext);
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-    surface->aglContext = aglContext;
-#endif
-    surface->cgContext = cgContext;
-    surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
-
-    surface->imageData = NULL;
-
-    return surface;
-}
-					 
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-cairo_surface_t *
-cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
-					      unsigned int width,
-					      unsigned int height,
-					      cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surf;
-    CGSize sz;
-
-    /* Make our CGContext from the AGL context */
-    sz.width = width;
-    sz.height = height;
-
-    CGContextRef cgc = CGGLContextCreate (aglContext, sz, NULL /* device RGB colorspace */);
-
-    surf = _cairo_nquartz_surface_create_internal (cgc, aglContext, CAIRO_CONTENT_COLOR_ALPHA,
-						   width, height, y_grows_down);
-    if (!surf) {
-	CGContextRelease (cgc);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    return (cairo_surface_t *) surf;
-}
-#endif
-
-cairo_surface_t *
-cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
-					     unsigned int width,
-					     unsigned int height,
-					     cairo_bool_t y_grows_down)
-{
-    cairo_nquartz_surface_t *surf;
-
-    CGContextRetain (cgContext);
-
-    surf = _cairo_nquartz_surface_create_internal (cgContext, NULL, CAIRO_CONTENT_COLOR_ALPHA,
-						   width, height, y_grows_down);
-    if (!surf) {
-	CGContextRelease (cgContext);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    return (cairo_surface_t *) surf;
-}
-
-cairo_surface_t *
-cairo_nquartz_surface_create (cairo_format_t format,
-			      unsigned int width,
-			      unsigned int height)
-{
-    cairo_nquartz_surface_t *surf;
-    CGContextRef cgc;
-    CGColorSpaceRef cgColorspace;
-    CGBitmapInfo bitinfo;
-    void *imageData;
-    int stride;
-    int bitsPerComponent;
-
-    if (format == CAIRO_FORMAT_ARGB32) {
-	cgColorspace = CGColorSpaceCreateDeviceRGB();
-	stride = width * 4;
-	bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_RGB24) {
-	cgColorspace = CGColorSpaceCreateDeviceRGB();
-	stride = width * 4;
-	bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_A8) {
-	cgColorspace = CGColorSpaceCreateDeviceGray();
-	if (width % 4 == 0)
-	    stride = width;
-	else
-	    stride = (width & ~3) + 4;
-	bitinfo = kCGImageAlphaNone;
-	bitsPerComponent = 8;
-    } else if (format == CAIRO_FORMAT_A1) {
-	/* I don't think we can usefully support this, as defined by
-	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
-	 * quantities.
-	 */
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    } else {
-	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    imageData = malloc (height * stride);
-    if (!imageData) {
-	CGColorSpaceRelease (cgColorspace);
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    cgc = CGBitmapContextCreate (imageData,
-				 width,
-				 height,
-				 bitsPerComponent,
-				 stride,
-				 cgColorspace,
-				 bitinfo);
-    CGColorSpaceRelease (cgColorspace);
-
-    if (!cgc) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    surf = _cairo_nquartz_surface_create_internal (cgc, NULL, _cairo_content_from_format (format),
-						   width, height, FALSE);
-    if (!surf) {
-	CGContextRelease (cgc);
-	// create_internal will have set an error
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
-
-    surf->imageData = imageData;
-
-    return (cairo_surface_t *) surf;
-}
-
-CGContextRef
-cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf)
-{
-    cairo_nquartz_surface_t *nquartz = (cairo_nquartz_surface_t*)surf;
-
-    if (!cairo_surface_is_nquartz(surf))
-	return NULL;
-
-    return nquartz->cgContext;
-}
-
-
-/* Debug stuff */
-
-#ifdef NQUARTZ_DEBUG
-
-#include <Movies.h>
-
-void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest)
-{
-    Handle  dataRef = NULL;
-    OSType  dataRefType;
-    CFStringRef inPath = CFStringCreateWithCString(NULL, dest, kCFStringEncodingASCII);
-
-    GraphicsExportComponent grex = 0;
-    unsigned long sizeWritten;
-
-    ComponentResult result;
-
-    // create the data reference
-    result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle,
-						    0, &dataRef, &dataRefType);
-
-    if (NULL != dataRef && noErr == result) {
-	// get the PNG exporter
-	result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG,
-				       &grex);
-
-	if (grex) {
-	    // tell the exporter where to find its source image
-	    result = GraphicsExportSetInputCGImage(grex, inImageRef);
-
-	    if (noErr == result) {
-		// tell the exporter where to save the exporter image
-		result = GraphicsExportSetOutputDataReference(grex, dataRef,
-							      dataRefType);
-
-		if (noErr == result) {
-		    // write the PNG file
-		    result = GraphicsExportDoExport(grex, &sizeWritten);
-		}
-	    }
-
-	    // remember to close the component
-	    CloseComponent(grex);
-	}
-
-	// remember to dispose of the data reference handle
-	DisposeHandle(dataRef);
-    }
-}
-#endif
-
-void
-nquartz_image_to_png (CGImageRef imgref, char *dest)
-{
-#if 0
-    static int sctr = 0;
-    char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png";
-
-    if (dest == NULL) {
-	fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr);
-	sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr);
-	sctr++;
-	dest = sptr;
-    }
-
-    ExportCGImageToPNGFile(imgref, dest);
-#endif
-}
-
-void
-nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest)
-{
-#if 0
-    static int sctr = 0;
-    char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png";
-
-    if (nq->base.type != CAIRO_SURFACE_TYPE_NQUARTZ) {
-	fprintf (stderr, "** nquartz_surface_to_png: surface %p isn't nquartz!\n", nq);
-	return;
-    }
-
-    if (dest == NULL) {
-	fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr);
-	sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr);
-	sctr++;
-	dest = sptr;
-    }
-
-    CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext);
-    if (imgref == NULL) {
-	fprintf (stderr, "nquartz surface at %p is not a bitmap context!\n", nq);
-	return;
-    }
-
-    ExportCGImageToPNGFile(imgref, dest);
-
-    CGImageRelease(imgref);
-#endif
-}
-
diff --git a/src/cairo-nquartz.h b/src/cairo-nquartz.h
deleted file mode 100644
index c6c58e7..0000000
--- a/src/cairo-nquartz.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2006 Mozilla 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Mozilla Corporation.
- *
- * Contributor(s):
- *      Vladimir Vukicevic <vladimir at mozilla.com>
- */
-
-#ifndef CAIRO_NQUARTZ_H
-#define CAIRO_NQUARTZ_H
-
-#include <cairo.h>
-
-#if CAIRO_HAS_NQUARTZ_SURFACE
-
-#include <Carbon/Carbon.h>
-
-#include <AGL/agl.h>
-
-CAIRO_BEGIN_DECLS
-
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create (cairo_format_t format,
-                              unsigned int width,
-                              unsigned int height);
-
-#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
-                                              unsigned int width,
-                                              unsigned int height,
-                                              cairo_bool_t y_grows_down);
-#endif
-
-cairo_public cairo_surface_t *
-cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
-                                             unsigned int width,
-                                             unsigned int height,
-                                             cairo_bool_t y_grows_down);
-
-cairo_public cairo_bool_t
-cairo_surface_is_nquartz (cairo_surface_t *surf);
-
-cairo_public CGContextRef
-cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf);
-
-CAIRO_END_DECLS
-
-#else  /* CAIRO_HAS_NQUARTZ_SURFACE */
-# error Cairo was not compiled with support for the nquartz backend
-#endif /* CAIRO_HAS_NQUARTZ_SURFACE */
-
-#endif /* CAIRO_NQUARTZ_H */
diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index f9db501..f053bc0 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -39,20 +39,34 @@
 #include <cairoint.h>
 #include <cairo-quartz.h>
 
-typedef struct cairo_quartz_surface {
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#include <AGL/agl.h>
+#include <OpenGL/gl.h>
+
+typedef AGLContext nquartz_agl_context_type;
+#else
+typedef void* nquartz_agl_context_type;
+#endif
+
+typedef struct cairo_nquartz_surface {
     cairo_surface_t base;
 
-    CGContextRef context;
+    void *imageData;
 
-    cairo_bool_t y_grows_down;
+    CGContextRef cgContext;
+    CGAffineTransform cgContextBaseCTM;
 
     cairo_rectangle_int16_t extents;
 
-    pixman_region16_t *clip_region;
-} cairo_quartz_surface_t;
-
-cairo_bool_t
-_cairo_surface_is_quartz (cairo_surface_t *surface);
+    /* These are stored while drawing operations are in place, set up
+     * by nquartz_setup_source() and nquartz_finish_source()
+     */
+    CGAffineTransform imageTransform;
+    CGImageRef sourceImage;
+    CGShadingRef sourceShading;
+    CGPatternRef sourcePattern;
+    nquartz_agl_context_type aglContext;
+} cairo_nquartz_surface_t, cairo_quartz_surface_t;
 
 cairo_bool_t
 _cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont);
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index cff15af..0745d89 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1,6 +1,7 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2004 Calum Robinson
+ * Copyright © 2006, 2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -27,237 +28,1841 @@
  *
  * The Original Code is the cairo graphics library.
  *
- * The Initial Developer of the Original Code is Calum Robinson
+ * The Initial Developer of the Original Code is Mozilla Corporation.
  *
  * Contributor(s):
- *    Calum Robinson <calumr at mac.com>
+ *	Vladimir Vukicevic <vladimir at mozilla.com>
+ */
+
+#include <Carbon/Carbon.h>
+
+/* Support rendering to an OpenGL AGL context using CGGLContextCreate;
+ * Apple has deprecated CGGLContext, so CAIRO_NQUARTZ_SUPPORT_AGL is
+ * not defined by default.
  */
 
 #include "cairoint.h"
 #include "cairo-private.h"
+
 #include "cairo-quartz-private.h"
 
+#undef NQUARTZ_DEBUG
+
+#ifdef NQUARTZ_DEBUG
+#define ND(_x)	fprintf _x
+#else
+#define ND(_x)	do {} while(0)
+#endif
+
+/* This method is private, but it exists.  Its params are are exposed
+ * as args to the NS* method, but not as CG.
+ */
+enum PrivateCGCompositeMode {
+    kPrivateCGCompositeClear		= 0,
+    kPrivateCGCompositeCopy		= 1,
+    kPrivateCGCompositeSourceOver	= 2,
+    kPrivateCGCompositeSourceIn		= 3,
+    kPrivateCGCompositeSourceOut	= 4,
+    kPrivateCGCompositeSourceAtop	= 5,
+    kPrivateCGCompositeDestinationOver	= 6,
+    kPrivateCGCompositeDestinationIn	= 7,
+    kPrivateCGCompositeDestinationOut	= 8,
+    kPrivateCGCompositeDestinationAtop	= 9,
+    kPrivateCGCompositeXOR		= 10,
+    kPrivateCGCompositePlusDarker	= 11, // (max (0, (1-d) + (1-s)))
+    kPrivateCGCompositePlusLighter	= 12, // (min (1, s + d))
+};
+typedef enum PrivateCGCompositeMode PrivateCGCompositeMode;
+CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
+CG_EXTERN void CGContextResetCTM (CGContextRef);
+CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform);
+CG_EXTERN void CGContextResetClip (CGContextRef);
+CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
+
+/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
+ * has all the stuff we care about, just some of it isn't exported in the SDK.
+ */ 
+#ifndef kCGBitmapByteOrder32Host
+#define USE_10_3_WORKAROUNDS
+#define kCGBitmapAlphaInfoMask 0x1F
+#define kCGBitmapByteOrderMask 0x7000
+#define kCGBitmapByteOrder32Host 0
+
+typedef uint32_t CGBitmapInfo;
+
+/* public in 10.4, present in 10.3.9 */
+CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
+CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
+#endif
+
+
+/**
+ ** Utility functions
+ **/
+
+void nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest);
+void nquartz_image_to_png (CGImageRef, char *dest);
+
+/*
+ * Cairo path -> Quartz path conversion helpers
+ */
+
+/* cairo path -> mutable path */
+static cairo_status_t
+_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
+{
+    CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
+		       _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
+{
+    CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
+			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
+{
+    CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
+			   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+			   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+			   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_path_close_path (void *closure)
+{
+    CGPathCloseSubpath ((CGMutablePathRef) closure);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* cairo path -> execute in context */
+static cairo_status_t
+_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
+{
+    //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
+    CGContextMoveToPoint ((CGContextRef) closure,
+			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
+{
+    //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
+    if (CGContextIsPathEmpty ((CGContextRef) closure))
+	CGContextMoveToPoint ((CGContextRef) closure,
+			      _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    else
+	CGContextAddLineToPoint ((CGContextRef) closure,
+				 _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
+{
+    //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n",
+    //		   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+    //		   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+    //		   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
+
+    CGContextAddCurveToPoint ((CGContextRef) closure,
+			      _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
+			      _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
+			      _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_quartz_context_close_path (void *closure)
+{
+    //ND((stderr, "closepath\n"));
+    CGContextClosePath ((CGContextRef) closure);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_nquartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
+					  CGMutablePathRef cgPath)
+{
+    return _cairo_path_fixed_interpret (path,
+					CAIRO_DIRECTION_FORWARD,
+					_cairo_path_to_quartz_path_move_to,
+					_cairo_path_to_quartz_path_line_to,
+					_cairo_path_to_quartz_path_curve_to,
+					_cairo_path_to_quartz_path_close_path,
+					cgPath);
+}
+
+static cairo_status_t
+_cairo_nquartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
+					     CGContextRef cgc)
+{
+    return _cairo_path_fixed_interpret (path,
+					CAIRO_DIRECTION_FORWARD,
+					_cairo_path_to_quartz_context_move_to,
+					_cairo_path_to_quartz_context_line_to,
+					_cairo_path_to_quartz_context_curve_to,
+					_cairo_path_to_quartz_context_close_path,
+					cgc);
+}
+
+/*
+ * Misc helpers/callbacks
+ */
+
+static PrivateCGCompositeMode
+_cairo_nquartz_cairo_operator_to_quartz (cairo_operator_t op)
+{
+    switch (op) {
+	case CAIRO_OPERATOR_CLEAR:
+	    return kPrivateCGCompositeClear;
+	case CAIRO_OPERATOR_SOURCE:
+	    return kPrivateCGCompositeCopy;
+	case CAIRO_OPERATOR_OVER:
+	    return kPrivateCGCompositeSourceOver;
+	case CAIRO_OPERATOR_IN:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeSourceIn;
+	case CAIRO_OPERATOR_OUT:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeSourceOut;
+	case CAIRO_OPERATOR_ATOP:
+	    return kPrivateCGCompositeSourceAtop;
+
+	case CAIRO_OPERATOR_DEST:
+	    /* XXX this is handled specially (noop)! */
+	    return kPrivateCGCompositeCopy;
+	case CAIRO_OPERATOR_DEST_OVER:
+	    return kPrivateCGCompositeDestinationOver;
+	case CAIRO_OPERATOR_DEST_IN:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeDestinationIn;
+	case CAIRO_OPERATOR_DEST_OUT:
+	    return kPrivateCGCompositeDestinationOut;
+	case CAIRO_OPERATOR_DEST_ATOP:
+	    /* XXX This doesn't match image output */
+	    return kPrivateCGCompositeDestinationAtop;
+
+	case CAIRO_OPERATOR_XOR:
+	    return kPrivateCGCompositeXOR; /* This will generate strange results */
+	case CAIRO_OPERATOR_ADD:
+	    return kPrivateCGCompositePlusLighter;
+	case CAIRO_OPERATOR_SATURATE:
+	    /* XXX This doesn't match image output for SATURATE; there's no equivalent */
+	    return kPrivateCGCompositePlusDarker;  /* ??? */
+    }
+
+
+    return kPrivateCGCompositeCopy;
+}
+
+static CGLineCap
+_cairo_nquartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap)
+{
+    switch (ccap) {
+	case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break;
+	case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break;
+	case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break;
+    }
+
+    return kCGLineCapButt;
+}
+
+static CGLineJoin
+_cairo_nquartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin)
+{
+    switch (cjoin) {
+	case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break;
+	case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break;
+	case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break;
+    }
+
+    return kCGLineJoinMiter;
+}
+
+static void
+_cairo_nquartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
+				       CGAffineTransform *dst)
+{
+    dst->a = src->xx;
+    dst->b = src->xy;
+    dst->c = src->yx;
+    dst->d = src->yy;
+    dst->tx = src->x0;
+    dst->ty = src->y0;
+}
+
+/**
+ ** Source -> Quartz setup and finish functions
+ **/
+
+static void
+ComputeGradientValue (void *info, const float *in, float *out)
+{
+    float fdist = *in; /* 0.0 .. 1.0 */
+    cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
+    cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
+    unsigned int i;
+
+    for (i = 0; i < grad->n_stops; i++) {
+	if (grad->stops[i].x > fdist_fix)
+	    break;
+    }
+
+    if (i == 0 || i == grad->n_stops) {
+	if (i == grad->n_stops)
+	    --i;
+	out[0] = grad->stops[i].color.red / 65535.;
+	out[1] = grad->stops[i].color.green / 65535.;
+	out[2] = grad->stops[i].color.blue / 65535.;
+	out[3] = grad->stops[i].color.alpha / 65535.;
+    } else {
+	float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
+	float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
+	float bp = (fdist - ax)/bx;
+	float ap = 1.0 - bp;
+
+	out[0] =
+	    (grad->stops[i-1].color.red / 65535.) * ap +
+	    (grad->stops[i].color.red / 65535.) * bp;
+	out[1] =
+	    (grad->stops[i-1].color.green / 65535.) * ap +
+	    (grad->stops[i].color.green / 65535.) * bp;
+	out[2] =
+	    (grad->stops[i-1].color.blue / 65535.) * ap +
+	    (grad->stops[i].color.blue / 65535.) * bp;
+	out[3] =
+	    (grad->stops[i-1].color.alpha / 65535.) * ap +
+	    (grad->stops[i].color.alpha / 65535.) * bp;
+    }
+}
+
+static CGFunctionRef
+CreateGradientFunction (cairo_gradient_pattern_t *gpat)
+{
+    static const float input_value_range[2] = { 0.f, 1.f };
+    static const float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f };
+    static const CGFunctionCallbacks callbacks = {
+	0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
+    };
+
+    return CGFunctionCreate (gpat,
+			     1,
+			     input_value_range,
+			     4,
+			     output_value_ranges,
+			     &callbacks);
+}
+
+static CGShadingRef
+_cairo_nquartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
+{
+    cairo_matrix_t mat;
+    double x0, y0;
+
+    if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
+	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return NULL;
+
+    /* We can only do this if we have an identity pattern matrix;
+     * otherwise fall back through to the generic pattern case.
+     * XXXperf we could optimize this by creating a pattern with the shading;
+     * but we'd need to know the extents to do that.
+     * ... but we don't care; we can use the surface extents for it
+     * XXXtodo - implement gradients with non-identity pattern matrices
+     */
+    cairo_pattern_get_matrix (abspat, &mat);
+    if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
+	return NULL;
+
+    x0 = mat.x0;
+    y0 = mat.y0;
+
+    if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) {
+	cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat;
+	CGShadingRef shading;
+	CGPoint start, end;
+	CGFunctionRef gradFunc;
+	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+
+	start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
+			     _cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
+	end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0,
+			   _cairo_fixed_to_double (lpat->gradient.p2.y) - y0);
+
+	cairo_pattern_reference (abspat);
+	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
+	shading = CGShadingCreateAxial (rgb,
+					start, end,
+					gradFunc,
+					true, true);
+	CGColorSpaceRelease(rgb);
+	CGFunctionRelease(gradFunc);
+
+	return shading;
+    }
+
+    if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) {
+	cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat;
+	CGShadingRef shading;
+	CGPoint start, end;
+	CGFunctionRef gradFunc;
+	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+
+	start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.inner.x) - x0,
+			     _cairo_fixed_to_double (rpat->gradient.inner.y) - y0);
+	end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.outer.x) - x0,
+			   _cairo_fixed_to_double (rpat->gradient.outer.y) - y0);
+
+	cairo_pattern_reference (abspat);
+	gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
+	shading = CGShadingCreateRadial (rgb,
+					 start,
+					 _cairo_fixed_to_double (rpat->gradient.inner.radius),
+					 end,
+					 _cairo_fixed_to_double (rpat->gradient.outer.radius),
+					 gradFunc,
+					 true, true);
+	CGColorSpaceRelease(rgb);
+	CGFunctionRelease(gradFunc);
+
+	return shading;
+    }
+
+    /* Shouldn't be reached */
+    ASSERT_NOT_REACHED;
+    return NULL;
+}
+
+
+/* Generic cairo_pattern -> CGPattern function */
+static void
+SurfacePatternDrawFunc (void *info, CGContextRef context)
+{
+    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
+    cairo_surface_t *pat_surf = spat->surface;
+
+    cairo_nquartz_surface_t *quartz_surf = NULL;
+
+    cairo_bool_t flip = FALSE;
+
+    CGImageRef img;
+
+    if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
+	/* This sucks; we should really store a dummy nquartz surface
+	 * for passing in here
+	 * XXXtodo store a dummy nquartz surface somewhere for handing off to clone_similar
+	 * XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
+	 * just create the CGImage directly!
+	 */
+
+	cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+	cairo_surface_t *new_surf = NULL;
+	cairo_rectangle_int16_t rect;
+
+	_cairo_surface_get_extents (pat_surf, &rect);
+
+	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
+				      rect.width, rect.height, &new_surf);
+
+	cairo_surface_destroy(dummy);
+
+	quartz_surf = (cairo_nquartz_surface_t *) new_surf;
+    } else {
+	/* If it's a nquartz surface, we can try to see if it's a CGBitmapContext;
+	 * we do this when we call CGBitmapContextCreateImage below.
+	 */
+	cairo_surface_reference (pat_surf);
+	quartz_surf = (cairo_nquartz_surface_t*) pat_surf;
+
+	/* XXXtodo WHY does this need to be flipped?  Writing this stuff
+	 * to disk shows that in both this path and the path above the source image
+	 * has an identical orientation, and the destination context at all times has a Y
+	 * flip.  So why do we need to flip in this case?
+	 */
+	flip = TRUE;
+    }
+
+    /* this is a 10.4 API, present in 10.3.9 */
+    CGContextFlush (quartz_surf->cgContext);
+    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+
+    if (!img) {
+	// ... give up.
+	ND((stderr, "CGBitmapContextCreateImage failed\n"));
+	cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
+	return;
+    }
+
+    if (flip) {
+	CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
+	CGContextScaleCTM (context, 1, -1);
+    }
+
+    CGRect imageBounds;
+    imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
+    imageBounds.origin.x = 0;
+    imageBounds.origin.y = 0;
+
+    CGContextDrawImage (context, imageBounds, img);
+
+    CGImageRelease (img);
+
+    cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
+}
+
+/* Borrowed from cairo-meta-surface */
+static cairo_status_t
+_init_pattern_with_snapshot (cairo_pattern_t *pattern,
+			     const cairo_pattern_t *other)
+{
+    _cairo_pattern_init_copy (pattern, other);
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern =
+	    (cairo_surface_pattern_t *) pattern;
+	cairo_surface_t *surface = surface_pattern->surface;
+
+	surface_pattern->surface = _cairo_surface_snapshot (surface);
+
+	cairo_surface_destroy (surface);
+
+	if (surface_pattern->surface->status)
+	    return surface_pattern->surface->status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static CGPatternRef
+_cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_t *dest,
+							  cairo_pattern_t *abspat)
+{
+    cairo_surface_pattern_t *spat;
+    cairo_surface_t *pat_surf;
+    cairo_rectangle_int16_t extents;
+
+    CGRect pbounds;
+    CGAffineTransform ptransform, stransform;
+    CGPatternCallbacks cb = { 0,
+			      SurfacePatternDrawFunc,
+			      (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
+    CGPatternRef cgpat;
+    float rw, rh;
+
+    cairo_pattern_union_t *snap_pattern = NULL;
+    cairo_pattern_t *target_pattern = abspat;
+
+    cairo_matrix_t m;
+    /* SURFACE is the only type we'll handle here */
+    if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
+	return NULL;
+
+    spat = (cairo_surface_pattern_t *) abspat;
+    pat_surf = spat->surface;
+
+    _cairo_surface_get_extents (pat_surf, &extents);
+    pbounds.origin.x = 0;
+    pbounds.origin.y = 0;
+    pbounds.size.width = extents.width;
+    pbounds.size.height = extents.height;
+
+    m = spat->base.matrix;
+    cairo_matrix_invert(&m);
+    _cairo_nquartz_cairo_matrix_to_quartz (&m, &stransform);
+
+    /* The pattern matrix is relative to the bottom left, again; the
+     * incoming cairo pattern matrix is relative to the upper left.
+     * So we take the pattern matrix and the original context matrix,
+     * which gives us the correct base translation/y flip.
+     */
+    ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM);
+
+#ifdef NQUARTZ_DEBUG
+    ND((stderr, "  pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height));
+    ND((stderr, "  pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d));
+    CGAffineTransform xform = CGContextGetCTM(dest->cgContext);
+    ND((stderr, "  context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
+#endif
+
+    // kjs seems to indicate this should work (setting to 0,0 to avoid
+    // tiling); however, the pattern CTM scaling ends up being NaN in
+    // the pattern draw function if either rw or rh are 0.
+    // XXXtodo get pattern drawing working with extend options
+    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
+#if 0
+    if (spat->base.extend == CAIRO_EXTEND_NONE) {
+	/* XXX wasteful; this will keep drawing the pattern in the
+	 * original location.  We need to set up the clip region
+	 * instead to do this right.
+	 */
+	rw = 0;
+	rh = 0;
+    } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
+	rw = extents.width;
+	rh = extents.height;
+    } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
+	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
+	 * and then tiling that
+	 */
+	rw = extents.width;
+	rh = extents.height;
+    } else {
+	/* CAIRO_EXTEND_PAD */
+	/* XXX broken. */
+	rw = 0;
+	rh = 0;
+    }
+#else
+    rw = extents.width;
+    rh = extents.height;
+#endif
+
+    /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
+       other block if it doesn't fafect performance */
+    if (1 /* context is for printing */) {
+	snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
+	target_pattern = (cairo_pattern_t*) snap_pattern;
+	_init_pattern_with_snapshot (target_pattern, abspat);
+    } else {
+	cairo_pattern_reference (abspat);
+	target_pattern = abspat;
+    }
+
+    cgpat = CGPatternCreate (target_pattern,
+			     pbounds,
+			     ptransform,
+			     rw, rh,
+			     kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
+			     TRUE,
+			     &cb);
+    return cgpat;
+}
+
+typedef enum {
+    DO_SOLID,
+    DO_SHADING,
+    DO_PATTERN,
+    DO_UNSUPPORTED
+} cairo_nquartz_action_t;
+
+static cairo_nquartz_action_t
+_cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
+			     cairo_pattern_t *source)
+{
+    assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
+
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+
+	CGContextSetRGBStrokeColor (surface->cgContext,
+				    solid->color.red,
+				    solid->color.green,
+				    solid->color.blue,
+				    solid->color.alpha);
+	CGContextSetRGBFillColor (surface->cgContext,
+				  solid->color.red,
+				  solid->color.green,
+				  solid->color.blue,
+				  solid->color.alpha);
+
+	return DO_SOLID;
+    } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR ||
+	       source->type == CAIRO_PATTERN_TYPE_RADIAL)
+    {
+	CGShadingRef shading = _cairo_nquartz_cairo_gradient_pattern_to_quartz (source);
+	if (!shading)
+	    return DO_UNSUPPORTED;
+
+	surface->sourceShading = shading;
+
+	return DO_SHADING;
+    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	CGPatternRef pattern = _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
+	if (!pattern)
+	    return DO_UNSUPPORTED;
+
+	float patternAlpha = 1.0f;
+
+	// Save before we change the pattern, colorspace, etc. so that
+	// we can restore and make sure that quartz releases our
+	// pattern (which may be stack allocated)
+	CGContextSaveGState(surface->cgContext);
+
+	CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+	CGContextSetFillColorSpace (surface->cgContext, patternSpace);
+	CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
+	CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
+	CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha);
+	CGColorSpaceRelease (patternSpace);
+
+	/* Quartz likes to munge the pattern phase (as yet unexplained
+	 * why); force it to 0,0 as we've already baked in the correct
+	 * pattern translation into the pattern matrix
+	 */
+	CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0));
+
+	surface->sourcePattern = pattern;
+
+	return DO_PATTERN;
+    } else {
+	return DO_UNSUPPORTED;
+    }
+
+    ASSERT_NOT_REACHED;
+}
+
+static void
+_cairo_nquartz_teardown_source (cairo_nquartz_surface_t *surface,
+				cairo_pattern_t *source)
+{
+    if (surface->sourceImage) {
+	// nothing to do; we don't use sourceImage yet
+    }
+
+    if (surface->sourceShading) {
+	CGShadingRelease(surface->sourceShading);
+	surface->sourceShading = NULL;
+    }
+
+    if (surface->sourcePattern) {
+	CGPatternRelease(surface->sourcePattern);
+	// To tear down the pattern and colorspace
+	CGContextRestoreGState(surface->cgContext);
+
+	surface->sourcePattern = NULL;
+    }
+}
+
+/**
+ ** get source/dest image implementation
+ **/
+
+static void
+ImageDataReleaseFunc(void *info, const void *data, size_t size)
+{
+    if (data != NULL) {
+	free((void *) data);
+    }
+}
+
+/* Read the image from the surface's front buffer */
+static cairo_int_status_t
+_cairo_nquartz_get_image (cairo_nquartz_surface_t *surface,
+			  cairo_image_surface_t **image_out,
+			  unsigned char **data_out)
+{
+    unsigned char *imageData;
+    cairo_image_surface_t *isurf;
+
+    /* If we weren't constructed with an AGL Context
+     * or a CCGBitmapContext, then we have no way
+     * of doing this
+     */
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+    if (surface->aglContext) {
+	AGLContext oldContext;
+	cairo_format_masks_t masks = { 32, 0xff << 24, 0xff << 16, 0xff << 8, 0xff << 0 };
+	unsigned int i;
+
+	oldContext = aglGetCurrentContext();
+	if (oldContext != surface->aglContext)
+	    aglSetCurrentContext(surface->aglContext);
+
+	imageData = (unsigned char *) malloc (surface->extents.width * surface->extents.height * 4);
+	if (!imageData)
+	    return CAIRO_STATUS_NO_MEMORY;
+
+	glReadBuffer (GL_FRONT);
+	glReadPixels (0, 0, surface->extents.width, surface->extents.height,
+		      GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+		      imageData);
+
+	/* swap lines */
+	/* XXX find some fast code to do this */
+	unsigned int lineSize = surface->extents.width * 4;
+	unsigned char *tmpLine = malloc(lineSize);
+	for (i = 0; i < surface->extents.height / 2; i++) {
+	    unsigned char *l0 = imageData + lineSize * i;
+	    unsigned char *l1 = imageData + (lineSize * (surface->extents.height - i - 1));
+	    memcpy (tmpLine, l0, lineSize);
+	    memcpy (l0, l1, lineSize);
+	    memcpy (l1, tmpLine, lineSize);
+	}
+	free (tmpLine);
+
+	if (oldContext && oldContext != surface->aglContext)
+	    aglSetCurrentContext(oldContext);
+
+	isurf = (cairo_image_surface_t *)_cairo_image_surface_create_with_masks
+	    (imageData,
+	     &masks,
+	     surface->extents.width,
+	     surface->extents.height,
+	     surface->extents.width * 4);
+
+	if (data_out)
+	    *data_out = imageData;
+	else
+	    _cairo_image_surface_assume_ownership_of_data (isurf);
+#else
+    /* no AGL */
+    if (0) {
+#endif
+    } else if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) {
+	unsigned int stride;
+	unsigned int bitinfo;
+	unsigned int bpc, bpp;
+	CGColorSpaceRef colorspace;
+	unsigned int color_comps;
+
+	imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
+#ifdef USE_10_3_WORKAROUNDS
+	bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext);
+#else
+	bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext);
+#endif
+	stride = CGBitmapContextGetBytesPerRow (surface->cgContext);
+	bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext);
+	bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext);
+
+	// let's hope they don't add YUV under us
+	colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
+	color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
+
+	// XXX TODO: We can handle all of these by converting to
+	// pixman masks, including non-native-endian masks
+	if (bpc != 8)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if (bpp != 32 && bpp != 8)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if (color_comps != 3 && color_comps != 1)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if (bpp == 32 && color_comps == 3 &&
+	    (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst &&
+	    (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+	{
+	    isurf = (cairo_image_surface_t *)
+		cairo_image_surface_create_for_data (imageData,
+						     CAIRO_FORMAT_ARGB32,
+						     surface->extents.width,
+						     surface->extents.height,
+						     stride);
+	} else if (bpp == 32 && color_comps == 3 &&
+		   (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst &&
+		   (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host)
+	{
+	    isurf = (cairo_image_surface_t *)
+		cairo_image_surface_create_for_data (imageData,
+						     CAIRO_FORMAT_RGB24,
+						     surface->extents.width,
+						     surface->extents.height,
+						     stride);
+	} else if (bpp == 8 && color_comps == 1)
+	{
+	    isurf = (cairo_image_surface_t *)
+		cairo_image_surface_create_for_data (imageData,
+						     CAIRO_FORMAT_A8,
+						     surface->extents.width,
+						     surface->extents.height,
+						     stride);
+	} else {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+    } else {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    *image_out = isurf;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ ** Cairo surface backend implementations
+ **/
+
 static cairo_status_t
-_cairo_quartz_surface_finish(void *abstract_surface)
+_cairo_nquartz_surface_finish (void *abstract_surface)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+
+    ND((stderr, "_cairo_nquartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
+
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+    if (surface->aglContext)
+	aglSetCurrentContext(surface->aglContext);
+#endif
+
+    CGContextFlush (surface->cgContext);
+
+    /* Restore our saved gstate that we use to reset clipping */
+    CGContextRestoreGState (surface->cgContext);
+
+    CGContextRelease (surface->cgContext);
 
-    if (surface->clip_region)
-      pixman_region_destroy (surface->clip_region);
+    surface->cgContext = NULL;
+
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+    if (surface->aglContext)
+	glFlush();
+
+    surface->aglContext = NULL;
+#endif
+
+    if (surface->imageData) {
+	free (surface->imageData);
+	surface->imageData = NULL;
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
-_cairo_quartz_surface_acquire_source_image(void *abstract_surface,
+_cairo_nquartz_surface_acquire_source_image (void *abstract_surface,
+					     cairo_image_surface_t **image_out,
+					     void **image_extra)
+{
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+
+    //ND((stderr, "%p _cairo_nquartz_surface_acquire_source_image\n", surface));
+
+    *image_extra = NULL;
+
+    return _cairo_nquartz_get_image (surface, image_out, NULL);
+}
+
+static cairo_status_t
+_cairo_nquartz_surface_acquire_dest_image (void *abstract_surface,
+					   cairo_rectangle_int16_t *interest_rect,
 					   cairo_image_surface_t **image_out,
+					   cairo_rectangle_int16_t *image_rect,
 					   void **image_extra)
 {
-  cairo_quartz_surface_t *surface = abstract_surface;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t status;
+    unsigned char *data;
+
+    ND((stderr, "%p _cairo_nquartz_surface_acquire_dest_image\n", surface));
+
+    *image_rect = surface->extents;
 
-  if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
-    /* XXX: We can create an image out of the bitmap here */
-  }
+    status = _cairo_nquartz_get_image (surface, image_out, &data);
+    if (status)
+	return status;
 
-  return CAIRO_INT_STATUS_UNSUPPORTED;
+    *image_extra = data;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_nquartz_surface_release_dest_image (void *abstract_surface,
+					   cairo_rectangle_int16_t *interest_rect,
+					   cairo_image_surface_t *image,
+					   cairo_rectangle_int16_t *image_rect,
+					   void *image_extra)
+{
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    unsigned char *imageData = (unsigned char *) image_extra;
+
+    //ND((stderr, "%p _cairo_nquartz_surface_release_dest_image\n", surface));
+
+    if (!CGBitmapContextGetData (surface->cgContext)) {
+	CGDataProviderRef dataProvider;
+	CGImageRef img;
+
+	dataProvider = CGDataProviderCreateWithData (NULL, imageData,
+						     surface->extents.width * surface->extents.height * 4,
+						     ImageDataReleaseFunc);
+
+	img = CGImageCreate (surface->extents.width, surface->extents.height,
+			     8, 32,
+			     surface->extents.width * 4,
+			     CGColorSpaceCreateDeviceRGB(),
+			     kCGImageAlphaPremultipliedFirst,
+			     dataProvider,
+			     NULL,
+			     false,
+			     kCGRenderingIntentDefault);
+
+	CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy);
+
+	CGContextDrawImage (surface->cgContext,
+			    CGRectMake (0, 0, surface->extents.width, surface->extents.height),
+			    img);
+
+	CGImageRelease (img);
+	CGDataProviderRelease (dataProvider);
+
+	ND((stderr, "Image for surface %p was recovered from a bitmap\n", surface));
+    }
+
+    cairo_surface_destroy ((cairo_surface_t *) image);
+}
+
+static cairo_surface_t *
+_cairo_nquartz_surface_create_similar (void *abstract_surface,
+				       cairo_content_t content,
+				       int width,
+				       int height)
+{
+    /*cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;*/
+
+    cairo_format_t format;
+
+    if (content == CAIRO_CONTENT_COLOR_ALPHA)
+	format = CAIRO_FORMAT_ARGB32;
+    else if (content == CAIRO_CONTENT_COLOR)
+	format = CAIRO_FORMAT_RGB24;
+    else if (content == CAIRO_CONTENT_ALPHA)
+	format = CAIRO_FORMAT_A8;
+    else
+	return NULL;
+
+    return cairo_quartz_surface_create (format, width, height);
 }
 
 static cairo_status_t
-_cairo_quartz_surface_acquire_dest_image(void                    *abstract_surface,
-                                         cairo_rectangle_int16_t *interest_rect,
-                                         cairo_image_surface_t  **image_out,
-                                         cairo_rectangle_int16_t *image_rect,
-                                         void                   **image_extra)
+_cairo_nquartz_surface_clone_similar (void *abstract_surface,
+				      cairo_surface_t *src,
+				      int              src_x,
+				      int              src_y,
+				      int              width,
+				      int              height,
+				      cairo_surface_t **clone_out)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
-    cairo_surface_t *image_surface;
-    unsigned char *data;
-    int x1, y1, x2, y2;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_nquartz_surface_t *new_surface = NULL;
+    cairo_format_t new_format;
+
+    CGImageRef quartz_image = NULL;
+
+    if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_QUARTZ) {
+	cairo_nquartz_surface_t *qsurf = (cairo_nquartz_surface_t *) src;
+	quartz_image = CGBitmapContextCreateImage (qsurf->cgContext);
+	new_format = CAIRO_FORMAT_ARGB32;  /* XXX bogus; recover a real format from the image */
+    } else if (_cairo_surface_is_image (src)) {
+	cairo_image_surface_t *isurf = (cairo_image_surface_t *) src;
+	CGDataProviderRef dataProvider;
+	CGColorSpaceRef cgColorspace;
+	CGBitmapInfo bitinfo;
+	int bitsPerComponent, bitsPerPixel;
+
+	if (isurf->format == CAIRO_FORMAT_ARGB32) {
+	    cgColorspace = CGColorSpaceCreateDeviceRGB();
+	    bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+	    bitsPerComponent = 8;
+	    bitsPerPixel = 32;
+	} else if (isurf->format == CAIRO_FORMAT_RGB24) {
+	    cgColorspace = CGColorSpaceCreateDeviceRGB();
+	    bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
+	    bitsPerComponent = 8;
+	    bitsPerPixel = 32;
+	} else if (isurf->format == CAIRO_FORMAT_A8) {
+	    cgColorspace = CGColorSpaceCreateDeviceGray();
+	    bitinfo = kCGImageAlphaNone;
+	    bitsPerComponent = 8;
+	    bitsPerPixel = 8;
+	} else {
+	    /* SUPPORT A1, maybe */
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+
+	new_format = isurf->format;
+
+	dataProvider = CGDataProviderCreateWithData (NULL,
+						     isurf->data,
+						     isurf->height * isurf->stride,
+						     NULL);
+
+	quartz_image = CGImageCreate (isurf->width, isurf->height,
+				      bitsPerComponent,
+				      bitsPerPixel,
+				      isurf->stride,
+				      cgColorspace,
+				      bitinfo,
+				      dataProvider,
+				      NULL,
+				      false,
+				      kCGRenderingIntentDefault);
+	CGDataProviderRelease (dataProvider);
+	CGColorSpaceRelease (cgColorspace);
+    } else {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (!quartz_image)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    new_surface = (cairo_nquartz_surface_t *)
+	cairo_quartz_surface_create (new_format,
+				     CGImageGetWidth (quartz_image),
+				     CGImageGetHeight (quartz_image));
+    if (!new_surface || new_surface->base.status)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    CGContextSetCompositeOperation (new_surface->cgContext,
+				    kPrivateCGCompositeCopy);
+
+    nquartz_image_to_png (quartz_image, NULL);
+
+    CGContextDrawImage (new_surface->cgContext,
+			CGRectMake (src_x, src_y, width, height),
+			quartz_image);
+    CGImageRelease (quartz_image);
+
+    *clone_out = (cairo_surface_t*) new_surface;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_nquartz_surface_get_extents (void *abstract_surface,
+				    cairo_rectangle_int16_t *extents)
+{
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+
+    *extents = surface->extents;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_nquartz_surface_paint (void *abstract_surface,
+			      cairo_operator_t op,
+			      cairo_pattern_t *source)
+{
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
+    cairo_nquartz_action_t action;
 
-    x1 = surface->extents.x;
-    x2 = surface->extents.x + surface->extents.width;
-    y1 = surface->extents.y;
-    y2 = surface->extents.y + surface->extents.height;
-
-    if (interest_rect->x > x1)
-	x1 = interest_rect->x;
-    if (interest_rect->y > y1)
-	y1 = interest_rect->y;
-    if (interest_rect->x + interest_rect->width < x2)
-	x2 = interest_rect->x + interest_rect->width;
-    if (interest_rect->y + interest_rect->height < y2)
-	y2 = interest_rect->y + interest_rect->height;
-
-    if (x1 >= x2 || y1 >= y2) {
-	*image_out = NULL;
-	*image_extra = NULL;
+    ND((stderr, "%p _cairo_nquartz_surface_paint op %d source->type %d\n", surface, op, source->type));
 
+    if (op == CAIRO_OPERATOR_DEST)
 	return CAIRO_STATUS_SUCCESS;
+
+    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
+
+    action = _cairo_nquartz_setup_source (surface, source);
+
+    if (action == DO_SOLID || action == DO_PATTERN) {
+	CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
+							  surface->extents.y,
+							  surface->extents.width,
+							  surface->extents.height));
+    } else if (action == DO_SHADING) {
+	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    } else {
+	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    image_rect->x = x1;
-    image_rect->y = y1;
-    image_rect->width = x2 - x1;
-    image_rect->height = y2 - y1;
-
-    data = calloc (image_rect->width * image_rect->height * 4, 1);
-    image_surface = cairo_image_surface_create_for_data (data,
-							 CAIRO_FORMAT_ARGB32,
-							 image_rect->width,
-							 image_rect->height,
-							 image_rect->width * 4);
+    _cairo_nquartz_teardown_source (surface, source);
 
-    *image_out = (cairo_image_surface_t *)image_surface;
-    *image_extra = data;
+    ND((stderr, "-- paint\n"));
+    return rv;
+}
 
-    return CAIRO_STATUS_SUCCESS;
+static cairo_int_status_t
+_cairo_nquartz_surface_fill (void *abstract_surface,
+			     cairo_operator_t op,
+			     cairo_pattern_t *source,
+			     cairo_path_fixed_t *path,
+			     cairo_fill_rule_t fill_rule,
+			     double tolerance,
+			     cairo_antialias_t antialias)
+{
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
+    cairo_nquartz_action_t action;
+
+    ND((stderr, "%p _cairo_nquartz_surface_fill op %d source->type %d\n", surface, op, source->type));
+
+    if (op == CAIRO_OPERATOR_DEST)
+	return CAIRO_STATUS_SUCCESS;
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    CGContextSaveGState (surface->cgContext);
+
+    CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
+    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
+
+    action = _cairo_nquartz_setup_source (surface, source);
+    if (action == DO_UNSUPPORTED) {
+	CGContextRestoreGState (surface->cgContext);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    CGContextBeginPath (surface->cgContext);
+    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
+
+    if (action == DO_SOLID || action == DO_PATTERN) {
+	if (fill_rule == CAIRO_FILL_RULE_WINDING)
+	    CGContextFillPath (surface->cgContext);
+	else
+	    CGContextEOFillPath (surface->cgContext);
+    } else if (action == DO_SHADING) {
+
+	// we have to clip and then paint the shading; we can't fill
+	// with the shading
+	if (fill_rule == CAIRO_FILL_RULE_WINDING)
+	    CGContextClip (surface->cgContext);
+	else
+	    CGContextEOClip (surface->cgContext);
+
+	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    } else {
+	rv = CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    _cairo_nquartz_teardown_source (surface, source);
+
+    CGContextRestoreGState (surface->cgContext);
+
+    ND((stderr, "-- fill\n"));
+    return rv;
 }
 
-static CGImageRef
-create_image_from_surface (cairo_image_surface_t *image_surface, void *data)
+static cairo_int_status_t
+_cairo_nquartz_surface_stroke (void *abstract_surface,
+			       cairo_operator_t op,
+			       cairo_pattern_t *source,
+			       cairo_path_fixed_t *path,
+			       cairo_stroke_style_t *style,
+			       cairo_matrix_t *ctm,
+			       cairo_matrix_t *ctm_inverse,
+			       double tolerance,
+			       cairo_antialias_t antialias)
 {
-  CGImageRef image;
-  CGColorSpaceRef color_space;
-  CGDataProviderRef data_provider;
-  int width, height;
-
-  width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface);
-  height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface);
-
-  color_space = CGColorSpaceCreateDeviceRGB();
-  data_provider = CGDataProviderCreateWithData (NULL, data,
-						width * height * 4, NULL);
-  image = CGImageCreate (width, height,
-			 8, 32,
-			 width * 4,
-			 color_space,
-			 kCGImageAlphaPremultipliedFirst,
-			 data_provider,
-			 NULL,
-			 FALSE, kCGRenderingIntentDefault);
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
+    cairo_nquartz_action_t action;
 
-  CGColorSpaceRelease (color_space);
-  CGDataProviderRelease (data_provider);
+    ND((stderr, "%p _cairo_nquartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
 
-  return image;
+    if (op == CAIRO_OPERATOR_DEST)
+	return CAIRO_STATUS_SUCCESS;
+
+    CGContextSaveGState (surface->cgContext);
+
+    // Turning antialiasing off causes misrendering with
+    // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels)
+    //CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
+    CGContextSetLineWidth (surface->cgContext, style->line_width);
+    CGContextSetLineCap (surface->cgContext, _cairo_nquartz_cairo_line_cap_to_quartz (style->line_cap));
+    CGContextSetLineJoin (surface->cgContext, _cairo_nquartz_cairo_line_join_to_quartz (style->line_join));
+    CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
+
+    if (style->dash && style->num_dashes) {
+#define STATIC_DASH 32
+	float sdash[STATIC_DASH];
+	float *fdash = sdash;
+	unsigned int k;
+	if (style->num_dashes > STATIC_DASH)
+	    fdash = malloc (sizeof(float)*style->num_dashes);
+
+	for (k = 0; k < style->num_dashes; k++)
+	    fdash[k] = (float) style->dash[k];
+	
+	CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, style->num_dashes);
+
+	if (fdash != sdash)
+	    free (fdash);
+    }
+
+    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
+
+    action = _cairo_nquartz_setup_source (surface, source);
+    if (action == DO_UNSUPPORTED) {
+	CGContextRestoreGState (surface->cgContext);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    CGContextBeginPath (surface->cgContext);
+    _cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
+
+    if (action == DO_SOLID || action == DO_PATTERN) {
+	CGContextStrokePath (surface->cgContext);
+    } else if (action == DO_SHADING) {
+	// we have to clip and then paint the shading; first we have to convert
+	// the stroke to a path that we can fill
+	CGContextReplacePathWithStrokedPath (surface->cgContext);
+	CGContextClip (surface->cgContext);
+
+	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    } else {
+	rv = CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    _cairo_nquartz_teardown_source (surface, source);
+
+    CGContextRestoreGState (surface->cgContext);
+
+    ND((stderr, "-- stroke\n"));
+    return rv;
 }
 
-static void
-_cairo_quartz_surface_release_dest_image(void                    *abstract_surface,
-                                         cairo_rectangle_int16_t *intersect_rect,
-                                         cairo_image_surface_t   *image,
-                                         cairo_rectangle_int16_t *image_rect,
-                                         void                    *image_extra)
+static cairo_int_status_t
+_cairo_nquartz_surface_show_glyphs (void *abstract_surface,
+				    cairo_operator_t op,
+				    cairo_pattern_t *source,
+				    cairo_glyph_t *glyphs,
+				    int num_glyphs,
+				    cairo_scaled_font_t *scaled_font)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
-    CGImageRef image_ref;
-    CGRect rect;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
+    cairo_nquartz_action_t action;
+    int i;
+
+    if (num_glyphs <= 0)
+	return CAIRO_STATUS_SUCCESS;
 
-    image_ref = create_image_from_surface (image, image_extra);
+    if (op == CAIRO_OPERATOR_DEST)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (!_cairo_scaled_font_is_atsui (scaled_font))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    CGContextSaveGState (surface->cgContext);
+
+    action = _cairo_nquartz_setup_source (surface, source);
+    if (action == DO_SOLID || action == DO_PATTERN) {
+	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
+    } else if (action == DO_SHADING) {
+	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
+    } else {
+	/* Unsupported */
+	CGContextRestoreGState (surface->cgContext);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
-    rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height);
+    CGContextSetCompositeOperation (surface->cgContext, _cairo_nquartz_cairo_operator_to_quartz (op));
 
-    if (surface->y_grows_down) {
-	CGContextSaveGState (surface->context);
-	CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y);
-	CGContextScaleCTM (surface->context, 1, -1);
+    ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
+    ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
+    CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
+
+    CGContextSetFont (surface->cgContext, cgfref);
+    CGFontRelease (cgfref);
+
+    /* So this should include the size; I don't know if I need to extract the
+     * size from this and call CGContextSetFontSize.. will I get crappy hinting
+     * with this 1.0 size business?  Or will CG just multiply that size into the
+     * text matrix?
+     */
+    //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
+    CGAffineTransform cairoTextTransform, textTransform;
+    _cairo_nquartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
+
+    textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
+    textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
+    textTransform = CGAffineTransformConcat (cairoTextTransform, textTransform);
+
+    CGContextSetTextMatrix (surface->cgContext, textTransform);
+    CGContextSetFontSize (surface->cgContext, 1.0);
+
+    // XXXtodo/perf: stack storage for glyphs/sizes
+#define STATIC_BUF_SIZE 64
+    CGGlyph glyphs_static[STATIC_BUF_SIZE];
+    CGSize cg_advances_static[STATIC_BUF_SIZE];
+    CGGlyph *cg_glyphs = &glyphs_static[0];
+    CGSize *cg_advances = &cg_advances_static[0];
+
+    if (num_glyphs > STATIC_BUF_SIZE) {
+	cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
+	cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
     }
 
-    CGContextDrawImage(surface->context, rect, image_ref);
-    CFRelease (image_ref);
+    double xprev = glyphs[0].x;
+    double yprev = glyphs[0].y;
 
-    if (surface->y_grows_down) {
-	CGContextRestoreGState (surface->context);
+    cg_glyphs[0] = glyphs[0].index;
+    cg_advances[0].width = 0;
+    cg_advances[0].height = 0;
+
+    for (i = 1; i < num_glyphs; i++) {
+	cg_glyphs[i] = glyphs[i].index;
+	cg_advances[i-1].width = glyphs[i].x - xprev;
+	cg_advances[i-1].height = glyphs[i].y - yprev;
+	xprev = glyphs[i].x;
+	yprev = glyphs[i].y;
     }
 
-    cairo_surface_destroy ((cairo_surface_t *)image);
-    free (image_extra);
+#if 0
+    for (i = 0; i < num_glyphs; i++) {
+	ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height));
+    }
+#endif
+
+    CGContextShowGlyphsWithAdvances (surface->cgContext,
+				     cg_glyphs,
+				     cg_advances,
+				     num_glyphs);
+
+    if (cg_glyphs != &glyphs_static[0]) {
+	free (cg_glyphs);
+	free (cg_advances);
+    }
+
+    if (action == DO_SHADING)
+	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+
+    _cairo_nquartz_teardown_source (surface, source);
+
+    CGContextRestoreGState (surface->cgContext);
+
+    return rv;
 }
 
 static cairo_int_status_t
-_cairo_quartz_surface_set_clip_region(void *abstract_surface,
-                                      pixman_region16_t * region)
+_cairo_nquartz_surface_mask (void *abstract_surface,
+			     cairo_operator_t op,
+			     cairo_pattern_t *source,
+			     cairo_pattern_t *mask)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+    cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
 
-    if (surface->clip_region)
-	pixman_region_destroy (surface->clip_region);
+    ND((stderr, "%p _cairo_nquartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type));
 
-    if (region) {
-	surface->clip_region = pixman_region_create ();
-	pixman_region_copy (surface->clip_region, region);
-    } else
-	surface->clip_region = NULL;
+    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
+	/* This is easy; we just need to paint with the alpha. */
+	cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
+
+	CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha);
+    } else {
+	/* So, CGContextClipToMask is not present in 10.3.9, so we're
+	 * doomed; if we have imageData, we can do fallback, otherwise
+	 * just pretend success.
+	 */
+	if (surface->imageData)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    return CAIRO_STATUS_SUCCESS;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    rv = _cairo_nquartz_surface_paint (surface, op, source);
+
+    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
+	CGContextSetAlpha (surface->cgContext, 1.0);
+    }
+
+    ND((stderr, "-- mask\n"));
+
+    return rv;
 }
 
 static cairo_int_status_t
-_cairo_quartz_surface_get_extents (void                    *abstract_surface,
-				   cairo_rectangle_int16_t *rectangle)
+_cairo_nquartz_surface_intersect_clip_path (void *abstract_surface,
+					    cairo_path_fixed_t *path,
+					    cairo_fill_rule_t fill_rule,
+					    double tolerance,
+					    cairo_antialias_t antialias)
 {
-    cairo_quartz_surface_t *surface = abstract_surface;
+    cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
+
+    ND((stderr, "%p _cairo_nquartz_surface_intersect_clip_path path: %p\n", surface, path));
+
+    if (path == NULL) {
+	/* If we're being asked to reset the clip, we can only do it
+	 * by restoring the gstate to our previous saved one, and
+	 * saving it again.
+	 *
+	 * Note that this assumes that ALL nquartz surface creation
+	 * functions will do a SaveGState first; we do this in create_internal.
+	 */
+	CGContextRestoreGState (surface->cgContext);
+	CGContextSaveGState (surface->cgContext);
+    } else {
+	CGContextBeginPath (surface->cgContext);
+	_cairo_nquartz_cairo_path_to_quartz_context (path, surface->cgContext);
+	if (fill_rule == CAIRO_FILL_RULE_WINDING)
+	    CGContextClip (surface->cgContext);
+	else
+	    CGContextEOClip (surface->cgContext);
+    }
 
-    *rectangle = surface->extents;
+    ND((stderr, "-- intersect_clip_path\n"));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
+// XXXtodo implement show_page; need to figure out how to handle begin/end
+
+static const struct _cairo_surface_backend cairo_nquartz_surface_backend = {
     CAIRO_SURFACE_TYPE_QUARTZ,
-    NULL, /* create_similar */
-    _cairo_quartz_surface_finish,
-    _cairo_quartz_surface_acquire_source_image,
+    _cairo_nquartz_surface_create_similar,
+    _cairo_nquartz_surface_finish,
+    _cairo_nquartz_surface_acquire_source_image,
     NULL, /* release_source_image */
-    _cairo_quartz_surface_acquire_dest_image,
-    _cairo_quartz_surface_release_dest_image,
-    NULL, /* clone_similar */
+    _cairo_nquartz_surface_acquire_dest_image,
+    _cairo_nquartz_surface_release_dest_image,
+    _cairo_nquartz_surface_clone_similar,
     NULL, /* composite */
     NULL, /* fill_rectangles */
     NULL, /* composite_trapezoids */
     NULL, /* copy_page */
     NULL, /* show_page */
-    _cairo_quartz_surface_set_clip_region,
-    NULL, /* intersect_clip_path */
-    _cairo_quartz_surface_get_extents,
-    NULL  /* old_show_glyphs */
+    NULL, /* set_clip_region */
+    _cairo_nquartz_surface_intersect_clip_path,
+    _cairo_nquartz_surface_get_extents,
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+
+    _cairo_nquartz_surface_paint,
+    _cairo_nquartz_surface_mask,
+    _cairo_nquartz_surface_stroke,
+    _cairo_nquartz_surface_fill,
+    _cairo_nquartz_surface_show_glyphs,
+
+    NULL, /* snapshot */
 };
 
-cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
-					     int width,
-					     int height,
-					     cairo_bool_t y_grows_down)
+static cairo_nquartz_surface_t *
+_cairo_nquartz_surface_create_internal (CGContextRef cgContext,
+					nquartz_agl_context_type aglContext,
+					cairo_content_t content,
+					unsigned int width,
+					unsigned int height)
 {
-    cairo_quartz_surface_t *surface;
-    CGRect clip_box;
+    cairo_nquartz_surface_t *surface;
 
-    surface = malloc(sizeof(cairo_quartz_surface_t));
+    /* Init the base surface */
+    surface = malloc(sizeof(cairo_nquartz_surface_t));
     if (surface == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return (cairo_surface_t*) &_cairo_surface_nil;
+	return NULL;
     }
 
-    /* XXX: The content value here might be totally wrong. */
-    _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend,
-			CAIRO_CONTENT_COLOR_ALPHA);
+    memset(surface, 0, sizeof(cairo_nquartz_surface_t));
+
+    _cairo_surface_init(&surface->base, &cairo_nquartz_surface_backend,
+			content);
+
+    /* Save our extents */
+    surface->extents.x = surface->extents.y = 0;
+    surface->extents.width = width;
+    surface->extents.height = height;
+
+    /* Save so we can always get back to a known-good CGContext -- this is
+     * required for proper behaviour of intersect_clip_path(NULL)
+     */
+    CGContextSaveGState (cgContext);
 
-    surface->context = context;
-    surface->clip_region = NULL;
-    surface->y_grows_down = y_grows_down;
+    surface->aglContext = aglContext;
+    surface->cgContext = cgContext;
+    surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
 
-    clip_box = CGContextGetClipBoundingBox (context);
-    surface->extents.x = clip_box.origin.x;
-    surface->extents.y = clip_box.origin.y;
-    surface->extents.width = clip_box.size.width;
-    surface->extents.height = clip_box.size.height;
+    surface->imageData = NULL;
 
-    return (cairo_surface_t *) surface;
+    return surface;
 }
+					 
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+cairo_surface_t *
+cairo_quartz_surface_create_for_agl_context (AGLContext aglContext,
+					     unsigned int width,
+					     unsigned int height)
+{
+    cairo_nquartz_surface_t *surf;
+    CGSize sz;
+
+    /* Make our CGContext from the AGL context */
+    sz.width = width;
+    sz.height = height;
+
+    CGContextRef cgc = CGGLContextCreate (aglContext, sz, NULL /* device RGB colorspace */);
+
+    surf = _cairo_nquartz_surface_create_internal (cgc, aglContext, CAIRO_CONTENT_COLOR_ALPHA,
+						   width, height);
+    if (!surf) {
+	CGContextRelease (cgc);
+	// create_internal will have set an error
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    return (cairo_surface_t *) surf;
+}
+#endif
+
+/**
+ * cairo_quartz_surface_create_for_cg_context
+ * @cgContext: the existing CGContext for which to create the surface
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a Quartz surface that wraps the given CGContext.  The
+ * CGContext is assumed to be in the QuickDraw coordinate space (that
+ * is, with the origin at the upper left and the Y axis increasing
+ * downward.)  If the CGContext is in the Quartz coordinate space (with
+ * the origin at the bottom left), then it should be flipped before
+ * this function is called:
+ *
+ * <informalexample><programlisting>
+ * GContextTranslateCTM (cgContext, 0.0, height);
+ * CGContextScaleCTM (cgContext, 1.0, -1.0);
+ * </programlisting></informalexample>
+ *
+ * A very small number of Cairo operations cannot be translated to
+ * Quartz operations; those operations will fail on this surface.
+ * If all Cairo operations are required to succeed, consider rendering
+ * to a surface created by cairo_quartz_surface_create() and then copying
+ * the result to the CGContext.
+ *
+ * Return value: the newly created Cairo surface.
+ *
+ * Since: 1.4
+ **/
 
-int
-_cairo_surface_is_quartz (cairo_surface_t *surface)
+cairo_surface_t *
+cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
+					    unsigned int width,
+					    unsigned int height)
 {
-    return surface->backend == &cairo_quartz_surface_backend;
+    cairo_nquartz_surface_t *surf;
+
+    CGContextRetain (cgContext);
+
+    surf = _cairo_nquartz_surface_create_internal (cgContext, NULL, CAIRO_CONTENT_COLOR_ALPHA,
+						   width, height);
+    if (!surf) {
+	CGContextRelease (cgContext);
+	// create_internal will have set an error
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    return (cairo_surface_t *) surf;
 }
+
+/**
+ * cairo_quartz_surface_create
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a Quartz surface backed by a CGBitmap.  The surface is
+ * created using the Device RGB (or Device Gray, for A8) color space.
+ * All Cairo operations, including those that require software
+ * rendering, will succeed on this surface.
+ *
+ * Return value: the newly created surface.
+ *
+ * Since: 1.4
+ **/
+cairo_surface_t *
+cairo_quartz_surface_create (cairo_format_t format,
+			     unsigned int width,
+			     unsigned int height)
+{
+    cairo_nquartz_surface_t *surf;
+    CGContextRef cgc;
+    CGColorSpaceRef cgColorspace;
+    CGBitmapInfo bitinfo;
+    void *imageData;
+    int stride;
+    int bitsPerComponent;
+
+    if (format == CAIRO_FORMAT_ARGB32) {
+	cgColorspace = CGColorSpaceCreateDeviceRGB();
+	stride = width * 4;
+	bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+	bitsPerComponent = 8;
+    } else if (format == CAIRO_FORMAT_RGB24) {
+	cgColorspace = CGColorSpaceCreateDeviceRGB();
+	stride = width * 4;
+	bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
+	bitsPerComponent = 8;
+    } else if (format == CAIRO_FORMAT_A8) {
+	cgColorspace = CGColorSpaceCreateDeviceGray();
+	if (width % 4 == 0)
+	    stride = width;
+	else
+	    stride = (width & ~3) + 4;
+	bitinfo = kCGImageAlphaNone;
+	bitsPerComponent = 8;
+    } else if (format == CAIRO_FORMAT_A1) {
+	/* I don't think we can usefully support this, as defined by
+	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
+	 * quantities.
+	 */
+	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    } else {
+	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    imageData = malloc (height * stride);
+    if (!imageData) {
+	CGColorSpaceRelease (cgColorspace);
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    cgc = CGBitmapContextCreate (imageData,
+				 width,
+				 height,
+				 bitsPerComponent,
+				 stride,
+				 cgColorspace,
+				 bitinfo);
+    CGColorSpaceRelease (cgColorspace);
+
+    if (!cgc) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    /* flip the Y axis */
+    CGContextTranslateCTM (cgc, 0.0, height);
+    CGContextScaleCTM (cgc, 1.0, -1.0);
+
+    surf = _cairo_nquartz_surface_create_internal (cgc, NULL, _cairo_content_from_format (format),
+						   width, height);
+    if (!surf) {
+	CGContextRelease (cgc);
+	// create_internal will have set an error
+	return (cairo_surface_t*) &_cairo_surface_nil;
+    }
+
+    surf->imageData = imageData;
+
+    return (cairo_surface_t *) surf;
+}
+
+/**
+ * cairo_quartz_surface_get_cg_context
+ * @surf: the Cairo Quartz surface
+ *
+ * Returns the CGContextRef that the given Quartz surface is backed
+ * by.
+ *
+ * Return value: the CGContextRef for the given surface.
+ *
+ * Since: 1.4
+ **/
+CGContextRef
+cairo_quartz_surface_get_cg_context (cairo_surface_t *surf)
+{
+    cairo_nquartz_surface_t *nquartz = (cairo_nquartz_surface_t*)surf;
+
+    if (cairo_surface_get_type(surf) != CAIRO_SURFACE_TYPE_QUARTZ)
+	return NULL;
+
+    return nquartz->cgContext;
+}
+
+
+/* Debug stuff */
+
+#ifdef NQUARTZ_DEBUG
+
+#include <Movies.h>
+
+void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest)
+{
+    Handle  dataRef = NULL;
+    OSType  dataRefType;
+    CFStringRef inPath = CFStringCreateWithCString(NULL, dest, kCFStringEncodingASCII);
+
+    GraphicsExportComponent grex = 0;
+    unsigned long sizeWritten;
+
+    ComponentResult result;
+
+    // create the data reference
+    result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle,
+						    0, &dataRef, &dataRefType);
+
+    if (NULL != dataRef && noErr == result) {
+	// get the PNG exporter
+	result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG,
+				       &grex);
+
+	if (grex) {
+	    // tell the exporter where to find its source image
+	    result = GraphicsExportSetInputCGImage(grex, inImageRef);
+
+	    if (noErr == result) {
+		// tell the exporter where to save the exporter image
+		result = GraphicsExportSetOutputDataReference(grex, dataRef,
+							      dataRefType);
+
+		if (noErr == result) {
+		    // write the PNG file
+		    result = GraphicsExportDoExport(grex, &sizeWritten);
+		}
+	    }
+
+	    // remember to close the component
+	    CloseComponent(grex);
+	}
+
+	// remember to dispose of the data reference handle
+	DisposeHandle(dataRef);
+    }
+}
+#endif
+
+void
+nquartz_image_to_png (CGImageRef imgref, char *dest)
+{
+#if 0
+    static int sctr = 0;
+    char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png";
+
+    if (dest == NULL) {
+	fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr);
+	sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr);
+	sctr++;
+	dest = sptr;
+    }
+
+    ExportCGImageToPNGFile(imgref, dest);
+#endif
+}
+
+void
+nquartz_surface_to_png (cairo_nquartz_surface_t *nq, char *dest)
+{
+#if 0
+    static int sctr = 0;
+    char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png";
+
+    if (nq->base.type != CAIRO_SURFACE_TYPE_QUARTZ) {
+	fprintf (stderr, "** nquartz_surface_to_png: surface %p isn't nquartz!\n", nq);
+	return;
+    }
+
+    if (dest == NULL) {
+	fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr);
+	sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr);
+	sctr++;
+	dest = sptr;
+    }
+
+    CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext);
+    if (imgref == NULL) {
+	fprintf (stderr, "nquartz surface at %p is not a bitmap context!\n", nq);
+	return;
+    }
+
+    ExportCGImageToPNGFile(imgref, dest);
+
+    CGImageRelease(imgref);
+#endif
+}
+
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index 286efe8..d0d87c2 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -1,6 +1,6 @@
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2002 University of Southern California
+ * Copyright © 2006, 2007 Mozilla Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -27,15 +27,14 @@
  *
  * The Original Code is the cairo graphics library.
  *
- * The Initial Developer of the Original Code is University of Southern
- * California.
+ * The Initial Developer of the Original Code is Mozilla Corporation.
  *
  * Contributor(s):
- *	Carl D. Worth <cworth at cworth.org>
+ *      Vladimir Vukicevic <vladimir at mozilla.com>
  */
 
-#ifndef CAIRO_QUARTZ_H
-#define CAIRO_QUARTZ_H
+#ifndef CAIRO_NQUARTZ_H
+#define CAIRO_NQUARTZ_H
 
 #include <cairo.h>
 
@@ -43,13 +42,31 @@
 
 #include <Carbon/Carbon.h>
 
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+#include <AGL/agl.h>
+#endif
+
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
-cairo_quartz_surface_create (CGContextRef    context,
-			     int	     width,
-			     int	     height,
-			     cairo_bool_t    y_grows_down);
+cairo_quartz_surface_create (cairo_format_t format,
+                             unsigned int width,
+                             unsigned int height);
+
+#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
+cairo_public cairo_surface_t *
+cairo_quartz_surface_create_for_agl_context (AGLContext aglContext,
+                                             unsigned int width,
+                                             unsigned int height);
+#endif
+
+cairo_public cairo_surface_t *
+cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
+                                            unsigned int width,
+                                            unsigned int height);
+
+cairo_public CGContextRef
+cairo_quartz_surface_get_cg_context (cairo_surface_t *surf);
 
 CAIRO_END_DECLS
 
@@ -57,4 +74,4 @@ CAIRO_END_DECLS
 # error Cairo was not compiled with support for the quartz backend
 #endif /* CAIRO_HAS_QUARTZ_SURFACE */
 
-#endif /* CAIRO_QUARTZ_H */
+#endif /* CAIRO_NQUARTZ_H */
diff --git a/src/cairo.h b/src/cairo.h
index 1c3fb25..2cb8e96 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1321,7 +1321,6 @@ typedef enum _cairo_surface_type {
     CAIRO_SURFACE_TYPE_BEOS,
     CAIRO_SURFACE_TYPE_DIRECTFB,
     CAIRO_SURFACE_TYPE_SVG,
-    CAIRO_SURFACE_TYPE_NQUARTZ,
     CAIRO_SURFACE_TYPE_OS2
 } cairo_surface_type_t;
 
diff --git a/test/get-clip.c b/test/get-clip.c
index f6a2f5a..0de84e9 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -135,16 +135,15 @@ draw (cairo_t *cr, int width, int height
     case CAIRO_SURFACE_TYPE_XLIB:
     case CAIRO_SURFACE_TYPE_XCB:
     case CAIRO_SURFACE_TYPE_GLITZ:
-    case CAIRO_SURFACE_TYPE_QUARTZ:
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
         uses_clip_rects = TRUE;
 	break;
+    case CAIRO_SURFACE_TYPE_QUARTZ:
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
     case CAIRO_SURFACE_TYPE_SVG:
-    case CAIRO_SURFACE_TYPE_NQUARTZ:
     case CAIRO_SURFACE_TYPE_OS2:
     default:
         uses_clip_rects = FALSE;


More information about the cairo-commit mailing list