+++ /dev/null
---- a/src/cairo-quartz-font.c 2012-11-13 18:20:00.000000000 -0800
-+++ b/src/cairo-quartz-font.c 2012-11-13 18:06:56.000000000 -0800
-@@ -90,8 +90,9 @@ static int (*CGFontGetAscentPtr) (CGFont
- static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL;
- static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL;
-
--/* Not public anymore in 64-bits nor in 10.7 */
--static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL;
-+/* CTFontCreateWithGraphicsFont is not public until 10.5. */
-+typedef const struct __CTFontDescriptor *CTFontDescriptorRef;
-+static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform *, CTFontDescriptorRef) = NULL;
-
- static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
- static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
-@@ -130,7 +131,7 @@ quartz_font_ensure_symbols(void)
- CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
- CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
-
-- FMGetATSFontRefFromFontPtr = dlsym(RTLD_DEFAULT, "FMGetATSFontRefFromFont");
-+ CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont");
-
- if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
- CGFontGetGlyphBBoxesPtr &&
-@@ -155,6 +156,7 @@ struct _cairo_quartz_font_face {
- cairo_font_face_t base;
-
- CGFontRef cgFont;
-+ CTFontRef ctFont;
- };
-
- /*
-@@ -239,6 +241,10 @@ _cairo_quartz_font_face_destroy (void *a
- {
- cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
-
-+ if (font_face->ctFont) {
-+ CFRelease (font_face->ctFont);
-+ }
-+
- CGFontRelease (font_face->cgFont);
- }
-
-@@ -363,6 +369,12 @@ cairo_quartz_font_face_create_for_cgfont
-
- font_face->cgFont = CGFontRetain (font);
-
-+ if (CTFontCreateWithGraphicsFontPtr) {
-+ font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL);
-+ } else {
-+ font_face->ctFont = NULL;
-+ }
-+
- _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
-
- return &font_face->base;
-@@ -782,49 +794,10 @@ _cairo_quartz_scaled_font_get_cg_font_re
- return ffont->cgFont;
- }
-
--/*
-- * compat with old ATSUI backend
-- */
--
--/**
-- * cairo_quartz_font_face_create_for_atsu_font_id
-- * @font_id: an ATSUFontID for the font.
-- *
-- * Creates a new font for the Quartz font backend based on an
-- * #ATSUFontID. This font can then be used with
-- * cairo_set_font_face() or cairo_scaled_font_create().
-- *
-- * Return value: a newly created #cairo_font_face_t. Free with
-- * cairo_font_face_destroy() when you are done using it.
-- *
-- * Since: 1.6
-- **/
--cairo_font_face_t *
--cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id)
-+CTFontRef
-+_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font)
- {
-- quartz_font_ensure_symbols();
--
-- if (FMGetATSFontRefFromFontPtr != NULL) {
-- ATSFontRef atsFont = FMGetATSFontRefFromFontPtr (font_id);
-- CGFontRef cgFont = CGFontCreateWithPlatformFont (&atsFont);
-- cairo_font_face_t *ff;
--
-- ff = cairo_quartz_font_face_create_for_cgfont (cgFont);
--
-- CGFontRelease (cgFont);
--
-- return ff;
-- } else {
-- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-- return (cairo_font_face_t *)&_cairo_font_face_nil;
-- }
--}
--
--/* This is the old name for the above function, exported for compat purposes */
--cairo_font_face_t *cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id);
-+ cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
-
--cairo_font_face_t *
--cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
--{
-- return cairo_quartz_font_face_create_for_atsu_font_id (font_id);
-+ return ffont->ctFont;
- }
---- a/src/cairo-quartz-image-surface.c 2010-06-18 04:47:13.000000000 -0700
-+++ b/src/cairo-quartz-image-surface.c 2012-11-13 18:06:56.000000000 -0800
-@@ -148,6 +148,8 @@ _cairo_quartz_image_surface_flush (void
- surface->image = newImage;
- CGImageRelease (oldImage);
-
-+ surface->base.is_clear = surface->imageSurface->base.is_clear;
-+
- return CAIRO_STATUS_SUCCESS;
- }
-
-@@ -270,6 +272,8 @@ cairo_quartz_image_surface_create (cairo
- qisurf->image = image;
- qisurf->imageSurface = image_surface;
-
-+ qisurf->base.is_clear = image_surface->base.is_clear;
-+
- return &qisurf->base;
- }
-
---- a/src/cairo-quartz-private.h 2010-12-25 06:21:34.000000000 -0800
-+++ b/src/cairo-quartz-private.h 2012-11-13 18:06:56.000000000 -0800
-@@ -50,6 +50,9 @@ typedef CGFloat cairo_quartz_float_t;
- typedef float cairo_quartz_float_t;
- #endif
-
-+/* define CTFontRef for pre-10.5 SDKs */
-+typedef const struct __CTFont *CTFontRef;
-+
- typedef struct cairo_quartz_surface {
- cairo_surface_t base;
-
-@@ -60,21 +63,22 @@ typedef struct cairo_quartz_surface {
- cairo_surface_t *imageSurfaceEquiv;
-
- cairo_surface_clipper_t clipper;
-- cairo_rectangle_int_t extents;
-
-- /* These are stored while drawing operations are in place, set up
-- * by quartz_setup_source() and quartz_finish_source()
-+ /**
-+ * If non-null, this is a CGImage representing the contents of the surface.
-+ * We clear this out before any painting into the surface, so that we
-+ * don't force a copy to be created.
- */
-- CGAffineTransform sourceTransform;
-+ CGImageRef bitmapContextImage;
-
-- CGImageRef sourceImage;
-- cairo_surface_t *sourceImageSurface;
-- CGRect sourceImageRect;
-+ /**
-+ * If non-null, this is the CGLayer for the surface.
-+ */
-+ CGLayerRef cgLayer;
-
-- CGShadingRef sourceShading;
-- CGPatternRef sourcePattern;
-+ cairo_rectangle_int_t extents;
-
-- CGInterpolationQuality oldInterpolationQuality;
-+ cairo_bool_t ownsData;
- } cairo_quartz_surface_t;
-
- typedef struct cairo_quartz_image_surface {
-@@ -103,6 +107,9 @@ _cairo_quartz_create_cgimage (cairo_form
- CGFontRef
- _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
-
-+CTFontRef
-+_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *sfont);
-+
- #else
-
- # error Cairo was not compiled with support for the quartz backend
---- a/src/cairo-quartz-surface.c 2012-11-13 18:20:00.000000000 -0800
-+++ b/src/cairo-quartz-surface.c 2012-11-13 18:06:56.000000000 -0800
-@@ -41,6 +41,8 @@
-
- #include "cairo-error-private.h"
- #include "cairo-surface-clipper-private.h"
-+#include "cairo-gstate-private.h"
-+#include "cairo-private.h"
-
- #include <dlfcn.h>
-
-@@ -77,6 +79,11 @@
- * This macro can be used to conditionally compile backend-specific code.
- */
-
-+/* Here are some of the differences between cairo and CoreGraphics
-+ - cairo has only a single source active at once vs. CoreGraphics having
-+ separate sources for stroke and fill
-+*/
-+
- /* This method is private, but it exists. Its params are are exposed
- * as args to the NS* method, but not as CG.
- */
-@@ -126,6 +133,12 @@ static void (*CGContextSetShouldAntialia
- static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
- static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
- static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL;
-+static CGFloat (*CGContextGetAlphaPtr) (CGContextRef) = NULL;
-+
-+/* CTFontDrawGlyphs is not available until 10.7 */
-+static void (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL;
-+
-+static SInt32 _cairo_quartz_osx_version = 0x0;
-
- static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
-
-@@ -160,6 +173,14 @@ static void quartz_ensure_symbols(void)
- CGContextCopyPathPtr = dlsym(RTLD_DEFAULT, "CGContextCopyPath");
- CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
- CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
-+ CGContextGetAlphaPtr = dlsym(RTLD_DEFAULT, "CGContextGetAlpha");
-+
-+ CTFontDrawGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
-+
-+ if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) {
-+ // assume 10.5
-+ _cairo_quartz_osx_version = 0x1050;
-+ }
-
- _cairo_quartz_symbol_lookup_done = TRUE;
- }
-@@ -430,6 +446,7 @@ _cairo_quartz_cairo_operator_to_quartz_c
- case CAIRO_OPERATOR_HSL_LUMINOSITY:
- default:
- assert (0);
-+ return kPrivateCGCompositeClear;
- }
- }
-
-@@ -598,10 +615,13 @@ _cairo_quartz_cairo_matrix_to_quartz (co
- typedef struct {
- bool isClipping;
- CGGlyph *cg_glyphs;
-- CGSize *cg_advances;
-+ union {
-+ CGSize *cg_advances;
-+ CGPoint *cg_positions;
-+ } u;
- size_t nglyphs;
- CGAffineTransform textTransform;
-- CGFontRef font;
-+ cairo_scaled_font_t *scaled_font;
- CGPoint origin;
- } unbounded_show_glyphs_t;
-
-@@ -679,12 +699,6 @@ _cairo_quartz_fixup_unbounded_operation
- else
- CGContextEOFillPath (cgc);
- } else if (op->op == UNBOUNDED_SHOW_GLYPHS) {
-- CGContextSetFont (cgc, op->u.show_glyphs.font);
-- CGContextSetFontSize (cgc, 1.0);
-- CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
-- CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
-- CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
--
- if (op->u.show_glyphs.isClipping) {
- /* Note that the comment in show_glyphs about kCGTextClip
- * and the text transform still applies here; however, the
-@@ -693,12 +707,25 @@ _cairo_quartz_fixup_unbounded_operation
- CGContextSetTextDrawingMode (cgc, kCGTextClip);
- CGContextSaveGState (cgc);
- }
-+ CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
-+ CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
-+ if (CTFontDrawGlyphsPtr) {
-+ CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (op->u.show_glyphs.scaled_font),
-+ op->u.show_glyphs.cg_glyphs,
-+ op->u.show_glyphs.u.cg_positions,
-+ op->u.show_glyphs.nglyphs,
-+ cgc);
-+ } else {
-+ CGContextSetFont (cgc, _cairo_quartz_scaled_font_get_cg_font_ref (op->u.show_glyphs.scaled_font));
-+ CGContextSetFontSize (cgc, 1.0);
-+ CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
-+
-+ CGContextShowGlyphsWithAdvances (cgc,
-+ op->u.show_glyphs.cg_glyphs,
-+ op->u.show_glyphs.u.cg_advances,
-+ op->u.show_glyphs.nglyphs);
-
-- CGContextShowGlyphsWithAdvances (cgc,
-- op->u.show_glyphs.cg_glyphs,
-- op->u.show_glyphs.cg_advances,
-- op->u.show_glyphs.nglyphs);
--
-+ }
- if (op->u.show_glyphs.isClipping) {
- CGContextClearRect (cgc, clipBoxRound);
- CGContextRestoreGState (cgc);
-@@ -1102,12 +1129,12 @@ DataProviderReleaseCallback (void *info,
- {
- quartz_source_image_t *source_img = info;
- _cairo_surface_release_source_image (source_img->surface, source_img->image_out, source_img->image_extra);
-+ cairo_surface_destroy (source_img->surface);
- free (source_img);
- }
-
- static cairo_status_t
--_cairo_surface_to_cgimage (cairo_surface_t *target,
-- cairo_surface_t *source,
-+_cairo_surface_to_cgimage (cairo_surface_t *source,
- CGImageRef *image_out)
- {
- cairo_status_t status;
-@@ -1127,9 +1154,14 @@ _cairo_surface_to_cgimage (cairo_surface
- }
-
- if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) {
-- *image_out = CGBitmapContextCreateImage (surface->cgContext);
-- if (*image_out)
-- return CAIRO_STATUS_SUCCESS;
-+ if (!surface->bitmapContextImage) {
-+ surface->bitmapContextImage =
-+ CGBitmapContextCreateImage (surface->cgContext);
-+ }
-+ if (surface->bitmapContextImage) {
-+ *image_out = CGImageRetain (surface->bitmapContextImage);
-+ return CAIRO_STATUS_SUCCESS;
-+ }
- }
- }
-
-@@ -1137,10 +1169,11 @@ _cairo_surface_to_cgimage (cairo_surface
- if (source_img == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-- source_img->surface = source;
-+ source_img->surface = cairo_surface_reference(source);
-
- status = _cairo_surface_acquire_source_image (source_img->surface, &source_img->image_out, &source_img->image_extra);
- if (status) {
-+ cairo_surface_destroy (source_img->surface);
- free (source_img);
- return status;
- }
-@@ -1251,7 +1284,7 @@ _cairo_quartz_cairo_repeating_surface_pa
- is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
- assert (is_bounded);
-
-- status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image);
-+ status = _cairo_surface_to_cgimage (pat_surf, &image);
- if (status)
- return status;
- if (image == NULL)
-@@ -1322,16 +1355,43 @@ typedef enum {
- DO_SHADING,
- DO_PATTERN,
- DO_IMAGE,
-+ DO_TILED_IMAGE,
-+ DO_LAYER,
- DO_UNSUPPORTED,
-- DO_NOTHING,
-- DO_TILED_IMAGE
-+ DO_NOTHING
- } cairo_quartz_action_t;
-
--static cairo_quartz_action_t
-+/* State used during a drawing operation. */
-+typedef struct {
-+ CGContextRef context;
-+ cairo_quartz_action_t action;
-+
-+ // Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
-+ CGAffineTransform transform;
-+
-+ // Used with DO_IMAGE and DO_TILED_IMAGE
-+ CGImageRef image;
-+ cairo_surface_t *imageSurface;
-+
-+ // Used with DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
-+ CGRect imageRect;
-+
-+ // Used with DO_LAYER
-+ CGLayerRef layer;
-+
-+ // Used with DO_SHADING
-+ CGShadingRef shading;
-+
-+ // Used with DO_PATTERN
-+ CGPatternRef pattern;
-+} cairo_quartz_drawing_state_t;
-+
-+static void
- _cairo_quartz_setup_fallback_source (cairo_quartz_surface_t *surface,
-- const cairo_pattern_t *source)
-+ const cairo_pattern_t *source,
-+ cairo_quartz_drawing_state_t *state)
- {
-- CGRect clipBox = CGContextGetClipBoundingBox (surface->cgContext);
-+ CGRect clipBox = CGContextGetClipBoundingBox (state->context);
- double x0, y0, w, h;
-
- cairo_surface_t *fallback;
-@@ -1340,8 +1400,10 @@ _cairo_quartz_setup_fallback_source (cai
- cairo_status_t status;
-
- if (clipBox.size.width == 0.0f ||
-- clipBox.size.height == 0.0f)
-- return DO_NOTHING;
-+ clipBox.size.height == 0.0f) {
-+ state->action = DO_NOTHING;
-+ return;
-+ }
-
- x0 = floor(clipBox.origin.x);
- y0 = floor(clipBox.origin.y);
-@@ -1384,18 +1446,21 @@ _cairo_quartz_setup_fallback_source (cai
- }
- #endif
-
-- status = _cairo_surface_to_cgimage (&surface->base, fallback, &img);
-- if (status)
-- return DO_UNSUPPORTED;
-- if (img == NULL)
-- return DO_NOTHING;
--
-- surface->sourceImageRect = CGRectMake (0.0, 0.0, w, h);
-- surface->sourceImage = img;
-- surface->sourceImageSurface = fallback;
-- surface->sourceTransform = CGAffineTransformMakeTranslation (x0, y0);
-+ status = _cairo_surface_to_cgimage (fallback, &img);
-+ if (status) {
-+ state->action = DO_UNSUPPORTED;
-+ return;
-+ }
-+ if (img == NULL) {
-+ state->action = DO_NOTHING;
-+ return;
-+ }
-
-- return DO_IMAGE;
-+ state->imageRect = CGRectMake (0.0, 0.0, w, h);
-+ state->image = img;
-+ state->imageSurface = fallback;
-+ state->transform = CGAffineTransformMakeTranslation (x0, y0);
-+ state->action = DO_IMAGE;
- }
-
- /*
-@@ -1411,10 +1476,11 @@ based on the extents of the object (the
- we don't want the rasterization of the entire gradient to depend on the
- clip region).
- */
--static cairo_quartz_action_t
-+static void
- _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
- const cairo_linear_pattern_t *lpat,
-- cairo_rectangle_int_t *extents)
-+ cairo_rectangle_int_t *extents,
-+ cairo_quartz_drawing_state_t *state)
- {
- const cairo_pattern_t *abspat = &lpat->base.base;
- cairo_matrix_t mat;
-@@ -1424,9 +1490,10 @@ _cairo_quartz_setup_linear_source (cairo
- bool extend = abspat->extend == CAIRO_EXTEND_PAD;
-
- if (lpat->base.n_stops == 0) {
-- CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.);
-- CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.);
-- return DO_SOLID;
-+ CGContextSetRGBStrokeColor (state->context, 0., 0., 0., 0.);
-+ CGContextSetRGBFillColor (state->context, 0., 0., 0., 0.);
-+ state->action = DO_SOLID;
-+ return;
- }
-
- if (lpat->p1.x == lpat->p2.x &&
-@@ -1436,12 +1503,13 @@ _cairo_quartz_setup_linear_source (cairo
- * Whatever the correct behaviour is, let's at least have only pixman's
- * implementation to worry about.
- */
-- return _cairo_quartz_setup_fallback_source (surface, abspat);
-+ _cairo_quartz_setup_fallback_source (surface, abspat, state);
-+ return;
- }
-
- mat = abspat->matrix;
- cairo_matrix_invert (&mat);
-- _cairo_quartz_cairo_matrix_to_quartz (&mat, &surface->sourceTransform);
-+ _cairo_quartz_cairo_matrix_to_quartz (&mat, &state->transform);
-
- rgb = CGColorSpaceCreateDeviceRGB();
-
-@@ -1461,21 +1529,22 @@ _cairo_quartz_setup_linear_source (cairo
- extents);
- }
-
-- surface->sourceShading = CGShadingCreateAxial (rgb,
-- start, end,
-- gradFunc,
-- extend, extend);
-+ state->shading = CGShadingCreateAxial (rgb,
-+ start, end,
-+ gradFunc,
-+ extend, extend);
-
- CGColorSpaceRelease(rgb);
- CGFunctionRelease(gradFunc);
-
-- return DO_SHADING;
-+ state->action = DO_SHADING;
- }
-
--static cairo_quartz_action_t
-+static void
- _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
- const cairo_radial_pattern_t *rpat,
-- cairo_rectangle_int_t *extents)
-+ cairo_rectangle_int_t *extents,
-+ cairo_quartz_drawing_state_t *state)
- {
- const cairo_pattern_t *abspat = &rpat->base.base;
- cairo_matrix_t mat;
-@@ -1494,9 +1563,10 @@ _cairo_quartz_setup_radial_source (cairo
- double centerDistance = sqrt (dx*dx + dy*dy);
-
- if (rpat->base.n_stops == 0) {
-- CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.);
-- CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.);
-- return DO_SOLID;
-+ CGContextSetRGBStrokeColor (state->context, 0., 0., 0., 0.);
-+ CGContextSetRGBFillColor (state->context, 0., 0., 0., 0.);
-+ state->action = DO_SOLID;
-+ return;
- }
-
- if (r2 <= centerDistance + r1 + 1e-6 && /* circle 2 doesn't contain circle 1 */
-@@ -1507,12 +1577,13 @@ _cairo_quartz_setup_radial_source (cairo
- * implementation to worry about.
- * Note that this also catches the cases where r1 == r2.
- */
-- return _cairo_quartz_setup_fallback_source (surface, abspat);
-+ _cairo_quartz_setup_fallback_source (surface, abspat, state);
-+ return;
- }
-
- mat = abspat->matrix;
- cairo_matrix_invert (&mat);
-- _cairo_quartz_cairo_matrix_to_quartz (&mat, &surface->sourceTransform);
-+ _cairo_quartz_cairo_matrix_to_quartz (&mat, &state->transform);
-
- rgb = CGColorSpaceCreateDeviceRGB();
-
-@@ -1531,90 +1602,79 @@ _cairo_quartz_setup_radial_source (cairo
- extents);
- }
-
-- surface->sourceShading = CGShadingCreateRadial (rgb,
-- start,
-- r1,
-- end,
-- r2,
-- gradFunc,
-- extend, extend);
-+ state->shading = CGShadingCreateRadial (rgb,
-+ start,
-+ r1,
-+ end,
-+ r2,
-+ gradFunc,
-+ extend, extend);
-
- CGColorSpaceRelease(rgb);
- CGFunctionRelease(gradFunc);
-
-- return DO_SHADING;
-+ state->action = DO_SHADING;
- }
-
--static cairo_quartz_action_t
--_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
-- const cairo_pattern_t *source,
-- cairo_rectangle_int_t *extents)
-+static void
-+_cairo_quartz_setup_surface_source (cairo_quartz_surface_t *surface,
-+ const cairo_surface_pattern_t *spat,
-+ cairo_rectangle_int_t *extents,
-+ cairo_quartz_drawing_state_t *state)
- {
-- assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
--
-- surface->oldInterpolationQuality = CGContextGetInterpolationQuality (surface->cgContext);
-- CGContextSetInterpolationQuality (surface->cgContext, _cairo_quartz_filter_to_quartz (source->filter));
-+ const cairo_pattern_t *source = &spat->base;
-+ CGContextRef context = state->context;
-
-- 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;
-- }
--
-- if (source->type == CAIRO_PATTERN_TYPE_LINEAR) {
-- const cairo_linear_pattern_t *lpat = (const cairo_linear_pattern_t *)source;
-- return _cairo_quartz_setup_linear_source (surface, lpat, extents);
-- }
--
-- if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
-- const cairo_radial_pattern_t *rpat = (const cairo_radial_pattern_t *)source;
-- return _cairo_quartz_setup_radial_source (surface, rpat, extents);
-- }
--
-- if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
-- (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
-+ if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD ||
-+ (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
- {
-- const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source;
- cairo_surface_t *pat_surf = spat->surface;
- CGImageRef img;
- cairo_matrix_t m = spat->base.matrix;
- cairo_rectangle_int_t extents;
-- cairo_status_t status;
- CGAffineTransform xform;
- CGRect srcRect;
- cairo_fixed_t fw, fh;
- cairo_bool_t is_bounded;
-+ cairo_bool_t repeat = source->extend == CAIRO_EXTEND_REPEAT;
-+ cairo_status_t status;
-
-- status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
-- if (status)
-- return DO_UNSUPPORTED;
-- if (img == NULL)
-- return DO_NOTHING;
-+ cairo_matrix_invert(&m);
-+ _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
-
-- CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
-+ /* Draw nonrepeating CGLayer surface using DO_LAYER */
-+ if (!repeat && cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
-+ cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
-+ if (quartz_surf->cgLayer) {
-+ state->imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
-+ state->layer = quartz_surf->cgLayer;
-+ state->action = DO_LAYER;
-+ return;
-+ }
-+ }
-+
-+ status = _cairo_surface_to_cgimage (pat_surf, &img);
-+ if (status) {
-+ state->action = DO_UNSUPPORTED;
-+ return;
-+ }
-+ if (img == NULL) {
-+ state->action = DO_NOTHING;
-+ return;
-+ }
-
-- surface->sourceImage = img;
-+ /* XXXroc what is this for? */
-+ CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
-
-- cairo_matrix_invert(&m);
-- _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceTransform);
-+ state->image = img;
-
- is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
- assert (is_bounded);
-
-- if (source->extend == CAIRO_EXTEND_NONE) {
-- surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
-- return DO_IMAGE;
-+ if (!repeat) {
-+ state->imageRect = CGRectMake (0, 0, extents.width, extents.height);
-+ state->action = DO_IMAGE;
-+ return;
- }
-
- /* Quartz seems to tile images at pixel-aligned regions only -- this
-@@ -1624,8 +1684,8 @@ _cairo_quartz_setup_source (cairo_quartz
- * epsilon), and if not, fall back to the CGPattern type.
- */
-
-- xform = CGAffineTransformConcat (CGContextGetCTM (surface->cgContext),
-- surface->sourceTransform);
-+ xform = CGAffineTransformConcat (CGContextGetCTM (context),
-+ state->transform);
-
- srcRect = CGRectMake (0, 0, extents.width, extents.height);
- srcRect = CGRectApplyAffineTransform (srcRect, xform);
-@@ -1646,101 +1706,218 @@ _cairo_quartz_setup_source (cairo_quartz
-
- srcRect = CGRectApplyAffineTransform (srcRect, xform);
-
-- surface->sourceImageRect = srcRect;
--
-- return DO_TILED_IMAGE;
-+ state->imageRect = srcRect;
-+ state->action = DO_TILED_IMAGE;
-+ return;
- }
-
- /* Fall through to generic SURFACE case */
- }
-
-- if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-- cairo_quartz_float_t patternAlpha = 1.0f;
-- CGColorSpaceRef patternSpace;
-- CGPatternRef pattern;
-- cairo_int_status_t status;
--
-- status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
-- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
-- return DO_NOTHING;
-- if (status)
-- return DO_UNSUPPORTED;
--
-- // 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);
--
-- 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;
-+ CGFloat patternAlpha = 1.0f;
-+ CGColorSpaceRef patternSpace;
-+ CGPatternRef pattern;
-+ cairo_int_status_t status;
-
-- return DO_PATTERN;
-+ status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
-+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
-+ state->action = DO_NOTHING;
-+ return;
-+ }
-+ if (status) {
-+ state->action = DO_UNSUPPORTED;
-+ return;
- }
-
-- return DO_UNSUPPORTED;
-+ patternSpace = CGColorSpaceCreatePattern (NULL);
-+ CGContextSetFillColorSpace (context, patternSpace);
-+ CGContextSetFillPattern (context, pattern, &patternAlpha);
-+ CGContextSetStrokeColorSpace (context, patternSpace);
-+ CGContextSetStrokePattern (context, 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 (context, CGSizeMake(0,0));
-+
-+ state->pattern = pattern;
-+ state->action = DO_PATTERN;
-+ return;
- }
-
-+/**
-+ * Call this before any operation that can modify the contents of a
-+ * cairo_quartz_surface_t.
-+ */
- static void
--_cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
-- const cairo_pattern_t *source)
-+_cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
- {
-- CGContextSetInterpolationQuality (surface->cgContext, surface->oldInterpolationQuality);
-+ if (surface->bitmapContextImage) {
-+ CGImageRelease (surface->bitmapContextImage);
-+ surface->bitmapContextImage = NULL;
-+ }
-+}
-
-- if (surface->sourceImage) {
-- CGImageRelease(surface->sourceImage);
-- surface->sourceImage = NULL;
-+/**
-+ * Sets up internal state to be used to draw the source mask, stored in
-+ * cairo_quartz_state_t. Guarantees to call CGContextSaveGState on
-+ * surface->cgContext.
-+ */
-+static cairo_quartz_drawing_state_t
-+_cairo_quartz_setup_state (cairo_quartz_surface_t *surface,
-+ const cairo_pattern_t *source,
-+ cairo_operator_t op,
-+ cairo_rectangle_int_t *extents)
-+{
-+ CGContextRef context = surface->cgContext;
-+ cairo_quartz_drawing_state_t state;
-+ cairo_status_t status;
-
-- cairo_surface_destroy(surface->sourceImageSurface);
-- surface->sourceImageSurface = NULL;
-+ state.context = context;
-+ state.image = NULL;
-+ state.imageSurface = NULL;
-+ state.layer = NULL;
-+ state.shading = NULL;
-+ state.pattern = NULL;
-+
-+ _cairo_quartz_surface_will_change (surface);
-+
-+ // 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(context);
-+
-+ CGContextSetInterpolationQuality (context, _cairo_quartz_filter_to_quartz (source->filter));
-+
-+ status = _cairo_quartz_surface_set_cairo_operator (surface, op);
-+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
-+ state.action = DO_NOTHING;
-+ return state;
-+ }
-+ if (status) {
-+ state.action = DO_UNSUPPORTED;
-+ return state;
- }
-
-- if (surface->sourceShading) {
-- CGShadingRelease(surface->sourceShading);
-- surface->sourceShading = NULL;
-+ if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
-+ cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-+
-+ CGContextSetRGBStrokeColor (context,
-+ solid->color.red,
-+ solid->color.green,
-+ solid->color.blue,
-+ solid->color.alpha);
-+ CGContextSetRGBFillColor (context,
-+ solid->color.red,
-+ solid->color.green,
-+ solid->color.blue,
-+ solid->color.alpha);
-+
-+ state.action = DO_SOLID;
-+ return state;
-+ }
-+
-+ if (source->type == CAIRO_PATTERN_TYPE_LINEAR) {
-+ const cairo_linear_pattern_t *lpat = (const cairo_linear_pattern_t *)source;
-+ _cairo_quartz_setup_linear_source (surface, lpat, extents, &state);
-+ return state;
-+ }
-+
-+ if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
-+ const cairo_radial_pattern_t *rpat = (const cairo_radial_pattern_t *)source;
-+ _cairo_quartz_setup_radial_source (surface, rpat, extents, &state);
-+ return state;
- }
-
-- if (surface->sourcePattern) {
-- CGPatternRelease(surface->sourcePattern);
-- // To tear down the pattern and colorspace
-- CGContextRestoreGState(surface->cgContext);
-+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
-+ if (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque (source, NULL) &&
-+ CGContextGetAlphaPtr &&
-+ CGContextGetAlphaPtr (surface->cgContext) == 1.0) {
-+ // Quartz won't touch pixels outside the bounds of the
-+ // source surface, so we can just go ahead and use Copy here
-+ // to accelerate things.
-+ // Quartz won't necessarily be able to do this optimization internally;
-+ // for CGLayer surfaces, we can know all the pixels are opaque
-+ // (because it's CONTENT_COLOR), but Quartz won't know.
-+ CGContextSetCompositeOperation (context, kPrivateCGCompositeCopy);
-+ }
-
-- surface->sourcePattern = NULL;
-+ const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source;
-+ _cairo_quartz_setup_surface_source (surface, spat, extents, &state);
-+ return state;
- }
--}
-
-+ state.action = DO_UNSUPPORTED;
-+ return state;
-+}
-
-+/**
-+ * 1) Tears down internal state used to draw the source
-+ * 2) Does CGContextRestoreGState(state->context)
-+ */
- static void
--_cairo_quartz_draw_image (cairo_quartz_surface_t *surface, cairo_operator_t op, cairo_quartz_action_t action)
-+_cairo_quartz_teardown_state (cairo_quartz_drawing_state_t *state)
- {
-- assert (surface && surface->sourceImage && (action == DO_IMAGE || action == DO_TILED_IMAGE));
-+ if (state->image) {
-+ CGImageRelease(state->image);
-+ }
-
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
-- CGContextScaleCTM (surface->cgContext, 1, -1);
--
-- if (action == DO_IMAGE) {
-- CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
-- if (!_cairo_operator_bounded_by_source(op)) {
-- CGContextBeginPath (surface->cgContext);
-- CGContextAddRect (surface->cgContext, surface->sourceImageRect);
-- CGContextAddRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
-- CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 0);
-- CGContextEOFillPath (surface->cgContext);
-+ if (state->imageSurface) {
-+ cairo_surface_destroy(state->imageSurface);
-+ }
-+
-+ if (state->shading) {
-+ CGShadingRelease(state->shading);
-+ }
-+
-+ if (state->pattern) {
-+ CGPatternRelease(state->pattern);
-+ }
-+
-+ CGContextRestoreGState(state->context);
-+}
-+
-+
-+static void
-+_cairo_quartz_draw_image (cairo_quartz_drawing_state_t *state, cairo_operator_t op)
-+{
-+ assert (state &&
-+ ((state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE)) ||
-+ (state->layer && state->action == DO_LAYER)));
-+
-+ CGContextConcatCTM (state->context, state->transform);
-+ CGContextTranslateCTM (state->context, 0, state->imageRect.size.height);
-+ CGContextScaleCTM (state->context, 1, -1);
-+
-+ if (state->action == DO_TILED_IMAGE) {
-+ CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
-+ /* no need to worry about unbounded operators, since tiled images
-+ fill the entire clip region */
-+ } else {
-+ if (state->action == DO_LAYER) {
-+ /* Note that according to Apple docs it's completely legal
-+ * to draw a CGLayer to any CGContext, even one it wasn't
-+ * created for.
-+ */
-+ CGContextSetInterpolationQuality (state->context, kCGInterpolationNone);
-+ CGContextDrawLayerAtPoint (state->context, state->imageRect.origin,
-+ state->layer);
-+ } else {
-+ CGContextDrawImage (state->context, state->imageRect, state->image);
-+ }
-+
-+ /* disable this EXTEND_NONE correctness code because we use this path
-+ * for both EXTEND_NONE and EXTEND_PAD */
-+ if (0 && !_cairo_operator_bounded_by_source (op)) {
-+ CGContextBeginPath (state->context);
-+ CGContextAddRect (state->context, state->imageRect);
-+ CGContextAddRect (state->context, CGContextGetClipBoundingBox (state->context));
-+ CGContextSetRGBFillColor (state->context, 0, 0, 0, 0);
-+ CGContextEOFillPath (state->context);
- }
-- } else
-- CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
-+ }
- }
-
-
-@@ -1762,6 +1939,7 @@ _cairo_quartz_get_image (cairo_quartz_su
- }
-
- if (surface->imageSurfaceEquiv) {
-+ CGContextFlush(surface->cgContext);
- *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv);
- return CAIRO_STATUS_SUCCESS;
- }
-@@ -1773,6 +1951,7 @@ _cairo_quartz_get_image (cairo_quartz_su
- CGColorSpaceRef colorspace;
- unsigned int color_comps;
-
-+ CGContextFlush(surface->cgContext);
- imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext);
-
- #ifdef USE_10_3_WORKAROUNDS
-@@ -1860,53 +2039,79 @@ _cairo_quartz_surface_finish (void *abst
-
- surface->cgContext = NULL;
-
-+ if (surface->bitmapContextImage) {
-+ CGImageRelease (surface->bitmapContextImage);
-+ surface->bitmapContextImage = NULL;
-+ }
-+
- if (surface->imageSurfaceEquiv) {
-+ if (surface->ownsData)
-+ _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
- cairo_surface_destroy (surface->imageSurfaceEquiv);
- surface->imageSurfaceEquiv = NULL;
-+ } else if (surface->imageData && surface->ownsData) {
-+ free (surface->imageData);
- }
-
-- if (surface->imageData) {
-- free (surface->imageData);
-- surface->imageData = NULL;
-+ surface->imageData = NULL;
-+
-+ if (surface->cgLayer) {
-+ CGLayerRelease (surface->cgLayer);
- }
-
- return CAIRO_STATUS_SUCCESS;
- }
-
- static cairo_status_t
--_cairo_quartz_surface_acquire_source_image (void *abstract_surface,
-- cairo_image_surface_t **image_out,
-- void **image_extra)
-+_cairo_quartz_surface_acquire_image (void *abstract_surface,
-+ cairo_image_surface_t **image_out,
-+ void **image_extra)
- {
- cairo_int_status_t status;
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
-
-- //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface));
--
-- status = _cairo_quartz_get_image (surface, image_out);
-- if (status)
-- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
--
- *image_extra = NULL;
-
-- return CAIRO_STATUS_SUCCESS;
--}
-+ /* ND((stderr, "%p _cairo_quartz_surface_acquire_image\n", surface)); */
-
--static cairo_surface_t *
--_cairo_quartz_surface_snapshot (void *abstract_surface)
--{
-- cairo_int_status_t status;
-- cairo_quartz_surface_t *surface = abstract_surface;
-- cairo_image_surface_t *image;
-+ status = _cairo_quartz_get_image (surface, image_out);
-
-- if (surface->imageSurfaceEquiv)
-- return NULL;
-+ if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->cgLayer) {
-+ /* copy the layer into a Quartz bitmap context so we can get the data */
-+ cairo_surface_t *tmp =
-+ cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32,
-+ surface->extents.width,
-+ surface->extents.height);
-+ cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) tmp;
-+
-+ /* if surface creation failed, we won't have a Quartz surface here */
-+ if (cairo_surface_get_type (tmp) == CAIRO_SURFACE_TYPE_QUARTZ &&
-+ tmp_surface->imageSurfaceEquiv) {
-+ CGContextSaveGState (tmp_surface->cgContext);
-+ CGContextTranslateCTM (tmp_surface->cgContext, 0, surface->extents.height);
-+ CGContextScaleCTM (tmp_surface->cgContext, 1, -1);
-+ /* Note that according to Apple docs it's completely legal
-+ * to draw a CGLayer to any CGContext, even one it wasn't
-+ * created for.
-+ */
-+ CGContextDrawLayerAtPoint (tmp_surface->cgContext,
-+ CGPointMake (0.0, 0.0),
-+ surface->cgLayer);
-+ CGContextRestoreGState (tmp_surface->cgContext);
-+
-+ *image_out = (cairo_image_surface_t*)
-+ cairo_surface_reference(tmp_surface->imageSurfaceEquiv);
-+ *image_extra = tmp;
-+ status = CAIRO_STATUS_SUCCESS;
-+ } else {
-+ cairo_surface_destroy (tmp);
-+ }
-+ }
-
-- status = _cairo_quartz_get_image (surface, &image);
-- if (unlikely (status))
-- return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
-+ if (status)
-+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-- return &image->base;
-+ return CAIRO_STATUS_SUCCESS;
- }
-
- static void
-@@ -1915,6 +2120,10 @@ _cairo_quartz_surface_release_source_ima
- void *image_extra)
- {
- cairo_surface_destroy ((cairo_surface_t *) image);
-+
-+ if (image_extra) {
-+ cairo_surface_destroy ((cairo_surface_t *) image_extra);
-+ }
- }
-
-
-@@ -1926,18 +2135,16 @@ _cairo_quartz_surface_acquire_dest_image
- void **image_extra)
- {
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
-- cairo_int_status_t status;
-
- ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface));
-
-- status = _cairo_quartz_get_image (surface, image_out);
-- if (status)
-- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
--
- *image_rect = surface->extents;
- *image_extra = NULL;
-
-- return CAIRO_STATUS_SUCCESS;
-+ _cairo_quartz_surface_will_change (surface);
-+
-+ return _cairo_quartz_surface_acquire_image (abstract_surface,
-+ image_out, image_extra);
- }
-
- static void
-@@ -1947,11 +2154,31 @@ _cairo_quartz_surface_release_dest_image
- cairo_rectangle_int_t *image_rect,
- void *image_extra)
- {
-- //cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
--
-- //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface));
-+ /* ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); */
-
- cairo_surface_destroy ((cairo_surface_t *) image);
-+
-+ if (image_extra) {
-+ /* we need to write the data from the temp surface back to the layer */
-+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
-+ cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) image_extra;
-+ CGImageRef img;
-+ cairo_status_t status = _cairo_surface_to_cgimage (&tmp_surface->base, &img);
-+ if (status) {
-+ cairo_surface_destroy (&tmp_surface->base);
-+ return;
-+ }
-+
-+ CGContextSaveGState (surface->cgContext);
-+ CGContextTranslateCTM (surface->cgContext, 0, surface->extents.height);
-+ CGContextScaleCTM (surface->cgContext, 1, -1);
-+ CGContextDrawImage (surface->cgContext,
-+ CGRectMake (0.0, 0.0, surface->extents.width, surface->extents.height),
-+ img);
-+ CGContextRestoreGState (surface->cgContext);
-+
-+ cairo_surface_destroy (&tmp_surface->base);
-+ }
- }
-
- static cairo_surface_t *
-@@ -1960,10 +2187,13 @@ _cairo_quartz_surface_create_similar (vo
- int width,
- int height)
- {
-- /*cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;*/
--
-+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
- cairo_format_t format;
-
-+ if (surface->cgLayer)
-+ return cairo_quartz_surface_create_cg_layer (abstract_surface, content,
-+ width, height);
-+
- if (content == CAIRO_CONTENT_COLOR_ALPHA)
- format = CAIRO_FORMAT_ARGB32;
- else if (content == CAIRO_CONTENT_COLOR)
-@@ -2027,7 +2257,7 @@ _cairo_quartz_surface_clone_similar (voi
- }
- }
-
-- status = _cairo_surface_to_cgimage ((cairo_surface_t*) abstract_surface, src, &quartz_image);
-+ status = _cairo_surface_to_cgimage (src, &quartz_image);
- if (status)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
-@@ -2087,7 +2317,7 @@ _cairo_quartz_surface_paint_cg (void *ab
- {
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
- cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-- cairo_quartz_action_t action;
-+ cairo_quartz_drawing_state_t state;
-
- ND((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type));
-
-@@ -2098,31 +2328,24 @@ _cairo_quartz_surface_paint_cg (void *ab
- if (unlikely (rv))
- return rv;
-
-- rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-- if (unlikely (rv))
-- return rv == CAIRO_INT_STATUS_NOTHING_TO_DO ? CAIRO_STATUS_SUCCESS : rv;
-+ state = _cairo_quartz_setup_state (surface, source, op, NULL);
-
-- action = _cairo_quartz_setup_source (surface, source, NULL);
--
-- 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) {
-- CGContextSaveGState (surface->cgContext);
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextDrawShading (surface->cgContext, surface->sourceShading);
-- CGContextRestoreGState (surface->cgContext);
-- } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-- CGContextSaveGState (surface->cgContext);
-- _cairo_quartz_draw_image (surface, op, action);
-- CGContextRestoreGState (surface->cgContext);
-- } else if (action != DO_NOTHING) {
-+ if (state.action == DO_SOLID || state.action == DO_PATTERN) {
-+ CGContextFillRect (state.context, CGRectMake(surface->extents.x,
-+ surface->extents.y,
-+ surface->extents.width,
-+ surface->extents.height));
-+ } else if (state.action == DO_SHADING) {
-+ CGContextConcatCTM (state.context, state.transform);
-+ CGContextDrawShading (state.context, state.shading);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
-+ state.action == DO_LAYER) {
-+ _cairo_quartz_draw_image (&state, op);
-+ } else if (state.action != DO_NOTHING) {
- rv = CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
-- _cairo_quartz_teardown_source (surface, source);
-+ _cairo_quartz_teardown_state (&state);
-
- ND((stderr, "-- paint\n"));
- return rv;
-@@ -2186,7 +2409,7 @@ _cairo_quartz_surface_fill_cg (void *abs
- {
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
- cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-- cairo_quartz_action_t action;
-+ cairo_quartz_drawing_state_t state;
- CGPathRef path_for_unbounded = NULL;
-
- ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
-@@ -2198,14 +2421,6 @@ _cairo_quartz_surface_fill_cg (void *abs
- if (unlikely (rv))
- return rv;
-
-- rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-- if (unlikely (rv))
-- return rv == CAIRO_INT_STATUS_NOTHING_TO_DO ? CAIRO_STATUS_SUCCESS : rv;
--
-- CGContextSaveGState (surface->cgContext);
--
-- CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
--
- if (_cairo_quartz_source_needs_extents (source))
- {
- /* We don't need precise extents since these are only used to
-@@ -2213,46 +2428,47 @@ _cairo_quartz_surface_fill_cg (void *abs
- object. */
- cairo_rectangle_int_t path_extents;
- _cairo_path_fixed_approximate_fill_extents (path, &path_extents);
-- action = _cairo_quartz_setup_source (surface, source, &path_extents);
-+ state = _cairo_quartz_setup_state (surface, source, op, &path_extents);
- } else {
-- action = _cairo_quartz_setup_source (surface, source, NULL);
-+ state = _cairo_quartz_setup_state (surface, source, op, NULL);
- }
-
-- _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
-+ CGContextSetShouldAntialias (state.context, (antialias != CAIRO_ANTIALIAS_NONE));
-+
-+ _cairo_quartz_cairo_path_to_quartz_context (path, state.context);
-
- if (!_cairo_operator_bounded_by_mask(op) && CGContextCopyPathPtr)
-- path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
-+ path_for_unbounded = CGContextCopyPathPtr (state.context);
-
-- if (action == DO_SOLID || action == DO_PATTERN) {
-+ if (state.action == DO_SOLID || state.action == DO_PATTERN) {
- if (fill_rule == CAIRO_FILL_RULE_WINDING)
-- CGContextFillPath (surface->cgContext);
-+ CGContextFillPath (state.context);
- else
-- CGContextEOFillPath (surface->cgContext);
-- } else if (action == DO_SHADING) {
-+ CGContextEOFillPath (state.context);
-+ } else if (state.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);
-+ CGContextClip (state.context);
- else
-- CGContextEOClip (surface->cgContext);
-+ CGContextEOClip (state.context);
-
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextDrawShading (surface->cgContext, surface->sourceShading);
-- } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-+ CGContextConcatCTM (state.context, state.transform);
-+ CGContextDrawShading (state.context, state.shading);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
-+ state.action == DO_LAYER) {
- if (fill_rule == CAIRO_FILL_RULE_WINDING)
-- CGContextClip (surface->cgContext);
-+ CGContextClip (state.context);
- else
-- CGContextEOClip (surface->cgContext);
-+ CGContextEOClip (state.context);
-
-- _cairo_quartz_draw_image (surface, op, action);
-- } else if (action != DO_NOTHING) {
-+ _cairo_quartz_draw_image (&state, op);
-+ } else if (state.action != DO_NOTHING) {
- rv = CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
-- _cairo_quartz_teardown_source (surface, source);
--
-- CGContextRestoreGState (surface->cgContext);
-+ _cairo_quartz_teardown_state (&state);
-
- if (path_for_unbounded) {
- unbounded_op_data_t ub;
-@@ -2319,7 +2535,7 @@ _cairo_quartz_surface_stroke_cg (void *a
- {
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
- cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-- cairo_quartz_action_t action;
-+ cairo_quartz_drawing_state_t state;
- CGAffineTransform origCTM, strokeTransform;
- CGPathRef path_for_unbounded = NULL;
-
-@@ -2336,16 +2552,25 @@ _cairo_quartz_surface_stroke_cg (void *a
- if (unlikely (rv))
- return rv == CAIRO_INT_STATUS_NOTHING_TO_DO ? CAIRO_STATUS_SUCCESS : rv;
-
-+ if (_cairo_quartz_source_needs_extents (source))
-+ {
-+ cairo_rectangle_int_t path_extents;
-+ _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &path_extents);
-+ state = _cairo_quartz_setup_state (surface, source, op, &path_extents);
-+ } else {
-+ state = _cairo_quartz_setup_state (surface, source, op, NULL);
-+ }
-+
- // Turning antialiasing off used to cause misrendering with
- // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels).
- // That's been since fixed in at least 10.5, and in the latest 10.4 dot releases.
-- CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-- CGContextSetLineWidth (surface->cgContext, style->line_width);
-- CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
-- CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
-- CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
-+ CGContextSetShouldAntialias (state.context, (antialias != CAIRO_ANTIALIAS_NONE));
-+ CGContextSetLineWidth (state.context, style->line_width);
-+ CGContextSetLineCap (state.context, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
-+ CGContextSetLineJoin (state.context, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
-+ CGContextSetMiterLimit (state.context, style->miter_limit);
-
-- origCTM = CGContextGetCTM (surface->cgContext);
-+ origCTM = CGContextGetCTM (state.context);
-
- if (style->dash && style->num_dashes) {
- #define STATIC_DASH 32
-@@ -2368,72 +2593,62 @@ _cairo_quartz_surface_stroke_cg (void *a
- if (fdash != sdash)
- free (fdash);
- } else
-- CGContextSetLineDash (surface->cgContext, 0, NULL, 0);
-+ CGContextSetLineDash (state.context, 0, NULL, 0);
-
-- CGContextSaveGState (surface->cgContext);
-
-+ _cairo_quartz_cairo_path_to_quartz_context (path, state.context);
-
-- if (_cairo_quartz_source_needs_extents (source))
-- {
-- cairo_rectangle_int_t path_extents;
-- _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &path_extents);
-- action = _cairo_quartz_setup_source (surface, source, &path_extents);
-- } else {
-- action = _cairo_quartz_setup_source (surface, source, NULL);
-- }
--
-- _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
-+ _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
-+ CGContextConcatCTM (state.context, strokeTransform);
-
- if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
-- path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
--
-- _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
-- CGContextConcatCTM (surface->cgContext, strokeTransform);
-+ path_for_unbounded = CGContextCopyPathPtr (state.context);
-
-- if (action == DO_SOLID || action == DO_PATTERN) {
-- CGContextStrokePath (surface->cgContext);
-- } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-- CGContextReplacePathWithStrokedPath (surface->cgContext);
-- CGContextClip (surface->cgContext);
--
-- CGContextSetCTM (surface->cgContext, origCTM);
-- _cairo_quartz_draw_image (surface, op, action);
-- } else if (action == DO_SHADING) {
-- CGContextReplacePathWithStrokedPath (surface->cgContext);
-- CGContextClip (surface->cgContext);
--
-- CGContextSetCTM (surface->cgContext, origCTM);
--
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextDrawShading (surface->cgContext, surface->sourceShading);
-- } else if (action != DO_NOTHING) {
-+ if (state.action == DO_SOLID || state.action == DO_PATTERN) {
-+ CGContextStrokePath (state.context);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
-+ state.action == DO_LAYER) {
-+ CGContextReplacePathWithStrokedPath (state.context);
-+ CGContextClip (state.context);
-+
-+ CGContextSetCTM (state.context, origCTM);
-+ _cairo_quartz_draw_image (&state, op);
-+ } else if (state.action == DO_SHADING) {
-+ CGContextReplacePathWithStrokedPath (state.context);
-+ CGContextClip (state.context);
-+
-+ CGContextSetCTM (state.context, origCTM);
-+
-+ CGContextConcatCTM (state.context, state.transform);
-+ CGContextDrawShading (state.context, state.shading);
-+ } else if (state.action != DO_NOTHING) {
- rv = CAIRO_INT_STATUS_UNSUPPORTED;
-+ goto BAIL;
- }
-
-- _cairo_quartz_teardown_source (surface, source);
--
-- CGContextRestoreGState (surface->cgContext);
--
- if (path_for_unbounded) {
- unbounded_op_data_t ub;
- ub.op = UNBOUNDED_STROKE_FILL;
- ub.u.stroke_fill.fill_rule = CAIRO_FILL_RULE_WINDING;
-
-- CGContextBeginPath (surface->cgContext);
-- CGContextAddPath (surface->cgContext, path_for_unbounded);
-+ CGContextBeginPath (state.context);
-+ CGContextAddPath (state.context, path_for_unbounded);
- CGPathRelease (path_for_unbounded);
-
-- CGContextSaveGState (surface->cgContext);
-- CGContextConcatCTM (surface->cgContext, strokeTransform);
-- CGContextReplacePathWithStrokedPath (surface->cgContext);
-- CGContextRestoreGState (surface->cgContext);
-+ CGContextSaveGState (state.context);
-+ CGContextConcatCTM (state.context, strokeTransform);
-+ CGContextReplacePathWithStrokedPath (state.context);
-+ CGContextRestoreGState (state.context);
-
-- ub.u.stroke_fill.cgPath = CGContextCopyPathPtr (surface->cgContext);
-+ ub.u.stroke_fill.cgPath = CGContextCopyPathPtr (state.context);
-
- _cairo_quartz_fixup_unbounded_operation (surface, &ub, antialias);
- CGPathRelease (ub.u.stroke_fill.cgPath);
- }
-
-+ BAIL:
-+ _cairo_quartz_teardown_state (&state);
-+
- ND((stderr, "-- stroke\n"));
- return rv;
- }
-@@ -2490,18 +2705,22 @@ _cairo_quartz_surface_show_glyphs_cg (vo
- CGGlyph glyphs_static[STATIC_BUF_SIZE];
- CGSize cg_advances_static[STATIC_BUF_SIZE];
- CGGlyph *cg_glyphs = &glyphs_static[0];
-+ /* We'll use the cg_advances array for either advances or positions,
-+ depending which API we're using to actually draw. The types involved
-+ have the same size, so this is safe. */
- CGSize *cg_advances = &cg_advances_static[0];
-
- cairo_rectangle_int_t glyph_extents;
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
- cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-- cairo_quartz_action_t action;
-+ cairo_quartz_drawing_state_t state;
- cairo_quartz_float_t xprev, yprev;
- int i;
- CGFontRef cgfref = NULL;
-
- cairo_bool_t isClipping = FALSE;
- cairo_bool_t didForceFontSmoothing = FALSE;
-+ cairo_antialias_t effective_antialiasing;
-
- if (IS_EMPTY(surface))
- return CAIRO_STATUS_SUCCESS;
-@@ -2516,54 +2735,51 @@ _cairo_quartz_surface_show_glyphs_cg (vo
- if (unlikely (rv))
- return rv;
-
-- rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-- if (unlikely (rv))
-- return rv == CAIRO_INT_STATUS_NOTHING_TO_DO ? CAIRO_STATUS_SUCCESS : rv;
--
-- CGContextSaveGState (surface->cgContext);
--
- if (_cairo_quartz_source_needs_extents (source) &&
- !_cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs,
- &glyph_extents, NULL))
- {
-- action = _cairo_quartz_setup_source (surface, source, &glyph_extents);
-+ state = _cairo_quartz_setup_state (surface, source, op, &glyph_extents);
- } else {
-- action = _cairo_quartz_setup_source (surface, source, NULL);
-+ state = _cairo_quartz_setup_state (surface, source, op, NULL);
- }
-
-- if (action == DO_SOLID || action == DO_PATTERN) {
-- CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-- } else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) {
-- CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
-+ if (state.action == DO_SOLID || state.action == DO_PATTERN) {
-+ CGContextSetTextDrawingMode (state.context, kCGTextFill);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
-+ state.action == DO_SHADING || state.action == DO_LAYER) {
-+ CGContextSetTextDrawingMode (state.context, kCGTextClip);
- isClipping = TRUE;
- } else {
-- if (action != DO_NOTHING)
-+ if (state.action != DO_NOTHING)
- rv = CAIRO_INT_STATUS_UNSUPPORTED;
- goto BAIL;
- }
-
- /* this doesn't addref */
- cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font);
-- CGContextSetFont (surface->cgContext, cgfref);
-- CGContextSetFontSize (surface->cgContext, 1.0);
-+ CGContextSetFont (state.context, cgfref);
-+ CGContextSetFontSize (state.context, 1.0);
-+
-+ effective_antialiasing = scaled_font->options.antialias;
-
- switch (scaled_font->options.antialias) {
- case CAIRO_ANTIALIAS_SUBPIXEL:
-- CGContextSetShouldAntialias (surface->cgContext, TRUE);
-- CGContextSetShouldSmoothFonts (surface->cgContext, TRUE);
-+ CGContextSetShouldAntialias (state.context, TRUE);
-+ CGContextSetShouldSmoothFonts (state.context, TRUE);
- if (CGContextSetAllowsFontSmoothingPtr &&
-- !CGContextGetAllowsFontSmoothingPtr (surface->cgContext))
-+ !CGContextGetAllowsFontSmoothingPtr (state.context))
- {
- didForceFontSmoothing = TRUE;
-- CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE);
-+ CGContextSetAllowsFontSmoothingPtr (state.context, TRUE);
- }
- break;
- case CAIRO_ANTIALIAS_NONE:
-- CGContextSetShouldAntialias (surface->cgContext, FALSE);
-+ CGContextSetShouldAntialias (state.context, FALSE);
- break;
- case CAIRO_ANTIALIAS_GRAY:
-- CGContextSetShouldAntialias (surface->cgContext, TRUE);
-- CGContextSetShouldSmoothFonts (surface->cgContext, FALSE);
-+ CGContextSetShouldAntialias (state.context, TRUE);
-+ CGContextSetShouldSmoothFonts (state.context, FALSE);
- break;
- case CAIRO_ANTIALIAS_DEFAULT:
- /* Don't do anything */
-@@ -2584,57 +2800,84 @@ _cairo_quartz_surface_show_glyphs_cg (vo
- }
- }
-
-+ /* scale(1,-1) * scaled_font->scale */
- textTransform = CGAffineTransformMake (scaled_font->scale.xx,
- scaled_font->scale.yx,
- -scaled_font->scale.xy,
- -scaled_font->scale.yy,
- 0, 0);
-- _cairo_quartz_cairo_matrix_to_quartz (&scaled_font->scale_inverse, &invTextTransform);
-
-- CGContextSetTextMatrix (surface->cgContext, CGAffineTransformIdentity);
-+ /* scaled_font->scale_inverse * scale(1,-1) */
-+ invTextTransform = CGAffineTransformMake (scaled_font->scale_inverse.xx,
-+ -scaled_font->scale_inverse.yx,
-+ scaled_font->scale_inverse.xy,
-+ -scaled_font->scale_inverse.yy,
-+ 0.0, 0.0);
-
-- /* Convert our glyph positions to glyph advances. We need n-1 advances,
-- * since the advance at index 0 is applied after glyph 0. */
-- xprev = glyphs[0].x;
-- yprev = glyphs[0].y;
--
-- cg_glyphs[0] = glyphs[0].index;
--
-- for (i = 1; i < num_glyphs; i++) {
-- cairo_quartz_float_t xf = glyphs[i].x;
-- cairo_quartz_float_t yf = glyphs[i].y;
-- cg_glyphs[i] = glyphs[i].index;
-- cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
-- xprev = xf;
-- yprev = yf;
-- }
-+ CGContextSetTextMatrix (state.context, CGAffineTransformIdentity);
-
- /* Translate to the first glyph's position before drawing */
-- ctm = CGContextGetCTM (surface->cgContext);
-- CGContextTranslateCTM (surface->cgContext, glyphs[0].x, glyphs[0].y);
-- CGContextConcatCTM (surface->cgContext, textTransform);
--
-- CGContextShowGlyphsWithAdvances (surface->cgContext,
-- cg_glyphs,
-- cg_advances,
-- num_glyphs);
--
-- CGContextSetCTM (surface->cgContext, ctm);
-+ ctm = CGContextGetCTM (state.context);
-+ CGContextTranslateCTM (state.context, glyphs[0].x, glyphs[0].y);
-+ CGContextConcatCTM (state.context, textTransform);
-+
-+ if (CTFontDrawGlyphsPtr) {
-+ /* If CTFontDrawGlyphs is available (i.e. OS X 10.7 or later), we want to use
-+ * that in preference to CGContextShowGlyphsWithAdvances so that colored-bitmap
-+ * fonts like Apple Color Emoji will render properly.
-+ * For this, we need to convert our glyph positions to Core Graphics's CGPoint.
-+ * We borrow the cg_advances array, as CGPoint and CGSize are the same size. */
-+
-+ CGPoint *cg_positions = (CGPoint*) cg_advances;
-+ cairo_quartz_float_t origin_x = glyphs[0].x;
-+ cairo_quartz_float_t origin_y = glyphs[0].y;
-+
-+ for (i = 0; i < num_glyphs; i++) {
-+ CGPoint pt = CGPointMake (glyphs[i].x - origin_x, glyphs[i].y - origin_y);
-+ cg_positions[i] = CGPointApplyAffineTransform (pt, invTextTransform);
-+ cg_glyphs[i] = glyphs[i].index;
-+ }
-
-- if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-- _cairo_quartz_draw_image (surface, op, action);
-- } else if (action == DO_SHADING) {
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextDrawShading (surface->cgContext, surface->sourceShading);
-+ CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (scaled_font),
-+ cg_glyphs, cg_positions, num_glyphs, state.context);
-+ } else {
-+ /* Convert our glyph positions to glyph advances. We need n-1 advances,
-+ * since the advance at index 0 is applied after glyph 0. */
-+ xprev = glyphs[0].x;
-+ yprev = glyphs[0].y;
-+
-+ cg_glyphs[0] = glyphs[0].index;
-+
-+ for (i = 1; i < num_glyphs; i++) {
-+ cairo_quartz_float_t xf = glyphs[i].x;
-+ cairo_quartz_float_t yf = glyphs[i].y;
-+ cg_glyphs[i] = glyphs[i].index;
-+ cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
-+ xprev = xf;
-+ yprev = yf;
-+ }
-+
-+ CGContextShowGlyphsWithAdvances (state.context,
-+ cg_glyphs,
-+ cg_advances,
-+ num_glyphs);
-+ }
-+
-+ CGContextSetCTM (state.context, ctm);
-+
-+ if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
-+ state.action == DO_LAYER) {
-+ _cairo_quartz_draw_image (&state, op);
-+ } else if (state.action == DO_SHADING) {
-+ CGContextConcatCTM (state.context, state.transform);
-+ CGContextDrawShading (state.context, state.shading);
- }
-
- BAIL:
-- _cairo_quartz_teardown_source (surface, source);
--
- if (didForceFontSmoothing)
-- CGContextSetAllowsFontSmoothingPtr (surface->cgContext, FALSE);
-+ CGContextSetAllowsFontSmoothingPtr (state.context, FALSE);
-
-- CGContextRestoreGState (surface->cgContext);
-+ _cairo_quartz_teardown_state (&state);
-
- if (rv == CAIRO_STATUS_SUCCESS &&
- cgfref &&
-@@ -2645,10 +2888,17 @@ BAIL:
-
- ub.u.show_glyphs.isClipping = isClipping;
- ub.u.show_glyphs.cg_glyphs = cg_glyphs;
-- ub.u.show_glyphs.cg_advances = cg_advances;
-+ if (CTFontDrawGlyphsPtr) {
-+ /* we're using Core Text API: the cg_advances array was
-+ reused (above) for glyph positions */
-+ CGPoint *cg_positions = (CGPoint*) cg_advances;
-+ ub.u.show_glyphs.u.cg_positions = cg_positions;
-+ } else {
-+ ub.u.show_glyphs.u.cg_advances = cg_advances;
-+ }
- ub.u.show_glyphs.nglyphs = num_glyphs;
- ub.u.show_glyphs.textTransform = textTransform;
-- ub.u.show_glyphs.font = cgfref;
-+ ub.u.show_glyphs.scaled_font = scaled_font;
- ub.u.show_glyphs.origin = CGPointMake (glyphs[0].x, glyphs[0].y);
-
- _cairo_quartz_fixup_unbounded_operation (surface, &ub, scaled_font->options.antialias);
-@@ -2717,7 +2967,7 @@ _cairo_quartz_surface_mask_with_surface
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- CGAffineTransform ctm, mask_matrix;
-
-- status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
-+ status = _cairo_surface_to_cgimage (pat_surf, &img);
- if (status)
- return status;
- if (img == NULL) {
-@@ -2820,7 +3070,9 @@ _cairo_quartz_surface_mask_cg (void *abs
- if (unlikely (rv))
- return rv;
-
-- if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
-+ /* Using CGContextSetAlpha to implement mask alpha doesn't work for all operators. */
-+ if (mask->type == CAIRO_PATTERN_TYPE_SOLID &&
-+ op == CAIRO_OPERATOR_OVER) {
- /* This is easy; we just need to paint with the alpha. */
- cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
-
-@@ -2834,8 +3086,11 @@ _cairo_quartz_surface_mask_cg (void *abs
- /* If we have CGContextClipToMask, we can do more complex masks */
- if (CGContextClipToMaskPtr) {
- /* For these, we can skip creating a temporary surface, since we already have one */
-- if (mask->type == CAIRO_PATTERN_TYPE_SURFACE && mask->extend == CAIRO_EXTEND_NONE)
-+ /* For some reason this doesn't work reliably on OS X 10.5. See bug 721663. */
-+ if (_cairo_quartz_osx_version >= 0x1060 && mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
-+ mask->extend == CAIRO_EXTEND_NONE) {
- return _cairo_quartz_surface_mask_with_surface (surface, op, source, (cairo_surface_pattern_t *) mask, clip);
-+ }
-
- return _cairo_quartz_surface_mask_with_generic (surface, op, source, mask, clip);
- }
-@@ -2920,13 +3175,24 @@ _cairo_quartz_surface_clipper_intersect_
- return CAIRO_STATUS_SUCCESS;
- }
-
-+static cairo_status_t
-+_cairo_quartz_surface_mark_dirty_rectangle (void *abstract_surface,
-+ int x, int y,
-+ int width, int height)
-+{
-+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
-+ _cairo_quartz_surface_will_change (surface);
-+ return CAIRO_STATUS_SUCCESS;
-+}
-+
-+
- // XXXtodo implement show_page; need to figure out how to handle begin/end
-
- static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
- CAIRO_SURFACE_TYPE_QUARTZ,
- _cairo_quartz_surface_create_similar,
- _cairo_quartz_surface_finish,
-- _cairo_quartz_surface_acquire_source_image,
-+ _cairo_quartz_surface_acquire_image,
- _cairo_quartz_surface_release_source_image,
- _cairo_quartz_surface_acquire_dest_image,
- _cairo_quartz_surface_release_dest_image,
-@@ -2942,7 +3208,7 @@ static const struct _cairo_surface_backe
- NULL, /* old_show_glyphs */
- NULL, /* get_font_options */
- NULL, /* flush */
-- NULL, /* mark_dirty_rectangle */
-+ _cairo_quartz_surface_mark_dirty_rectangle,
- NULL, /* scaled_font_fini */
- NULL, /* scaled_glyph_fini */
-
-@@ -2952,7 +3218,7 @@ static const struct _cairo_surface_backe
- _cairo_quartz_surface_fill,
- _cairo_quartz_surface_show_glyphs,
-
-- _cairo_quartz_surface_snapshot,
-+ NULL, /* snapshot */
- NULL, /* is_similar */
- NULL /* fill_stroke */
- };
-@@ -3004,6 +3270,9 @@ _cairo_quartz_surface_create_internal (C
-
- surface->imageData = NULL;
- surface->imageSurfaceEquiv = NULL;
-+ surface->bitmapContextImage = NULL;
-+ surface->cgLayer = NULL;
-+ surface->ownsData = TRUE;
-
- return surface;
- }
-@@ -3056,6 +3325,81 @@ cairo_quartz_surface_create_for_cg_conte
- }
-
- /**
-+ * cairo_quartz_cglayer_surface_create_similar
-+ * @surface: The returned surface can be efficiently drawn into this
-+ * destination surface (if tiling is not used)."
-+ * @content: the content type of the surface
-+ * @width: width of the surface, in pixels
-+ * @height: height of the surface, in pixels
-+ *
-+ * Creates a Quartz surface backed by a CGLayer, if the given surface
-+ * is a Quartz surface; the CGLayer is created to match the surface's
-+ * Quartz context. Otherwise just calls cairo_surface_create_similar.
-+ * The returned surface can be efficiently blitted to the given surface,
-+ * but tiling and 'extend' modes other than NONE are not so efficient.
-+ *
-+ * Return value: the newly created surface.
-+ *
-+ * Since: 1.10
-+ **/
-+cairo_surface_t *
-+cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
-+ cairo_content_t content,
-+ unsigned int width,
-+ unsigned int height)
-+{
-+ cairo_quartz_surface_t *surf;
-+ CGLayerRef layer;
-+ CGContextRef ctx;
-+ CGContextRef cgContext;
-+
-+ cgContext = cairo_quartz_surface_get_cg_context (surface);
-+ if (!cgContext)
-+ return cairo_surface_create_similar (surface, content,
-+ width, height);
-+
-+
-+ if (!_cairo_quartz_verify_surface_size(width, height))
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
-+
-+ /* If we pass zero width or height into CGLayerCreateWithContext below,
-+ * it will fail.
-+ */
-+ if (width == 0 || height == 0) {
-+ return (cairo_surface_t*)
-+ _cairo_quartz_surface_create_internal (NULL, content,
-+ width, height);
-+ }
-+
-+ layer = CGLayerCreateWithContext (cgContext,
-+ CGSizeMake (width, height),
-+ NULL);
-+ if (!layer)
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-+
-+ ctx = CGLayerGetContext (layer);
-+ CGContextSetInterpolationQuality (ctx, kCGInterpolationNone);
-+ /* Flip it when we draw into it, so that when we finally composite it
-+ * to a flipped target, the directions match and Quartz will optimize
-+ * the composition properly
-+ */
-+ CGContextTranslateCTM (ctx, 0, height);
-+ CGContextScaleCTM (ctx, 1, -1);
-+
-+ CGContextRetain (ctx);
-+ surf = _cairo_quartz_surface_create_internal (ctx, content,
-+ width, height);
-+ if (surf->base.status) {
-+ CGLayerRelease (layer);
-+ // create_internal will have set an error
-+ return (cairo_surface_t*) surf;
-+ }
-+ surf->cgLayer = layer;
-+
-+ 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
-@@ -3075,13 +3419,93 @@ cairo_quartz_surface_create (cairo_forma
- unsigned int width,
- unsigned int height)
- {
-+ int stride;
-+ unsigned char *data;
-+
-+ if (!_cairo_quartz_verify_surface_size(width, height))
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
-+
-+ if (width == 0 || height == 0) {
-+ return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
-+ width, height);
-+ }
-+
-+ if (format == CAIRO_FORMAT_ARGB32 ||
-+ format == CAIRO_FORMAT_RGB24)
-+ {
-+ stride = width * 4;
-+ } else if (format == CAIRO_FORMAT_A8) {
-+ stride = width;
-+ } 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.
-+ */
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-+ } else {
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-+ }
-+
-+ /* The Apple docs say that for best performance, the stride and the data
-+ * pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
-+ * so we don't have to anything special on allocation.
-+ */
-+ stride = (stride + 15) & ~15;
-+
-+ data = _cairo_malloc_ab (height, stride);
-+ if (!data) {
-+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-+ }
-+
-+ /* zero the memory to match the image surface behaviour */
-+ memset (data, 0, height * stride);
-+
-+ cairo_quartz_surface_t *surf;
-+ surf = (cairo_quartz_surface_t *) cairo_quartz_surface_create_for_data
-+ (data, format, width, height, stride);
-+ if (surf->base.status) {
-+ free (data);
-+ return (cairo_surface_t *) surf;
-+ }
-+
-+ // We created this data, so we can delete it.
-+ surf->ownsData = TRUE;
-+
-+ return (cairo_surface_t *) surf;
-+}
-+
-+/**
-+ * cairo_quartz_surface_create_for_data
-+ * @data: a pointer to a buffer supplied by the application in which
-+ * to write contents. This pointer must be suitably aligned for any
-+ * kind of variable, (for example, a pointer returned by malloc).
-+ * @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.12
-+ **/
-+cairo_surface_t *
-+cairo_quartz_surface_create_for_data (unsigned char *data,
-+ cairo_format_t format,
-+ unsigned int width,
-+ unsigned int height,
-+ unsigned int stride)
-+{
- cairo_quartz_surface_t *surf;
- CGContextRef cgc;
- CGColorSpaceRef cgColorspace;
- CGBitmapInfo bitinfo;
-- void *imageData;
-- int stride;
-+ void *imageData = data;
- int bitsPerComponent;
-+ unsigned int i;
-
- // verify width and height of surface
- if (!_cairo_quartz_verify_surface_size(width, height))
-@@ -3102,10 +3526,8 @@ cairo_quartz_surface_create (cairo_forma
- else
- bitinfo |= kCGImageAlphaNoneSkipFirst;
- bitsPerComponent = 8;
-- stride = width * 4;
- } else if (format == CAIRO_FORMAT_A8) {
- cgColorspace = NULL;
-- stride = width;
- bitinfo = kCGImageAlphaOnly;
- bitsPerComponent = 8;
- } else if (format == CAIRO_FORMAT_A1) {
-@@ -3118,21 +3540,6 @@ cairo_quartz_surface_create (cairo_forma
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
- }
-
-- /* The Apple docs say that for best performance, the stride and the data
-- * pointer should be 16-byte aligned. malloc already aligns to 16-bytes,
-- * so we don't have to anything special on allocation.
-- */
-- stride = (stride + 15) & ~15;
--
-- imageData = _cairo_malloc_ab (height, stride);
-- if (!imageData) {
-- CGColorSpaceRelease (cgColorspace);
-- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-- }
--
-- /* zero the memory to match the image surface behaviour */
-- memset (imageData, 0, height * stride);
--
- cgc = CGBitmapContextCreate (imageData,
- width,
- height,
-@@ -3161,7 +3568,19 @@ cairo_quartz_surface_create (cairo_forma
- }
-
- surf->imageData = imageData;
-- surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
-+
-+ cairo_surface_t* tmpImageSurfaceEquiv =
-+ cairo_image_surface_create_for_data (imageData, format,
-+ width, height, stride);
-+
-+ if (cairo_surface_status (tmpImageSurfaceEquiv)) {
-+ // Tried & failed to create an imageSurfaceEquiv!
-+ cairo_surface_destroy (tmpImageSurfaceEquiv);
-+ surf->imageSurfaceEquiv = NULL;
-+ } else {
-+ surf->imageSurfaceEquiv = tmpImageSurfaceEquiv;
-+ surf->ownsData = FALSE;
-+ }
-
- return (cairo_surface_t *) surf;
- }
-@@ -3193,6 +3612,74 @@ _cairo_surface_is_quartz (const cairo_su
- return surface->backend == &cairo_quartz_surface_backend;
- }
-
-+CGContextRef
-+cairo_quartz_get_cg_context_with_clip (cairo_t *cr)
-+{
-+
-+ cairo_surface_t *surface = cr->gstate->target;
-+ cairo_clip_t *clip = &cr->gstate->clip;
-+ cairo_status_t status;
-+
-+ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface;
-+
-+ if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ)
-+ return NULL;
-+
-+ if (!clip->path) {
-+ if (clip->all_clipped) {
-+ /* Save the state before we set an empty clip rect so that
-+ * our previous clip will be restored */
-+
-+ /* _cairo_surface_clipper_set_clip doesn't deal with
-+ * clip->all_clipped because drawing is normally discarded earlier */
-+ CGRect empty = {{0,0}, {0,0}};
-+ CGContextClipToRect (quartz->cgContext, empty);
-+ CGContextSaveGState (quartz->cgContext);
-+
-+ return quartz->cgContext;
-+ }
-+
-+ /* an empty clip is represented by NULL */
-+ clip = NULL;
-+ }
-+
-+ status = _cairo_surface_clipper_set_clip (&quartz->clipper, clip);
-+
-+ /* Save the state after we set the clip so that it persists
-+ * after we restore */
-+ CGContextSaveGState (quartz->cgContext);
-+
-+ if (unlikely (status))
-+ return NULL;
-+
-+ return quartz->cgContext;
-+}
-+
-+void
-+cairo_quartz_finish_cg_context_with_clip (cairo_t *cr)
-+{
-+ cairo_surface_t *surface = cr->gstate->target;
-+
-+ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface;
-+
-+ if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ)
-+ return;
-+
-+ CGContextRestoreGState (quartz->cgContext);
-+}
-+
-+cairo_surface_t *
-+cairo_quartz_surface_get_image (cairo_surface_t *surface)
-+{
-+ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *)surface;
-+ cairo_image_surface_t *image;
-+
-+ if (_cairo_quartz_get_image(quartz, &image))
-+ return NULL;
-+
-+ return (cairo_surface_t *)image;
-+}
-+
- /* Debug stuff */
-
- #ifdef QUARTZ_DEBUG
---- a/src/cairo-quartz.h 2012-11-13 18:20:00.000000000 -0800
-+++ b/src/cairo-quartz.h 2012-11-13 18:06:56.000000000 -0800
-@@ -50,6 +50,19 @@ cairo_quartz_surface_create (cairo_forma
- unsigned int height);
-
- cairo_public cairo_surface_t *
-+cairo_quartz_surface_create_for_data (unsigned char *data,
-+ cairo_format_t format,
-+ unsigned int width,
-+ unsigned int height,
-+ unsigned int stride);
-+
-+cairo_public cairo_surface_t *
-+cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
-+ cairo_content_t content,
-+ unsigned int width,
-+ unsigned int height);
-+
-+cairo_public cairo_surface_t *
- cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
- unsigned int width,
- unsigned int height);
-@@ -57,6 +70,15 @@ cairo_quartz_surface_create_for_cg_conte
- cairo_public CGContextRef
- cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
-
-+cairo_public CGContextRef
-+cairo_quartz_get_cg_context_with_clip (cairo_t *cr);
-+
-+cairo_public void
-+cairo_quartz_finish_cg_context_with_clip (cairo_t *cr);
-+
-+cairo_public cairo_surface_t *
-+cairo_quartz_surface_get_image (cairo_surface_t *surface);
-+
- #if CAIRO_HAS_QUARTZ_FONT
-
- /*
-@@ -66,8 +88,10 @@ cairo_quartz_surface_get_cg_context (cai
- cairo_public cairo_font_face_t *
- cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
-
-+#ifndef __LP64__
- cairo_public cairo_font_face_t *
- cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id);
-+#endif
-
- #endif /* CAIRO_HAS_QUARTZ_FONT */
\ No newline at end of file
+++ /dev/null
-diff --git a/configure.ac b/configure.ac
-index 42c04ef..1260b8a 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -185,7 +185,7 @@ changequote(,)dnl
- if test "x$GCC" = "xyes"; then
- case " $CFLAGS " in
- *[\ \ ]-Wall[\ \ ]*) ;;
-- *) CFLAGS="$CFLAGS -Wall" ;;
-+ *) CFLAGS="$CFLAGS -Wall -ObjC" ;;
- esac
- fi
- changequote([,])dnl
-diff --git a/pango/pangocairo-coretext.h b/pango/pangocairo-coretext.h
-index 31faf9b..f562587 100644
---- a/pango/pangocairo-coretext.h
-+++ b/pango/pangocairo-coretext.h
-@@ -43,6 +43,19 @@ struct _PangoCairoCoreTextFontMap
- gdouble dpi;
- };
-
-+struct _PangoCairoCoreTextFont
-+{
-+ PangoCoreTextFont font;
-+ PangoCairoFontPrivate cf_priv;
-+
-+ int abs_size;
-+};
-+
-+struct _PangoCairoCoreTextFontClass
-+{
-+ PangoCoreTextFontClass parent_class;
-+};
-+
- GType pango_cairo_core_text_font_map_get_type (void) G_GNUC_CONST;
-
- PangoCoreTextFont *
-diff --git a/pango/pangocairo-coretextfont.c b/pango/pangocairo-coretextfont.c
-index 0f2a9ef..463b6e2 100644
---- a/pango/pangocairo-coretextfont.c
-+++ b/pango/pangocairo-coretextfont.c
-@@ -23,6 +23,7 @@
-
- #include "config.h"
-
-+#import <AppKit/AppKit.h>
- #include <Carbon/Carbon.h>
-
- #include "pango-impl-utils.h"
-@@ -32,21 +33,6 @@
- #include "pangocairo-coretext.h"
- #include "pangocairo-coretextfont.h"
-
--struct _PangoCairoCoreTextFont
--{
-- PangoCoreTextFont font;
-- PangoCairoFontPrivate cf_priv;
--
-- int abs_size;
--};
--
--struct _PangoCairoCoreTextFontClass
--{
-- PangoCoreTextFontClass parent_class;
--};
--
--
--
- static cairo_font_face_t *pango_cairo_core_text_font_create_font_face (PangoCairoFont *font);
- static PangoFontMetrics *pango_cairo_core_text_font_create_base_metrics_for_context (PangoCairoFont *font,
- PangoContext *context);
-@@ -204,6 +190,75 @@ pango_cairo_core_text_font_init (PangoCairoCoreTextFont *cafont G_GNUC_UNUSED)
- {
- }
-
-+static gchar *
-+gchar_from_cf_string (CFStringRef str)
-+{
-+ CFIndex len;
-+ gchar *buffer;
-+
-+ /* GetLength returns the number of UTF-16 pairs, so this number
-+ * times 2 should definitely give us enough space for UTF8.
-+ * We add one for the terminating zero.
-+ */
-+ len = CFStringGetLength (str) * 2 + 1;
-+ buffer = g_new0 (char, len);
-+ CFStringGetCString (str, buffer, len, kCFStringEncodingUTF8);
-+
-+ return buffer;
-+}
-+
-+static gchar *
-+ct_font_descriptor_get_family_name (CTFontDescriptorRef desc,
-+ gboolean may_fail)
-+{
-+ CFStringRef cf_str;
-+ char *buffer;
-+
-+ cf_str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
-+ if (!cf_str)
-+ {
-+ int i;
-+
-+ /* No font family name is set, try to retrieve font name and deduce
-+ * the family name from that instead.
-+ */
-+ cf_str = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
-+ if (!cf_str)
-+ {
-+ if (may_fail)
-+ return NULL;
-+
-+ /* This font is likely broken, return a default family name ... */
-+ return g_strdup ("Sans");
-+ }
-+
-+ buffer = gchar_from_cf_string (cf_str);
-+ CFRelease (cf_str);
-+
-+ for (i = 0; i < strlen (buffer); i++)
-+ if (buffer[i] == '-')
-+ break;
-+
-+ if (i < strlen (buffer))
-+ {
-+ char *ret;
-+
-+ ret = g_strndup (buffer, i);
-+ g_free (buffer);
-+
-+ return ret;
-+ }
-+ else
-+ return buffer;
-+ }
-+ /* else */
-+
-+ buffer = gchar_from_cf_string (cf_str);
-+ CFRelease (cf_str);
-+
-+ return buffer;
-+}
-+
- PangoCoreTextFont *
- _pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap,
- PangoCoreTextFontKey *key)
-diff --git a/pango/pangocairo-coretextfontmap.c b/pango/pangocairo-coretextfontmap.c
-index ba5dcec..6cb3809 100644
---- a/pango/pangocairo-coretextfontmap.c
-+++ b/pango/pangocairo-coretextfontmap.c
-@@ -26,6 +26,9 @@
- #include "pangocairo.h"
- #include "pangocairo-private.h"
- #include "pangocairo-coretext.h"
-+#include "pangocairo-coretextfont.h"
-+
-+#import <AppKit/Appkit.h>
-
- typedef struct _PangoCairoCoreTextFontMapClass PangoCairoCoreTextFontMapClass;
-
-@@ -161,6 +164,106 @@ pango_cairo_core_text_font_map_context_key_equal (PangoCoreTextFontMap *fontmap
- return cairo_font_options_equal (key_a, key_b);
- }
-
-+static int
-+get_scaled_size (PangoCoreTextFontMap *fontmap,
-+ PangoContext *context,
-+ const PangoFontDescription *desc)
-+{
-+ double size = pango_font_description_get_size (desc);
-+
-+ if (!pango_font_description_get_size_is_absolute (desc))
-+ {
-+ double dpi = pango_cairo_core_text_font_map_get_resolution_core_text (fontmap, context);
-+ size = size * dpi / 72.;
-+ }
-+
-+ return .5 + pango_matrix_get_font_scale_factor (pango_context_get_matrix (context)) * size;
-+}
-+
-+static PangoCoreTextFont *
-+pango_cairo_core_text_font_map_load_font (PangoCoreTextFontMap *fontmap,
-+ PangoContext *context,
-+ const PangoFontDescription *description)
-+{
-+ char *descname = pango_font_description_get_family (description);
-+
-+ if (strcmp (descname, "-apple-system-font") == 0)
-+ {
-+ PangoCoreTextFont *cfont;
-+ NSFont *sysfont;
-+ CTFontDescriptorRef ctfontdescriptor;
-+ cairo_matrix_t font_matrix;
-+ PangoCoreTextFontsetKey fontset_key;
-+ PangoCoreTextFontKey key;
-+ PangoLanguage *language;
-+ PangoFontDescription *tmp_desc;
-+ gboolean synthetic_italic = FALSE;
-+ double abs_size = get_scaled_size (fontmap, context, description);
-+ double size = pango_units_to_double (abs_size) / pango_matrix_get_font_scale_factor (pango_context_get_matrix (context));
-+
-+ sysfont = [NSFont systemFontOfSize: size];
-+ ctfontdescriptor = (CTFontDescriptorRef)[sysfont fontDescriptor];
-+
-+ PangoCairoCoreTextFont *cafont = g_object_new (PANGO_TYPE_CAIRO_CORE_TEXT_FONT, NULL);
-+ cfont = PANGO_CORE_TEXT_FONT (cafont);
-+ cafont->abs_size = abs_size;
-+ _pango_core_text_font_set_ctfont (cfont, CFRetain (sysfont));
-+
-+ tmp_desc = pango_font_description_copy_static (description);
-+
-+ _pango_core_text_fontset_key_init (&fontset_key,
-+ fontmap,
-+ context,
-+ tmp_desc,
-+ pango_context_get_language (context));
-+ _pango_core_text_font_key_init (&key,
-+ fontmap,
-+ &fontset_key,
-+ ctfontdescriptor,
-+ synthetic_italic);
-+
-+ if (pango_core_text_font_key_get_synthetic_italic (&key))
-+ synthetic_italic = TRUE;
-+
-+ if (synthetic_italic)
-+ {
-+ cairo_matrix_init (&font_matrix,
-+ 1, 0,
-+ -0.25, 1,
-+ 0, 0);
-+ }
-+ else
-+ {
-+ cairo_matrix_init_identity (&font_matrix);
-+ }
-+
-+ cairo_matrix_scale (&font_matrix, size, size);
-+
-+ _pango_cairo_font_private_initialize (&cafont->cf_priv,
-+ (PangoCairoFont *)cafont,
-+ pango_core_text_font_key_get_gravity (&key),
-+ pango_core_text_font_key_get_context_key (&key),
-+ pango_core_text_font_key_get_matrix (&key),
-+ &font_matrix);
-+
-+ PangoCoreTextFont *tmp_font = _pango_core_text_font_map_lookup_font (fontmap, &key);
-+ if (tmp_font)
-+ {
-+ g_object_ref (tmp_font);
-+ return tmp_font;
-+ }
-+ else
-+ {
-+ g_object_ref (cfont);
-+ _pango_core_text_font_map_add (PANGO_CORE_TEXT_FONT_MAP (fontmap), &key, cfont);
-+
-+ return cfont;
-+ }
-+ }
-+
-+ return PANGO_FONT_MAP_CLASS (pango_cairo_core_text_font_map_parent_class)->load_font (fontmap, context, description);
-+}
-+
- static void
- pango_cairo_core_text_font_map_class_init (PangoCairoCoreTextFontMapClass *class)
- {
-@@ -170,6 +273,7 @@ pango_cairo_core_text_font_map_class_init (PangoCairoCoreTextFontMapClass *class
-
- object_class->finalize = pango_cairo_core_text_font_map_finalize;
-
-+ fontmap_class->load_font = pango_cairo_core_text_font_map_load_font;
- fontmap_class->get_serial = pango_cairo_core_text_font_map_get_serial;
- fontmap_class->changed = pango_cairo_core_text_font_map_changed;
-
-diff --git a/pango/pangocoretext-fontmap.c b/pango/pangocoretext-fontmap.c
-index bcbb173..4234bf1 100644
---- a/pango/pangocoretext-fontmap.c
-+++ b/pango/pangocoretext-fontmap.c
-@@ -28,6 +28,7 @@
- #include "pango-impl-utils.h"
- #include "modules.h"
-
-+#import <AppKit/Appkit.h>
- #include <Carbon/Carbon.h>
-
- typedef struct _FontHashKey FontHashKey;
-@@ -826,28 +827,12 @@ get_scaled_size (PangoCoreTextFontMap *fontmap,
- return .5 + pango_matrix_get_font_scale_factor (pango_context_get_matrix (context)) * size;
- }
-
--
--/*
-- * PangoCoreTextFontsetKey
-- */
--struct _PangoCoreTextFontsetKey
--{
-- PangoCoreTextFontMap *fontmap;
-- PangoLanguage *language;
-- PangoFontDescription *desc;
-- PangoMatrix matrix;
-- int pixelsize;
-- double resolution;
-- PangoGravity gravity;
-- gpointer context_key;
--};
--
--static void
--pango_core_text_fontset_key_init (PangoCoreTextFontsetKey *key,
-- PangoCoreTextFontMap *fontmap,
-- PangoContext *context,
-- const PangoFontDescription *desc,
-- PangoLanguage *language)
-+void
-+_pango_core_text_fontset_key_init (PangoCoreTextFontsetKey *key,
-+ PangoCoreTextFontMap *fontmap,
-+ PangoContext *context,
-+ const PangoFontDescription *desc,
-+ PangoLanguage *language)
- {
- if (!language && context)
- language = pango_context_get_language (context);
-@@ -960,27 +945,12 @@ pango_core_text_fontset_key_get_context_key (const PangoCoreTextFontsetKey *key)
- return key->context_key;
- }
-
--/*
-- * PangoCoreTextFontKey
-- */
--struct _PangoCoreTextFontKey
--{
-- PangoCoreTextFontMap *fontmap;
-- CTFontDescriptorRef ctfontdescriptor;
-- PangoMatrix matrix;
-- PangoGravity gravity;
-- int pixelsize;
-- double resolution;
-- gboolean synthetic_italic;
-- gpointer context_key;
--};
--
--static void
--pango_core_text_font_key_init (PangoCoreTextFontKey *key,
-- PangoCoreTextFontMap *ctfontmap,
-- PangoCoreTextFontsetKey *fontset_key,
-- CTFontDescriptorRef ctdescriptor,
-- gboolean synthetic_italic)
-+void
-+_pango_core_text_font_key_init (PangoCoreTextFontKey *key,
-+ PangoCoreTextFontMap *ctfontmap,
-+ PangoCoreTextFontsetKey *fontset_key,
-+ CTFontDescriptorRef ctdescriptor,
-+ gboolean synthetic_italic)
- {
- key->fontmap = ctfontmap;
- key->ctfontdescriptor = ctdescriptor;
-@@ -1104,14 +1074,24 @@ pango_core_text_font_key_get_ctfontdescriptor (const PangoCoreTextFontKey *key)
- return key->ctfontdescriptor;
- }
-
-+PangoCoreTextFont *
-+_pango_core_text_font_map_lookup_font (PangoCoreTextFontMap *fontmap,
-+ PangoCoreTextFontKey *key)
-+{
-+ return g_hash_table_lookup (fontmap->font_hash, key);
-+}
-
--
--static void
--pango_core_text_font_map_add (PangoCoreTextFontMap *ctfontmap,
-- PangoCoreTextFontKey *key,
-- PangoCoreTextFont *ctfont)
-+void
-+_pango_core_text_font_map_add (PangoCoreTextFontMap *ctfontmap,
-+ PangoCoreTextFontKey *key,
-+ PangoCoreTextFont *ctfont)
- {
- PangoCoreTextFontKey *key_copy;
-+ PangoCoreTextFont *tmp;
-+
-+ tmp = g_hash_table_lookup (ctfontmap->font_hash, key);
-+ if (tmp)
-+ return;
-
- _pango_core_text_font_set_font_map (ctfont, ctfontmap);
-
-@@ -1130,8 +1110,8 @@ pango_core_text_font_map_new_font (PangoCoreTextFontMap *fontmap,
- PangoCoreTextFont *font;
- PangoCoreTextFontKey key;
-
-- pango_core_text_font_key_init (&key, fontmap, fontset_key, ctfontdescriptor,
-- synthetic_italic);
-+ _pango_core_text_font_key_init (&key, fontmap, fontset_key, ctfontdescriptor,
-+ synthetic_italic);
-
- font = g_hash_table_lookup (fontmap->font_hash, &key);
- if (font)
-@@ -1144,7 +1124,7 @@ pango_core_text_font_map_new_font (PangoCoreTextFontMap *fontmap,
- if (!font)
- return NULL;
-
-- pango_core_text_font_map_add (fontmap, &key, font);
-+ _pango_core_text_font_map_add (fontmap, &key, font);
-
- return font;
- }
-@@ -1295,8 +1275,8 @@ pango_core_text_font_map_load_fontset (PangoFontMap *fontmap,
- PangoCoreTextFontMap *ctfontmap = PANGO_CORE_TEXT_FONT_MAP (fontmap);
- static gboolean warned_full_fallback = FALSE; /* MT-safe */
-
-- pango_core_text_fontset_key_init (&key, ctfontmap,
-- context, desc, language);
-+ _pango_core_text_fontset_key_init (&key, ctfontmap,
-+ context, desc, language);
-
- fontset = g_hash_table_lookup (ctfontmap->fontset_hash, &key);
-
-@@ -1320,8 +1300,8 @@ pango_core_text_font_map_load_fontset (PangoFontMap *fontmap,
- tmp_desc = pango_font_description_copy_static (desc);
- pango_font_description_set_family_static (tmp_desc, "Sans");
-
-- pango_core_text_fontset_key_init (&key, ctfontmap, context, tmp_desc,
-- language);
-+ _pango_core_text_fontset_key_init (&key, ctfontmap, context, tmp_desc,
-+ language);
-
- fontset = g_hash_table_lookup (ctfontmap->fontset_hash, &key);
- if (G_LIKELY (fontset))
-@@ -1450,6 +1430,53 @@ pango_core_text_font_map_init (PangoCoreTextFontMap *ctfontmap)
- CFRelease (dict);
- }
-
-+ if (true)
-+ {
-+ NSFont *sysfont = [NSFont systemFontOfSize: 0.0];
-+ NSString *name = [[NSFont fontWithName: [[sysfont fontDescriptor] postscriptName] size: 0.0] familyName];
-+
-+ NSArray *fontfaces = [[NSFontManager sharedFontManager] availableMembersOfFontFamily: name];
-+ int num_faces = [fontfaces count];
-+ CFRelease (name);
-+
-+ for (int faceindex = 0; faceindex < num_faces; faceindex++)
-+ {
-+ SInt64 font_traits;
-+ char *buffer;
-+ char *family_name;
-+ CFNumberRef number;
-+ CFDictionaryRef dict;
-+ CTFontDescriptorRef desc = [sysfont fontDescriptor];
-+
-+ buffer = ct_font_descriptor_get_family_name (desc, TRUE);
-+ if (!buffer)
-+ continue;
-+
-+ family_name = g_utf8_casefold (buffer, -1);
-+ family = g_hash_table_lookup (ctfontmap->families, family_name);
-+ if (!family)
-+ {
-+ family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL);
-+ g_hash_table_insert (ctfontmap->families, g_strdup ("-apple-system-font"), family);
-+ family->family_name = g_strdup (buffer);
-+ }
-+
-+ g_free (buffer);
-+ g_free (family_name);
-+
-+ dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
-+ number = (CFNumberRef)CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
-+
-+ if (CFNumberGetValue (number, kCFNumberSInt64Type, &font_traits))
-+ {
-+ if ((font_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait)
-+ family->is_monospace = TRUE;
-+ }
-+
-+ CFRelease (dict);
-+ }
-+ }
-+
- /* Insert aliases */
- family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL);
- family->family_name = g_strdup ("Sans");
-diff --git a/pango/pangocoretext-private.h b/pango/pangocoretext-private.h
-index 8076eae..5c6ce41 100644
---- a/pango/pangocoretext-private.h
-+++ b/pango/pangocoretext-private.h
-@@ -81,6 +81,30 @@ struct _PangoCoreTextFontMapClass
- PangoContext *context);
- };
-
-+struct _PangoCoreTextFontKey
-+{
-+ PangoCoreTextFontMap *fontmap;
-+ CTFontDescriptorRef ctfontdescriptor;
-+ PangoMatrix matrix;
-+ PangoGravity gravity;
-+ int pixelsize;
-+ double resolution;
-+ gboolean synthetic_italic;
-+ gpointer context_key;
-+};
-+
-+struct _PangoCoreTextFontsetKey
-+{
-+ PangoCoreTextFontMap *fontmap;
-+ PangoLanguage *language;
-+ PangoFontDescription *desc;
-+ PangoMatrix matrix;
-+ int pixelsize;
-+ double resolution;
-+ PangoGravity gravity;
-+ gpointer context_key;
-+};
-+
-
- GType pango_core_text_font_map_get_type (void) G_GNUC_CONST;
-
-@@ -97,6 +121,24 @@ void _pango_core_text_font_set_font_key (PangoCoreTextF
- void _pango_core_text_font_set_ctfont (PangoCoreTextFont *font,
- CTFontRef font_ref);
-
-+void _pango_core_text_fontset_key_init (PangoCoreTextFontsetKey *key,
-+ PangoCoreTextFontMap *fontmap,
-+ PangoContext *context,
-+ const PangoFontDescription *desc,
-+ PangoLanguage *language);
-+void _pango_core_text_font_key_init (PangoCoreTextFontKey *key,
-+ PangoCoreTextFontMap *ctfontmap,
-+ PangoCoreTextFontsetKey *fontset_key,
-+ CTFontDescriptorRef ctdescriptor,
-+ gboolean synthetic_italic);
-+
-+void _pango_core_text_font_map_add (PangoCoreTextFontMap *ctfontmap,
-+ PangoCoreTextFontKey *key,
-+ PangoCoreTextFont *ctfont);
-+
-+PangoCoreTextFont *_pango_core_text_font_map_lookup_font (PangoCoreTextFontMap *fontmap,
-+ PangoCoreTextFontKey *key);
-+
- PangoFontDescription *_pango_core_text_font_description_from_ct_font_descriptor (CTFontDescriptorRef desc);
-
- int pango_core_text_font_key_get_absolute_size (const PangoCoreTextFontKey *key);