[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
- Previous message: [cairo-commit]
goocanvas/src goocanvas.c, 1.6, 1.7 goocanvastable.c,
1.6, 1.7 goocanvastable.h, 1.4, 1.5 goocanvastext.c, 1.12,
1.13 goocanvaswidget.c, 1.4, 1.5
- Next message: [cairo-commit] goocanvas ChangeLog,1.82,1.83 TODO,1.26,1.27
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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;
- Previous message: [cairo-commit]
goocanvas/src goocanvas.c, 1.6, 1.7 goocanvastable.c,
1.6, 1.7 goocanvastable.h, 1.4, 1.5 goocanvastext.c, 1.12,
1.13 goocanvaswidget.c, 1.4, 1.5
- Next message: [cairo-commit] goocanvas ChangeLog,1.82,1.83 TODO,1.26,1.27
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list