summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/quartz-state.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/quartz-state.patch')
-rw-r--r--gfx/cairo/quartz-state.patch1190
1 files changed, 0 insertions, 1190 deletions
diff --git a/gfx/cairo/quartz-state.patch b/gfx/cairo/quartz-state.patch
deleted file mode 100644
index d4c04f706..000000000
--- a/gfx/cairo/quartz-state.patch
+++ /dev/null
@@ -1,1190 +0,0 @@
-diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
---- a/gfx/cairo/cairo/src/cairo-quartz-private.h
-+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
-@@ -50,30 +50,16 @@ typedef struct cairo_quartz_surface {
- CGContextRef cgContext;
- CGAffineTransform cgContextBaseCTM;
-
- void *imageData;
- 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()
-- */
-- CGAffineTransform sourceTransform;
--
-- CGImageRef sourceImage;
-- cairo_surface_t *sourceImageSurface;
-- CGRect sourceImageRect;
--
-- CGShadingRef sourceShading;
-- CGPatternRef sourcePattern;
--
-- CGInterpolationQuality oldInterpolationQuality;
- } cairo_quartz_surface_t;
-
- typedef struct cairo_quartz_image_surface {
- cairo_surface_t base;
-
- cairo_rectangle_int_t extents;
-
- CGImageRef image;
-diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
-+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
-@@ -1333,36 +1333,59 @@ _cairo_quartz_cairo_repeating_surface_pa
- return CAIRO_STATUS_SUCCESS;
- }
-
- typedef enum {
- DO_SOLID,
- DO_SHADING,
- DO_PATTERN,
- DO_IMAGE,
-+ DO_TILED_IMAGE,
- 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 and DO_TILED_IMAGE
-+ CGAffineTransform transform;
-+
-+ // Used with DO_IMAGE and DO_TILED_IMAGE
-+ CGImageRef image;
-+ cairo_surface_t *imageSurface;
-+ CGRect imageRect;
-+
-+ // 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;
- CGImageRef img;
-
- 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);
- w = ceil(clipBox.origin.x + clipBox.size.width) - x0;
- h = ceil(clipBox.origin.y + clipBox.size.height) - y0;
-
- /* Create a temporary the size of the clip surface, and position
- * it so that the device origin coincides with the original surface */
-@@ -1396,73 +1419,79 @@ _cairo_quartz_setup_fallback_source (cai
- &fallback->device_transform_inverse);
- status = _cairo_surface_paint (fallback,
- CAIRO_OPERATOR_SOURCE,
- &pattern.base, NULL);
- }
- #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);
--
-- return DO_IMAGE;
-+ if (status) {
-+ state->action = DO_UNSUPPORTED;
-+ return;
-+ }
-+ if (img == NULL) {
-+ state->action = DO_NOTHING;
-+ return;
-+ }
-+
-+ state->imageRect = CGRectMake (0.0, 0.0, w, h);
-+ state->image = img;
-+ state->imageSurface = fallback;
-+ state->transform = CGAffineTransformMakeTranslation (x0, y0);
-+ state->action = DO_IMAGE;
- }
-
- /*
- Quartz does not support repeating radients. We handle repeating gradients
- by manually extending the gradient and repeating color stops. We need to
- minimize the number of repetitions since Quartz seems to sample our color
- function across the entire range, even if part of that range is not needed
- for the visible area of the gradient, and it samples with some fixed resolution,
- so if the gradient range is too large it samples with very low resolution and
- the gradient is very coarse. CreateRepeatingLinearGradientFunction and
- CreateRepeatingRadialGradientFunction compute the number of repetitions needed
- based on the extents of the object (the clip region cannot be used here since
- 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;
- CGPoint start, end;
- CGFunctionRef gradFunc;
- CGColorSpaceRef rgb;
- 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 &&
- lpat->p1.y == lpat->p2.y) {
- /* Quartz handles cases where the vector has no length very
- * differently from pixman.
- * 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();
-
- start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x),
- _cairo_fixed_to_double (lpat->p1.y));
- end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x),
- _cairo_fixed_to_double (lpat->p2.y));
-
-@@ -1472,31 +1501,32 @@ _cairo_quartz_setup_linear_source (cairo
- gradFunc = CreateGradientFunction (&lpat->base);
- } else {
- gradFunc = CreateRepeatingLinearGradientFunction (surface,
- &lpat->base,
- &start, &end,
- 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;
- CGPoint start, end;
- CGFunctionRef gradFunc;
- CGColorSpaceRef rgb;
- bool extend = abspat->extend == CAIRO_EXTEND_PAD;
- double c1x = _cairo_fixed_to_double (rpat->c1.x);
-@@ -1505,35 +1535,37 @@ _cairo_quartz_setup_radial_source (cairo
- double c2y = _cairo_fixed_to_double (rpat->c2.y);
- double r1 = _cairo_fixed_to_double (rpat->r1);
- double r2 = _cairo_fixed_to_double (rpat->r2);
- double dx = c1x - c2x;
- double dy = c1y - c2y;
- 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 */
- r1 <= centerDistance + r2 + 1e-6) { /* circle 1 doesn't contain circle 2 */
- /* Quartz handles cases where neither circle contains the other very
- * differently from pixman.
- * Whatever the correct behaviour is, let's at least have only pixman's
- * 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();
-
- start = CGPointMake (c1x, c1y);
- end = CGPointMake (c2x, c2y);
-
- if (abspat->extend == CAIRO_EXTEND_NONE ||
- abspat->extend == CAIRO_EXTEND_PAD)
-@@ -1542,111 +1574,146 @@ _cairo_quartz_setup_radial_source (cairo
- } else {
- gradFunc = CreateRepeatingRadialGradientFunction (surface,
- &rpat->base,
- &start, &r1,
- &end, &r2,
- 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)
-+/**
-+ * 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)
- {
-- assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
--
-- surface->oldInterpolationQuality = CGContextGetInterpolationQuality (surface->cgContext);
-- CGContextSetInterpolationQuality (surface->cgContext, _cairo_quartz_filter_to_quartz (source->filter));
-+ CGContextRef context = surface->cgContext;
-+ cairo_quartz_drawing_state_t state;
-+ cairo_status_t status;
-+
-+ state.context = context;
-+ state.image = NULL;
-+ state.imageSurface = NULL;
-+ state.shading = NULL;
-+ state.pattern = NULL;
-+
-+ // 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 (source->type == CAIRO_PATTERN_TYPE_SOLID) {
- cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
-
-- CGContextSetRGBStrokeColor (surface->cgContext,
-+ CGContextSetRGBStrokeColor (context,
- solid->color.red,
- solid->color.green,
- solid->color.blue,
- solid->color.alpha);
-- CGContextSetRGBFillColor (surface->cgContext,
-+ CGContextSetRGBFillColor (context,
- solid->color.red,
- solid->color.green,
- solid->color.blue,
- solid->color.alpha);
-
-- return DO_SOLID;
-+ 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;
-- return _cairo_quartz_setup_linear_source (surface, lpat, extents);
-+ _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;
-- return _cairo_quartz_setup_radial_source (surface, rpat, extents);
-+ _cairo_quartz_setup_radial_source (surface, rpat, extents, &state);
-+ return state;
- }
-
- if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
- (source->extend == CAIRO_EXTEND_NONE || (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;
-
- status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
-- if (status)
-- return DO_UNSUPPORTED;
-- if (img == NULL)
-- return DO_NOTHING;
-+ if (status) {
-+ state.action = DO_UNSUPPORTED;
-+ return state;
-+ }
-+ if (img == NULL) {
-+ state.action = DO_NOTHING;
-+ return state;
-+ }
-
- CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
-
-- surface->sourceImage = img;
-+ state.image = img;
-
- cairo_matrix_invert(&m);
-- _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceTransform);
-+ _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
-
- 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;
-+ state.imageRect = CGRectMake (0, 0, extents.width, extents.height);
-+ state.action = DO_IMAGE;
-+ return state;
- }
-
- /* Quartz seems to tile images at pixel-aligned regions only -- this
- * leads to seams if the image doesn't end up scaling to fill the
- * space exactly. The CGPattern tiling approach doesn't have this
- * problem. Check if we're going to fill up the space (within some
- * 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);
-
- fw = _cairo_fixed_from_double (srcRect.size.width);
- fh = _cairo_fixed_from_double (srcRect.size.height);
-
- if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
-@@ -1657,111 +1724,109 @@ _cairo_quartz_setup_source (cairo_quartz
-
- srcRect.size.width = round(srcRect.size.width);
- srcRect.size.height = round(srcRect.size.height);
-
- xform = CGAffineTransformInvert (xform);
-
- srcRect = CGRectApplyAffineTransform (srcRect, xform);
-
-- surface->sourceImageRect = srcRect;
--
-- return DO_TILED_IMAGE;
-+ state.imageRect = srcRect;
-+ state.action = DO_TILED_IMAGE;
-+ return state;
- }
-
- /* Fall through to generic SURFACE case */
- }
-
- if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
- CGFloat 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);
-+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
-+ state.action = DO_NOTHING;
-+ return state;
-+ }
-+ if (status) {
-+ state.action = DO_UNSUPPORTED;
-+ return state;
-+ }
-+
-+ 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 (surface->cgContext, CGSizeMake(0,0));
--
-- surface->sourcePattern = pattern;
--
-- return DO_PATTERN;
-+ CGContextSetPatternPhase (context, CGSizeMake(0,0));
-+
-+ state.pattern = pattern;
-+ state.action = DO_PATTERN;
-+ return state;
- }
-
-- return DO_UNSUPPORTED;
-+ 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_teardown_source (cairo_quartz_surface_t *surface,
-- const cairo_pattern_t *source)
-+_cairo_quartz_teardown_state (cairo_quartz_drawing_state_t *state)
- {
-- CGContextSetInterpolationQuality (surface->cgContext, surface->oldInterpolationQuality);
--
-- if (surface->sourceImage) {
-- CGImageRelease(surface->sourceImage);
-- surface->sourceImage = NULL;
--
-- cairo_surface_destroy(surface->sourceImageSurface);
-- surface->sourceImageSurface = NULL;
-+ if (state->image) {
-+ CGImageRelease(state->image);
- }
-
-- if (surface->sourceShading) {
-- CGShadingRelease(surface->sourceShading);
-- surface->sourceShading = NULL;
-+ if (state->imageSurface) {
-+ cairo_surface_destroy(state->imageSurface);
- }
-
-- if (surface->sourcePattern) {
-- CGPatternRelease(surface->sourcePattern);
-- // To tear down the pattern and colorspace
-- CGContextRestoreGState(surface->cgContext);
--
-- surface->sourcePattern = NULL;
-+ if (state->shading) {
-+ CGShadingRelease(state->shading);
- }
-+
-+ if (state->pattern) {
-+ CGPatternRelease(state->pattern);
-+ }
-+
-+ 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_draw_image (cairo_quartz_drawing_state_t *state, cairo_operator_t op)
- {
-- assert (surface && surface->sourceImage && (action == DO_IMAGE || action == DO_TILED_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);
-+ assert (state && state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE));
-+
-+ CGContextConcatCTM (state->context, state->transform);
-+ CGContextTranslateCTM (state->context, 0, state->imageRect.size.height);
-+ CGContextScaleCTM (state->context, 1, -1);
-+
-+ if (state->action == DO_IMAGE) {
-+ CGContextDrawImage (state->context, state->imageRect, state->image);
-+ if (!_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);
-+ CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
- }
-
-
- /*
- * get source/dest image implementation
- */
-
- /* Read the image from the surface's front buffer */
-@@ -2098,52 +2163,44 @@ _cairo_quartz_surface_get_extents (void
- static cairo_int_status_t
- _cairo_quartz_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_clip_t *clip)
- {
- 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));
-
- if (IS_EMPTY(surface))
- return CAIRO_STATUS_SUCCESS;
-
- rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
- 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;
--
-- 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) {
-+ state = _cairo_quartz_setup_state (surface, source, op, NULL);
-+
-+ 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) {
-+ _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;
- }
-
- static cairo_bool_t
- _cairo_quartz_source_needs_extents (const cairo_pattern_t *source)
- {
-@@ -2170,91 +2227,83 @@ _cairo_quartz_surface_fill (void *abstra
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip)
- {
- 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;
- quartz_stroke_t stroke;
- CGPathRef path_for_unbounded = NULL;
-
- ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
-
- if (IS_EMPTY(surface))
- return CAIRO_STATUS_SUCCESS;
-
- rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
- 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
- compute the number of gradient reptitions needed to cover the
- 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);
- }
-
-- CGContextBeginPath (surface->cgContext);
--
-- stroke.cgContext = surface->cgContext;
-+ CGContextSetShouldAntialias (state.context, (antialias != CAIRO_ANTIALIAS_NONE));
-+
-+ CGContextBeginPath (state.context);
-+
-+ stroke.cgContext = state.context;
- stroke.ctm_inverse = NULL;
- rv = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
- if (rv)
- goto BAIL;
-
- if (!_cairo_operator_bounded_by_mask(op) && CGContextCopyPathPtr)
-- path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
--
-- if (action == DO_SOLID || action == DO_PATTERN) {
-+ path_for_unbounded = CGContextCopyPathPtr (state.context);
-+
-+ 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);
--
-- CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-- CGContextDrawShading (surface->cgContext, surface->sourceShading);
-- } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-+ CGContextEOClip (state.context);
-+
-+ CGContextConcatCTM (state.context, state.transform);
-+ CGContextDrawShading (state.context, state.shading);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
- if (fill_rule == CAIRO_FILL_RULE_WINDING)
-- CGContextClip (surface->cgContext);
-+ CGContextClip (state.context);
- else
-- CGContextEOClip (surface->cgContext);
--
-- _cairo_quartz_draw_image (surface, op, action);
-- } else if (action != DO_NOTHING) {
-+ CGContextEOClip (state.context);
-+
-+ _cairo_quartz_draw_image (&state, op);
-+ } else if (state.action != DO_NOTHING) {
- rv = CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- BAIL:
-- _cairo_quartz_teardown_source (surface, source);
--
-- CGContextRestoreGState (surface->cgContext);
-+ _cairo_quartz_teardown_state (&state);
-
- if (path_for_unbounded) {
- unbounded_op_data_t ub;
- ub.op = UNBOUNDED_STROKE_FILL;
- ub.u.stroke_fill.cgPath = path_for_unbounded;
- ub.u.stroke_fill.fill_rule = fill_rule;
-
- _cairo_quartz_fixup_unbounded_operation (surface, &ub, antialias);
-@@ -2274,44 +2323,49 @@ _cairo_quartz_surface_stroke (void *abst
- cairo_matrix_t *ctm,
- cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip)
- {
- 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;
- quartz_stroke_t stroke;
- CGAffineTransform origCTM, strokeTransform;
- CGPathRef path_for_unbounded = NULL;
-
- ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
-
- if (IS_EMPTY(surface))
- return CAIRO_STATUS_SUCCESS;
-
- rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
- 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;
-+ 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);
--
-- origCTM = CGContextGetCTM (surface->cgContext);
-+ 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 (state.context);
-
- if (style->dash && style->num_dashes) {
- #define STATIC_DASH 32
- CGFloat sdash[STATIC_DASH];
- CGFloat *fdash = sdash;
- double offset = style->dash_offset;
- unsigned int max_dashes = style->num_dashes;
- unsigned int k;
-@@ -2330,90 +2384,75 @@ _cairo_quartz_surface_stroke (void *abst
- if (max_dashes > STATIC_DASH)
- fdash = _cairo_malloc_ab (max_dashes, sizeof (CGFloat));
- if (fdash == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- for (k = 0; k < max_dashes; k++)
- fdash[k] = (CGFloat) style->dash[k % style->num_dashes];
- }
-- CGContextSetLineDash (surface->cgContext, offset, fdash, max_dashes);
-+ CGContextSetLineDash (state.context, offset, fdash, max_dashes);
- if (fdash != sdash)
- free (fdash);
- } else
-- CGContextSetLineDash (surface->cgContext, 0, NULL, 0);
--
-- CGContextSaveGState (surface->cgContext);
--
--
-- 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);
-- }
-+ CGContextSetLineDash (state.context, 0, NULL, 0);
-
- _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
-- CGContextConcatCTM (surface->cgContext, strokeTransform);
--
-- CGContextBeginPath (surface->cgContext);
--
-- stroke.cgContext = surface->cgContext;
-+ CGContextConcatCTM (state.context, strokeTransform);
-+
-+ CGContextBeginPath (state.context);
-+
-+ stroke.cgContext = state.context;
- stroke.ctm_inverse = ctm_inverse;
- rv = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
- if (rv)
- goto BAIL;
-
- if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
-- path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
--
-- 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) {
-+ path_for_unbounded = CGContextCopyPathPtr (state.context);
-+
-+ if (state.action == DO_SOLID || state.action == DO_PATTERN) {
-+ CGContextStrokePath (state.context);
-+ } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
-+ 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;
- }
-
-+ if (path_for_unbounded) {
-+ CGContextSetCTM (state.context, origCTM);
-+ CGContextConcatCTM (state.context, strokeTransform);
-+
-+ CGContextBeginPath (state.context);
-+ CGContextAddPath (state.context, path_for_unbounded);
-+ CGPathRelease (path_for_unbounded);
-+
-+ CGContextReplacePathWithStrokedPath (state.context);
-+
-+ CGContextAddRect (state.context, CGContextGetClipBoundingBox (state.context));
-+
-+ CGContextSetRGBFillColor (state.context, 0., 0., 0., 0.);
-+ CGContextEOFillPath (state.context);
-+ }
-+
- BAIL:
-- _cairo_quartz_teardown_source (surface, source);
--
-- CGContextRestoreGState (surface->cgContext);
--
-- if (path_for_unbounded) {
-- CGContextSaveGState (surface->cgContext);
-- CGContextConcatCTM (surface->cgContext, strokeTransform);
--
-- CGContextBeginPath (surface->cgContext);
-- CGContextAddPath (surface->cgContext, path_for_unbounded);
-- CGPathRelease (path_for_unbounded);
--
-- CGContextReplacePathWithStrokedPath (surface->cgContext);
--
-- CGContextAddRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
--
-- CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.);
-- CGContextEOFillPath (surface->cgContext);
--
-- CGContextRestoreGState (surface->cgContext);
-- }
-+ _cairo_quartz_teardown_state (&state);
-
- ND((stderr, "-- stroke\n"));
- return rv;
- }
-
- #if CAIRO_HAS_QUARTZ_FONT
- static cairo_int_status_t
- _cairo_quartz_surface_show_glyphs (void *abstract_surface,
-@@ -2429,17 +2468,17 @@ _cairo_quartz_surface_show_glyphs (void
- #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];
-
- 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;
- float xprev, yprev;
- int i;
- CGFontRef cgfref = NULL;
-
- cairo_bool_t isClipping = FALSE;
- cairo_bool_t didForceFontSmoothing = FALSE;
-
- if (IS_EMPTY(surface))
-@@ -2450,65 +2489,59 @@ _cairo_quartz_surface_show_glyphs (void
-
- if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
- 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_rectangle_int_t glyph_extents;
- _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) {
-+ 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);
-
- 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 */
- break;
- }
-
- if (num_glyphs > STATIC_BUF_SIZE) {
- cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof(CGGlyph));
-@@ -2532,17 +2565,17 @@ _cairo_quartz_surface_show_glyphs (void
- textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
- textTransform = CGAffineTransformConcat (CGAffineTransformMake(scaled_font->ctm.xx,
- -scaled_font->ctm.yx,
- -scaled_font->ctm.xy,
- scaled_font->ctm.yy,
- 0., 0.),
- textTransform);
-
-- CGContextSetTextMatrix (surface->cgContext, textTransform);
-+ CGContextSetTextMatrix (state.context, textTransform);
-
- /* 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;
-
-@@ -2569,40 +2602,38 @@ _cairo_quartz_surface_show_glyphs (void
-
- #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
-
- /* Translate to the first glyph's position before drawing */
-- ctm = CGContextGetCTM (surface->cgContext);
-- CGContextTranslateCTM (surface->cgContext, glyphs[0].x, glyphs[0].y);
--
-- CGContextShowGlyphsWithAdvances (surface->cgContext,
-+ ctm = CGContextGetCTM (state.context);
-+ CGContextTranslateCTM (state.context, glyphs[0].x, glyphs[0].y);
-+
-+ CGContextShowGlyphsWithAdvances (state.context,
- cg_glyphs,
- cg_advances,
- num_glyphs);
-
-- CGContextSetCTM (surface->cgContext, ctm);
--
-- 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);
-+ CGContextSetCTM (state.context, ctm);
-+
-+ if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
-+ _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);
--
-- CGContextRestoreGState (surface->cgContext);
-+ CGContextSetAllowsFontSmoothingPtr (state.context, FALSE);
-+
-+ _cairo_quartz_teardown_state (&state);
-
- if (rv == CAIRO_STATUS_SUCCESS &&
- cgfref &&
- !_cairo_operator_bounded_by_mask (op))
- {
- unbounded_op_data_t ub;
- ub.op = UNBOUNDED_SHOW_GLYPHS;
-