[cairo-commit] 7 commits - src/cairo-quartz-private.h src/cairo-quartz-surface.c

Andrea Canciani ranma42 at kemper.freedesktop.org
Tue Oct 12 15:28:30 PDT 2010


 src/cairo-quartz-private.h |   21 --
 src/cairo-quartz-surface.c |  337 +++++++++++++++++++--------------------------
 2 files changed, 155 insertions(+), 203 deletions(-)

New commits:
commit 35b1688c92d2c0e1353fc2b5e89abb29c2acda8d
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Oct 13 00:13:42 2010 +0200

    quartz: Remove unused imageSurface field
    
    imageSurface was used to store a reference to the fallback image
    generated by during fallbacks for gradients. The fallback code
    has been removed as it is not needed anymore, thus this field can
    be removed as well.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index c4d9492..c86d913 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1311,7 +1311,6 @@ typedef struct {
 
     /* Used with DO_IMAGE and DO_TILED_IMAGE */
     CGImageRef image;
-    cairo_surface_t *imageSurface;
     CGRect imageRect;
 
     /* Used with DO_SHADING */
@@ -1438,7 +1437,6 @@ _cairo_quartz_setup_source (cairo_quartz_drawing_state_t *state,
     cairo_status_t status;
 
     state->image = NULL;
-    state->imageSurface = NULL;
     state->shading = NULL;
 
     /* Save before we change the pattern, colorspace, etc. so that
@@ -1596,9 +1594,6 @@ _cairo_quartz_teardown_source (cairo_quartz_drawing_state_t *state,
     if (state->image)
 	CGImageRelease (state->image);
 
-    if (state->imageSurface)
-	cairo_surface_destroy (state->imageSurface);
-
     if (state->shading)
 	CGShadingRelease (state->shading);
 }
commit ce455994a36cabe4a39a666556282ef2bf8b8daf
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Oct 13 00:10:09 2010 +0200

    quartz: Cleanup gradient setup functions
    
    Gradient setup does not depend anymore on the surface on which the
    gradient will be composited.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 6872e52..c4d9492 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -887,8 +887,7 @@ UpdateLinearParametersToIncludePoint (double *min_t, double *max_t, CGPoint *sta
 }
 
 static CGFunctionRef
-CreateRepeatingLinearGradientFunction (cairo_quartz_surface_t *surface,
-				       const cairo_gradient_pattern_t *gpat,
+CreateRepeatingLinearGradientFunction (const cairo_gradient_pattern_t *gpat,
 				       CGPoint *start, CGPoint *end,
 				       const cairo_rectangle_int_t *extents)
 {
@@ -987,8 +986,7 @@ UpdateRadialParameterToIncludePoint (double *max_t, CGPoint *center,
 
 /* This must only be called when one of the circles properly contains the other */
 static CGFunctionRef
-CreateRepeatingRadialGradientFunction (cairo_quartz_surface_t *surface,
-                                       const cairo_gradient_pattern_t *gpat,
+CreateRepeatingRadialGradientFunction (const cairo_gradient_pattern_t *gpat,
                                        CGPoint *start, double *start_radius,
                                        CGPoint *end, double *end_radius,
                                        const cairo_rectangle_int_t *extents)
@@ -1336,7 +1334,6 @@ clip region).
 */
 static cairo_int_status_t
 _cairo_quartz_setup_linear_source (cairo_quartz_drawing_state_t *state,
-				   cairo_quartz_surface_t *surface,
 				   const cairo_linear_pattern_t *lpat,
 				   const cairo_rectangle_int_t *extents)
 {
@@ -1363,8 +1360,7 @@ _cairo_quartz_setup_linear_source (cairo_quartz_drawing_state_t *state,
     if (!extend)
 	gradFunc = CreateGradientFunction (&lpat->base);
     else
-	gradFunc = CreateRepeatingLinearGradientFunction (surface,
-						          &lpat->base,
+	gradFunc = CreateRepeatingLinearGradientFunction (&lpat->base,
 						          &start, &end,
 						          extents);
 
@@ -1382,7 +1378,6 @@ _cairo_quartz_setup_linear_source (cairo_quartz_drawing_state_t *state,
 
 static cairo_int_status_t
 _cairo_quartz_setup_radial_source (cairo_quartz_drawing_state_t *state,
-				   cairo_quartz_surface_t *surface,
 				   const cairo_radial_pattern_t *rpat,
 				   const cairo_rectangle_int_t *extents)
 {
@@ -1413,8 +1408,7 @@ _cairo_quartz_setup_radial_source (cairo_quartz_drawing_state_t *state,
     if (!extend)
 	gradFunc = CreateGradientFunction (&rpat->base);
     else
-	gradFunc = CreateRepeatingRadialGradientFunction (surface,
-						          &rpat->base,
+	gradFunc = CreateRepeatingRadialGradientFunction (&rpat->base,
 						          &start, &r1,
 						          &end, &r2,
 						          extents);
@@ -1480,12 +1474,12 @@ _cairo_quartz_setup_source (cairo_quartz_drawing_state_t *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 (state, surface, lpat, extents);
+	return _cairo_quartz_setup_linear_source (state, 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 (state, surface, rpat, extents);
+	return _cairo_quartz_setup_radial_source (state, rpat, extents);
     }
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
commit 1061c80d79e0e282617669397b45e0776d23bfb6
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Thu Jul 29 16:48:30 2010 +0200

    quartz: Move drawing state out of surface
    
    Some pattern types (gradients, surface patterns) require some
    temporary information to be stored as "graphic state", because it
    doesn't belong to CGContext. Previously all of this data was stored
    inside the surface during the drawing operations, now it's in a
    stack-allocated structure (of type cairo_quartz_drawing_state_t).
    Based on a patch by Robert O'Callahan <robert at ocallahan.org>.
    See https://bugzilla.mozilla.org/show_bug.cgi?id=522859

diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index bd12bfb..beac884 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -69,18 +69,6 @@ typedef struct cairo_quartz_surface {
     cairo_surface_clipper_t clipper;
     cairo_rectangle_int_t extents;
     cairo_rectangle_int_t virtual_extents;
-
-    /* These are stored while drawing operations are in place, set up
-     * by quartz_setup_source() and quartz_finish_source()
-     */
-    cairo_quartz_action_t action;
-    CGAffineTransform sourceTransform;
-
-    CGImageRef sourceImage;
-    cairo_surface_t *sourceImageSurface;
-    CGRect sourceImageRect;
-
-    CGShadingRef sourceShading;
 } cairo_quartz_surface_t;
 
 typedef struct cairo_quartz_image_surface {
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index ec5aa26..6872e52 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1304,6 +1304,23 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* State used during a drawing operation. */
+typedef struct {
+    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;
+
+} cairo_quartz_drawing_state_t;
+
 /*
 Quartz does not support repeating radients. We handle repeating gradients
 by manually extending the gradient and repeating color stops. We need to
@@ -1318,7 +1335,8 @@ we don't want the rasterization of the entire gradient to depend on the
 clip region).
 */
 static cairo_int_status_t
-_cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
+_cairo_quartz_setup_linear_source (cairo_quartz_drawing_state_t *state,
+				   cairo_quartz_surface_t *surface,
 				   const cairo_linear_pattern_t *lpat,
 				   const cairo_rectangle_int_t *extents)
 {
@@ -1333,7 +1351,7 @@ _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
 
     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 ();
 
@@ -1350,20 +1368,21 @@ _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
 						          &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);
 
-    surface->action = DO_SHADING;
+    state->action = DO_SHADING;
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
-_cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
+_cairo_quartz_setup_radial_source (cairo_quartz_drawing_state_t *state,
+				   cairo_quartz_surface_t *surface,
 				   const cairo_radial_pattern_t *rpat,
 				   const cairo_rectangle_int_t *extents)
 {
@@ -1384,7 +1403,7 @@ _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
 
     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 ();
 
@@ -1400,30 +1419,33 @@ _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
 						          &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);
 
-    surface->action = DO_SHADING;
+    state->action = DO_SHADING;
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
-_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
+_cairo_quartz_setup_source (cairo_quartz_drawing_state_t *state,
+			    cairo_quartz_surface_t *surface,
 			    cairo_operator_t op,
 			    const cairo_pattern_t *source,
 			    const cairo_rectangle_int_t *extents)
 {
     cairo_status_t status;
 
-    assert (!(surface->sourceImage || surface->sourceShading));
+    state->image = NULL;
+    state->imageSurface = NULL;
+    state->shading = NULL;
 
     /* Save before we change the pattern, colorspace, etc. so that
      * we can restore and make sure that quartz releases our
@@ -1452,18 +1474,18 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 				  solid->color.blue,
 				  solid->color.alpha);
 
-	surface->action = DO_DIRECT;
+	state->action = DO_DIRECT;
 	return CAIRO_STATUS_SUCCESS;
     }
 
     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);
+	return _cairo_quartz_setup_linear_source (state, 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);
+	return _cairo_quartz_setup_radial_source (state, surface, rpat, extents);
     }
 
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
@@ -1487,17 +1509,17 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 
 	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);
-	    surface->action = DO_IMAGE;
+	    state->imageRect = CGRectMake (0, 0, extents.width, extents.height);
+	    state->action = DO_IMAGE;
 	    return CAIRO_STATUS_SUCCESS;
 	}
 
@@ -1509,7 +1531,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	 */
 
 	xform = CGAffineTransformConcat (CGContextGetCTM (surface->cgContext),
-					 surface->sourceTransform);
+					 state->transform);
 
 	srcRect = CGRectMake (0, 0, extents.width, extents.height);
 	srcRect = CGRectApplyAffineTransform (srcRect, xform);
@@ -1530,8 +1552,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 
 	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
 
-	    surface->sourceImageRect = srcRect;
-	    surface->action = DO_TILED_IMAGE;
+	    state->imageRect = srcRect;
+	    state->action = DO_TILED_IMAGE;
 	    return CAIRO_STATUS_SUCCESS;
 	}
 
@@ -1563,7 +1585,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 
 	CGPatternRelease (pattern);
 
-	surface->action = DO_DIRECT;
+	state->action = DO_DIRECT;
 	return CAIRO_STATUS_SUCCESS;
     }
 
@@ -1571,64 +1593,62 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 }
 
 static void
-_cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
-			       const cairo_pattern_t *source)
+_cairo_quartz_teardown_source (cairo_quartz_drawing_state_t *state,
+			       cairo_quartz_surface_t *surface)
+			       
 {
     CGContextRestoreGState (surface->cgContext);
 
-    if (surface->sourceImage) {
-	CGImageRelease (surface->sourceImage);
-	surface->sourceImage = NULL;
+    if (state->image)
+	CGImageRelease (state->image);
 
-	cairo_surface_destroy (surface->sourceImageSurface);
-	surface->sourceImageSurface = NULL;
-    }
+    if (state->imageSurface)
+	cairo_surface_destroy (state->imageSurface);
 
-    if (surface->sourceShading) {
-	CGShadingRelease (surface->sourceShading);
-	surface->sourceShading = NULL;
-    }
+    if (state->shading)
+	CGShadingRelease (state->shading);
 }
 
 static cairo_int_status_t
-_cairo_quartz_setup_source_safe (cairo_quartz_surface_t *surface,
+_cairo_quartz_setup_source_safe (cairo_quartz_drawing_state_t *state,
+				 cairo_quartz_surface_t *surface,
 				 cairo_operator_t op,
 				 const cairo_pattern_t *source,
 				 const cairo_rectangle_int_t *extents)
 {
     cairo_int_status_t status;
 
-    status = _cairo_quartz_setup_source (surface, op, source, extents);
+    status = _cairo_quartz_setup_source (state, surface, op, source, extents);
     if (unlikely (status))
-	_cairo_quartz_teardown_source (surface, source);
+	_cairo_quartz_teardown_source (state, surface);
 
     return status;
 }
 
 static void
-_cairo_quartz_draw_source (cairo_quartz_surface_t *surface, cairo_operator_t op)
+_cairo_quartz_draw_source (cairo_quartz_surface_t *surface, cairo_operator_t op, cairo_quartz_drawing_state_t *state)
 {
-    CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
+    CGContextConcatCTM (surface->cgContext, state->transform);
 
-    if (surface->action == DO_SHADING) {
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    if (state->action == DO_SHADING) {
+	CGContextDrawShading (surface->cgContext, state->shading);
 	return;
     }
 
-    CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
+    CGContextTranslateCTM (surface->cgContext, 0, state->imageRect.size.height);
     CGContextScaleCTM (surface->cgContext, 1, -1);
 
-    if (surface->action == DO_IMAGE) {
-	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
+    if (state->action == DO_IMAGE) {
+	CGContextDrawImage (surface->cgContext, state->imageRect, state->image);
 	if (!_cairo_operator_bounded_by_source (op)) {
 	    CGContextBeginPath (surface->cgContext);
-	    CGContextAddRect (surface->cgContext, surface->sourceImageRect);
+	    CGContextAddRect (surface->cgContext, state->imageRect);
 	    CGContextAddRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
 	    CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 0);
 	    CGContextEOFillPath (surface->cgContext);
 	}
     } else
-	CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
+	CGContextDrawTiledImagePtr (surface->cgContext, state->imageRect, state->image);
 }
 
 
@@ -1979,6 +1999,7 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
 				const cairo_pattern_t *source,
 				cairo_clip_t *clip)
 {
+    cairo_quartz_drawing_state_t state;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     cairo_rectangle_int_t extents;
 
@@ -1995,20 +2016,20 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (&state, surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
-    if (surface->action == DO_DIRECT) {
+    if (state.action == DO_DIRECT) {
 	CGContextFillRect (surface->cgContext, CGRectMake (surface->extents.x,
 							   surface->extents.y,
 							   surface->extents.width,
 							   surface->extents.height));
     } else {
-	_cairo_quartz_draw_source (surface, op);
+	_cairo_quartz_draw_source (surface, op, &state);
     }
 
-    _cairo_quartz_teardown_source (surface, source);
+    _cairo_quartz_teardown_source (&state, surface);
 
     ND ((stderr, "-- paint\n"));
     return rv;
@@ -2051,6 +2072,7 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 			       cairo_antialias_t antialias,
 			       cairo_clip_t *clip)
 {
+    cairo_quartz_drawing_state_t state;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     CGPathRef path_for_unbounded = NULL;
     cairo_rectangle_int_t extents;
@@ -2068,7 +2090,7 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (&state, surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
@@ -2079,7 +2101,7 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
     if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
 	path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
 
-    if (surface->action == DO_DIRECT) {
+    if (state.action == DO_DIRECT) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextFillPath (surface->cgContext);
 	else
@@ -2090,10 +2112,10 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 	else
 	    CGContextEOClip (surface->cgContext);
 
-	_cairo_quartz_draw_source (surface, op);
+	_cairo_quartz_draw_source (surface, op, &state);
     }
 
-    _cairo_quartz_teardown_source (surface, source);
+    _cairo_quartz_teardown_source (&state, surface);
 
     if (path_for_unbounded) {
 	unbounded_op_data_t ub;
@@ -2158,6 +2180,7 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
 				 cairo_antialias_t antialias,
 				 cairo_clip_t *clip)
 {
+    cairo_quartz_drawing_state_t state;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     CGAffineTransform origCTM, strokeTransform;
     CGPathRef path_for_unbounded = NULL;
@@ -2210,7 +2233,7 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (&state, surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
@@ -2222,17 +2245,17 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
     CGContextConcatCTM (surface->cgContext, strokeTransform);
 
-    if (surface->action == DO_DIRECT) {
+    if (state.action == DO_DIRECT) {
 	CGContextStrokePath (surface->cgContext);
     } else {
 	CGContextReplacePathWithStrokedPath (surface->cgContext);
 	CGContextClip (surface->cgContext);
 
 	CGContextSetCTM (surface->cgContext, origCTM);
-	_cairo_quartz_draw_source (surface, op);
+	_cairo_quartz_draw_source (surface, op, &state);
     }
 
-    _cairo_quartz_teardown_source (surface, source);
+    _cairo_quartz_teardown_source (&state, surface);
 
     if (path_for_unbounded) {
 	unbounded_op_data_t ub;
@@ -2312,6 +2335,7 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
     CGGlyph *cg_glyphs = &glyphs_static[0];
     CGSize *cg_advances = &cg_advances_static[0];
 
+    cairo_quartz_drawing_state_t state;
     cairo_rectangle_int_t extents;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     cairo_quartz_float_t xprev, yprev;
@@ -2338,11 +2362,11 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (&state, surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
-    if (surface->action == DO_DIRECT) {
+    if (state.action == DO_DIRECT) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
     } else {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
@@ -2428,11 +2452,11 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
 
     CGContextSetCTM (surface->cgContext, ctm);
 
-    if (surface->action != DO_DIRECT)
-	_cairo_quartz_draw_source (surface, op);
+    if (state.action != DO_DIRECT)
+	_cairo_quartz_draw_source (surface, op, &state);
 
 BAIL:
-    _cairo_quartz_teardown_source (surface, source);
+    _cairo_quartz_teardown_source (&state, surface);
 
     if (didForceFontSmoothing)
 	CGContextSetAllowsFontSmoothingPtr (surface->cgContext, FALSE);
commit bbaca9598292eaee2da3c8a7c275d53bf1a1a652
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Thu Jul 29 15:50:21 2010 +0200

    quartz: Unify DO_SHADING, DO_IMAGE and DO_TILED_IMAGE
    
    DO_SHADING, DO_IMAGE and DO_TILED_IMAGE sources all require the source
    to be painted over the whole surface (inside the clip region), thus can
    share the same code path in drawing functions.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 9bf0240..ec5aa26 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1606,11 +1606,15 @@ _cairo_quartz_setup_source_safe (cairo_quartz_surface_t *surface,
 }
 
 static void
-_cairo_quartz_draw_image (cairo_quartz_surface_t *surface, cairo_operator_t op)
+_cairo_quartz_draw_source (cairo_quartz_surface_t *surface, cairo_operator_t op)
 {
-    assert (surface && surface->sourceImage && (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE));
-
     CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
+
+    if (surface->action == DO_SHADING) {
+	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+	return;
+    }
+
     CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
     CGContextScaleCTM (surface->cgContext, 1, -1);
 
@@ -2000,11 +2004,8 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
 							   surface->extents.y,
 							   surface->extents.width,
 							   surface->extents.height));
-    } else if (surface->action == DO_SHADING) {
-	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
-	_cairo_quartz_draw_image (surface, op);
+    } else {
+	_cairo_quartz_draw_source (surface, op);
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2083,24 +2084,13 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 	    CGContextFillPath (surface->cgContext);
 	else
 	    CGContextEOFillPath (surface->cgContext);
-    } else if (surface->action == DO_SHADING) {
-
-	// we have to clip and then paint the shading; we can't fill
-	// with the shading
-	if (fill_rule == CAIRO_FILL_RULE_WINDING)
-	    CGContextClip (surface->cgContext);
-	else
-	    CGContextEOClip (surface->cgContext);
-
-	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
+    } else {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextClip (surface->cgContext);
 	else
 	    CGContextEOClip (surface->cgContext);
 
-	_cairo_quartz_draw_image (surface, op);
+	_cairo_quartz_draw_source (surface, op);
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2234,20 +2224,12 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
 
     if (surface->action == DO_DIRECT) {
 	CGContextStrokePath (surface->cgContext);
-    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
-	CGContextReplacePathWithStrokedPath (surface->cgContext);
-	CGContextClip (surface->cgContext);
-
-	CGContextSetCTM (surface->cgContext, origCTM);
-	_cairo_quartz_draw_image (surface, op);
-    } else if (surface->action == DO_SHADING) {
+    } else {
 	CGContextReplacePathWithStrokedPath (surface->cgContext);
 	CGContextClip (surface->cgContext);
 
 	CGContextSetCTM (surface->cgContext, origCTM);
-
-	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+	_cairo_quartz_draw_source (surface, op);
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2362,7 +2344,7 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
 
     if (surface->action == DO_DIRECT) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE || surface->action == DO_SHADING) {
+    } else {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
 	isClipping = TRUE;
     }
@@ -2446,12 +2428,8 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
 
     CGContextSetCTM (surface->cgContext, ctm);
 
-    if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
-	_cairo_quartz_draw_image (surface, op);
-    } else if (surface->action == DO_SHADING) {
-	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
-	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    }
+    if (surface->action != DO_DIRECT)
+	_cairo_quartz_draw_source (surface, op);
 
 BAIL:
     _cairo_quartz_teardown_source (surface, source);
commit 51a6ae9d71daefdca214fdc48e1bb8fcba10029d
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Thu Jul 29 15:06:39 2010 +0200

    quartz: Unify DO_SOLID and DO_PATTERN
    
    Both DO_SOLID and DO_PATTERN setup the underlying CGContext to directly
    use the chosen color/pattern when filling and stroking, thus require no
    additional drawing operations and can share the same drawing code.

diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 9a45c66..bd12bfb 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -51,9 +51,8 @@ typedef float cairo_quartz_float_t;
 #endif
 
 typedef enum {
-    DO_SOLID,
+    DO_DIRECT,
     DO_SHADING,
-    DO_PATTERN,
     DO_IMAGE,
     DO_TILED_IMAGE
 } cairo_quartz_action_t;
@@ -82,7 +81,6 @@ typedef struct cairo_quartz_surface {
     CGRect sourceImageRect;
 
     CGShadingRef sourceShading;
-    CGPatternRef sourcePattern;
 } cairo_quartz_surface_t;
 
 typedef struct cairo_quartz_image_surface {
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 4f111ad..9bf0240 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1423,7 +1423,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 {
     cairo_status_t status;
 
-    assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
+    assert (!(surface->sourceImage || surface->sourceShading));
 
     /* Save before we change the pattern, colorspace, etc. so that
      * we can restore and make sure that quartz releases our
@@ -1452,7 +1452,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 				  solid->color.blue,
 				  solid->color.alpha);
 
-	surface->action = DO_SOLID;
+	surface->action = DO_DIRECT;
 	return CAIRO_STATUS_SUCCESS;
     }
 
@@ -1561,8 +1561,9 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	 */
 	CGContextSetPatternPhase (surface->cgContext, CGSizeMake (0, 0));
 
-	surface->sourcePattern = pattern;
-	surface->action = DO_PATTERN;
+	CGPatternRelease (pattern);
+
+	surface->action = DO_DIRECT;
 	return CAIRO_STATUS_SUCCESS;
     }
 
@@ -1587,11 +1588,6 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
 	CGShadingRelease (surface->sourceShading);
 	surface->sourceShading = NULL;
     }
-
-    if (surface->sourcePattern) {
-	CGPatternRelease (surface->sourcePattern);
-	surface->sourcePattern = NULL;
-    }
 }
 
 static cairo_int_status_t
@@ -1999,7 +1995,7 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
+    if (surface->action == DO_DIRECT) {
 	CGContextFillRect (surface->cgContext, CGRectMake (surface->extents.x,
 							   surface->extents.y,
 							   surface->extents.width,
@@ -2082,7 +2078,7 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
     if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
 	path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
 
-    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
+    if (surface->action == DO_DIRECT) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextFillPath (surface->cgContext);
 	else
@@ -2236,7 +2232,7 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
     CGContextConcatCTM (surface->cgContext, strokeTransform);
 
-    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
+    if (surface->action == DO_DIRECT) {
 	CGContextStrokePath (surface->cgContext);
     } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
 	CGContextReplacePathWithStrokedPath (surface->cgContext);
@@ -2364,7 +2360,7 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
+    if (surface->action == DO_DIRECT) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
     } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE || surface->action == DO_SHADING) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
commit c22e75e9f6cb471c764af0d721ad07cdf30a3bad
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jul 28 19:03:13 2010 +0200

    quartz: Set operator when setting up source
    
    Share some code between the drawing functions by saving the state
    and setting the operator when setting up the source and by restoring
    the state during teardown.
    Based on a patch by Robert O'Callahan <robert at ocallahan.org>.
    See https://bugzilla.mozilla.org/show_bug.cgi?id=522859

diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 55bc84d..9a45c66 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -83,8 +83,6 @@ typedef struct cairo_quartz_surface {
 
     CGShadingRef sourceShading;
     CGPatternRef sourcePattern;
-
-    CGInterpolationQuality oldInterpolationQuality;
 } cairo_quartz_surface_t;
 
 typedef struct cairo_quartz_image_surface {
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index a76adee..4f111ad 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1417,12 +1417,25 @@ _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
 
 static cairo_int_status_t
 _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
+			    cairo_operator_t op,
 			    const cairo_pattern_t *source,
 			    const cairo_rectangle_int_t *extents)
 {
+    cairo_status_t status;
+
     assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
 
-    surface->oldInterpolationQuality = CGContextGetInterpolationQuality (surface->cgContext);
+    /* 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);
+
+    status = _cairo_quartz_surface_set_cairo_operator (surface, op);
+    if (unlikely (status))
+	return status;
+
     CGContextSetInterpolationQuality (surface->cgContext, _cairo_quartz_filter_to_quartz (source->filter));
 
     if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
@@ -1461,7 +1474,6 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *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;
@@ -1536,11 +1548,6 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	if (unlikely (status))
 	    return status;
 
-	// 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);
@@ -1566,7 +1573,7 @@ static void
 _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
 			       const cairo_pattern_t *source)
 {
-    CGContextSetInterpolationQuality (surface->cgContext, surface->oldInterpolationQuality);
+    CGContextRestoreGState (surface->cgContext);
 
     if (surface->sourceImage) {
 	CGImageRelease (surface->sourceImage);
@@ -1583,21 +1590,19 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
 
     if (surface->sourcePattern) {
 	CGPatternRelease (surface->sourcePattern);
-	// To tear down the pattern and colorspace
-	CGContextRestoreGState (surface->cgContext);
-
 	surface->sourcePattern = NULL;
     }
 }
 
 static cairo_int_status_t
 _cairo_quartz_setup_source_safe (cairo_quartz_surface_t *surface,
+				 cairo_operator_t op,
 				 const cairo_pattern_t *source,
 				 const cairo_rectangle_int_t *extents)
 {
     cairo_int_status_t status;
 
-    status = _cairo_quartz_setup_source (surface, source, extents);
+    status = _cairo_quartz_setup_source (surface, op, source, extents);
     if (unlikely (status))
 	_cairo_quartz_teardown_source (surface, source);
 
@@ -1986,15 +1991,11 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-    if (unlikely (rv))
-	return rv;
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
@@ -2004,14 +2005,10 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
 							   surface->extents.width,
 							   surface->extents.height));
     } else if (surface->action == DO_SHADING) {
-	CGContextSaveGState (surface->cgContext);
 	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-	CGContextRestoreGState (surface->cgContext);
     } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
-	CGContextSaveGState (surface->cgContext);
 	_cairo_quartz_draw_image (surface, op);
-	CGContextRestoreGState (surface->cgContext);
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2070,20 +2067,14 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-    if (unlikely (rv))
-	return rv;
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
-    CGContextSaveGState (surface->cgContext);
-
     CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
 
     _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
@@ -2118,8 +2109,6 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 
     _cairo_quartz_teardown_source (surface, source);
 
-    CGContextRestoreGState (surface->cgContext);
-
     if (path_for_unbounded) {
 	unbounded_op_data_t ub;
 	ub.op = UNBOUNDED_STROKE_FILL;
@@ -2197,10 +2186,6 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-    if (unlikely (rv))
-	return rv;
-
     // 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.
@@ -2239,12 +2224,10 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
-    CGContextSaveGState (surface->cgContext);
-
     _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
 
     if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
@@ -2273,8 +2256,6 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
 
     _cairo_quartz_teardown_source (surface, source);
 
-    CGContextRestoreGState (surface->cgContext);
-
     if (path_for_unbounded) {
 	unbounded_op_data_t ub;
 	ub.op = UNBOUNDED_STROKE_FILL;
@@ -2375,20 +2356,14 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    rv = _cairo_quartz_surface_set_cairo_operator (surface, op);
-    if (unlikely (rv))
-	return rv;
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, op, source, &extents);
     if (unlikely (rv))
 	return rv;
 
-    CGContextSaveGState (surface->cgContext);
-
     if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
     } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE || surface->action == DO_SHADING) {
@@ -2488,8 +2463,6 @@ BAIL:
     if (didForceFontSmoothing)
 	CGContextSetAllowsFontSmoothingPtr (surface->cgContext, FALSE);
 
-    CGContextRestoreGState (surface->cgContext);
-
     if (rv == CAIRO_STATUS_SUCCESS &&
 	cgfref &&
 	!_cairo_operator_bounded_by_mask (op))
commit 6bc1376cf52a9815b75f8c0ce66e149fbc64495e
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Fri Oct 8 09:49:51 2010 +0200

    quartz: Remove DO_NOTHING and DO_UNSUPPORTED actions
    
    DO_NOTHING and DO_UNSUPPORTED are not actual actions and are better
    handled by returning an appropriate cairo_int_status_t (and falling
    back, if needed).

diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 8401a82..55bc84d 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -50,6 +50,14 @@ typedef CGFloat cairo_quartz_float_t;
 typedef float cairo_quartz_float_t;
 #endif
 
+typedef enum {
+    DO_SOLID,
+    DO_SHADING,
+    DO_PATTERN,
+    DO_IMAGE,
+    DO_TILED_IMAGE
+} cairo_quartz_action_t;
+
 typedef struct cairo_quartz_surface {
     cairo_surface_t base;
 
@@ -66,6 +74,7 @@ typedef struct cairo_quartz_surface {
     /* These are stored while drawing operations are in place, set up
      * by quartz_setup_source() and quartz_finish_source()
      */
+    cairo_quartz_action_t action;
     CGAffineTransform sourceTransform;
 
     CGImageRef sourceImage;
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index ee2f150..a76adee 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1304,16 +1304,6 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     return CAIRO_STATUS_SUCCESS;
 }
 
-typedef enum {
-    DO_SOLID,
-    DO_SHADING,
-    DO_PATTERN,
-    DO_IMAGE,
-    DO_UNSUPPORTED,
-    DO_NOTHING,
-    DO_TILED_IMAGE
-} cairo_quartz_action_t;
-
 /*
 Quartz does not support repeating radients. We handle repeating gradients
 by manually extending the gradient and repeating color stops. We need to
@@ -1327,7 +1317,7 @@ 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 cairo_int_status_t
 _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
 				   const cairo_linear_pattern_t *lpat,
 				   const cairo_rectangle_int_t *extents)
@@ -1368,10 +1358,11 @@ _cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
     CGColorSpaceRelease (rgb);
     CGFunctionRelease (gradFunc);
 
-    return DO_SHADING;
+    surface->action = DO_SHADING;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_quartz_action_t
+static cairo_int_status_t
 _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
 				   const cairo_radial_pattern_t *rpat,
 				   const cairo_rectangle_int_t *extents)
@@ -1420,10 +1411,11 @@ _cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
     CGColorSpaceRelease (rgb);
     CGFunctionRelease (gradFunc);
 
-    return DO_SHADING;
+    surface->action = DO_SHADING;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_quartz_action_t
+static cairo_int_status_t
 _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 			    const cairo_pattern_t *source,
 			    const cairo_rectangle_int_t *extents)
@@ -1447,7 +1439,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 				  solid->color.blue,
 				  solid->color.alpha);
 
-	return DO_SOLID;
+	surface->action = DO_SOLID;
+	return CAIRO_STATUS_SUCCESS;
     }
 
     if (source->type == CAIRO_PATTERN_TYPE_LINEAR) {
@@ -1476,9 +1469,9 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 
 	status = _cairo_surface_to_cgimage (pat_surf, &img);
 	if (unlikely (status))
-	    return DO_UNSUPPORTED;
+	    return status;
 	if (unlikely (img == NULL))
-	    return DO_NOTHING;
+	    return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
 	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
 
@@ -1492,7 +1485,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 
 	if (source->extend == CAIRO_EXTEND_NONE) {
 	    surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
-	    return DO_IMAGE;
+	    surface->action = DO_IMAGE;
+	    return CAIRO_STATUS_SUCCESS;
 	}
 
 	/* Quartz seems to tile images at pixel-aligned regions only -- this
@@ -1525,8 +1519,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
 
 	    surface->sourceImageRect = srcRect;
-
-	    return DO_TILED_IMAGE;
+	    surface->action = DO_TILED_IMAGE;
+	    return CAIRO_STATUS_SUCCESS;
 	}
 
 	/* Fall through to generic SURFACE case */
@@ -1535,14 +1529,12 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
     if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_quartz_float_t patternAlpha = 1.0f;
 	CGColorSpaceRef patternSpace;
-	CGPatternRef pattern;
+	CGPatternRef pattern = NULL;
 	cairo_int_status_t status;
 
 	status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
-	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
-	    return DO_NOTHING;
 	if (unlikely (status))
-	    return DO_UNSUPPORTED;
+	    return status;
 
 	// Save before we change the pattern, colorspace, etc. so that
 	// we can restore and make sure that quartz releases our
@@ -1563,11 +1555,11 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	CGContextSetPatternPhase (surface->cgContext, CGSizeMake (0, 0));
 
 	surface->sourcePattern = pattern;
-
-	return DO_PATTERN;
+	surface->action = DO_PATTERN;
+	return CAIRO_STATUS_SUCCESS;
     }
 
-    return DO_UNSUPPORTED;
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
 static void
@@ -1598,17 +1590,30 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
     }
 }
 
+static cairo_int_status_t
+_cairo_quartz_setup_source_safe (cairo_quartz_surface_t *surface,
+				 const cairo_pattern_t *source,
+				 const cairo_rectangle_int_t *extents)
+{
+    cairo_int_status_t status;
+
+    status = _cairo_quartz_setup_source (surface, source, extents);
+    if (unlikely (status))
+	_cairo_quartz_teardown_source (surface, source);
+
+    return status;
+}
 
 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_surface_t *surface, cairo_operator_t op)
 {
-    assert (surface && surface->sourceImage && (action == DO_IMAGE || action == DO_TILED_IMAGE));
+    assert (surface && surface->sourceImage && (surface->action == DO_IMAGE || surface->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) {
+    if (surface->action == DO_IMAGE) {
 	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
 	if (!_cairo_operator_bounded_by_source (op)) {
 	    CGContextBeginPath (surface->cgContext);
@@ -1970,7 +1975,6 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
 				cairo_clip_t *clip)
 {
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_quartz_action_t action;
     cairo_rectangle_int_t extents;
 
     ND ((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type));
@@ -1990,24 +1994,24 @@ _cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    action = _cairo_quartz_setup_source (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    if (unlikely (rv))
+	return rv;
 
-    if (action == DO_SOLID || action == DO_PATTERN) {
+    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
 	CGContextFillRect (surface->cgContext, CGRectMake (surface->extents.x,
 							   surface->extents.y,
 							   surface->extents.width,
 							   surface->extents.height));
-    } else if (action == DO_SHADING) {
+    } else if (surface->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) {
+    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
 	CGContextSaveGState (surface->cgContext);
-	_cairo_quartz_draw_image (surface, op, action);
+	_cairo_quartz_draw_image (surface, op);
 	CGContextRestoreGState (surface->cgContext);
-    } else if (action != DO_NOTHING) {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2054,7 +2058,6 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 			       cairo_clip_t *clip)
 {
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_quartz_action_t action;
     CGPathRef path_for_unbounded = NULL;
     cairo_rectangle_int_t extents;
 
@@ -2071,27 +2074,29 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    CGContextSaveGState (surface->cgContext);
-
-    CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    action = _cairo_quartz_setup_source (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    if (unlikely (rv))
+	return rv;
+
+    CGContextSaveGState (surface->cgContext);
+
+    CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
 
     _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
 
     if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
 	path_for_unbounded = CGContextCopyPathPtr (surface->cgContext);
 
-    if (action == DO_SOLID || action == DO_PATTERN) {
+    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextFillPath (surface->cgContext);
 	else
 	    CGContextEOFillPath (surface->cgContext);
-    } else if (action == DO_SHADING) {
+    } else if (surface->action == DO_SHADING) {
 
 	// we have to clip and then paint the shading; we can't fill
 	// with the shading
@@ -2102,15 +2107,13 @@ _cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
 
 	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
+    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextClip (surface->cgContext);
 	else
 	    CGContextEOClip (surface->cgContext);
 
-	_cairo_quartz_draw_image (surface, op, action);
-    } else if (action != DO_NOTHING) {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
+	_cairo_quartz_draw_image (surface, op);
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2181,7 +2184,6 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
 				 cairo_clip_t *clip)
 {
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_quartz_action_t action;
     CGAffineTransform origCTM, strokeTransform;
     CGPathRef path_for_unbounded = NULL;
     cairo_rectangle_int_t extents;
@@ -2233,13 +2235,15 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     } else
 	CGContextSetLineDash (surface->cgContext, 0, NULL, 0);
 
-    CGContextSaveGState (surface->cgContext);
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    action = _cairo_quartz_setup_source (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    if (unlikely (rv))
+	return rv;
+
+    CGContextSaveGState (surface->cgContext);
 
     _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
 
@@ -2249,15 +2253,15 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
     _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
     CGContextConcatCTM (surface->cgContext, strokeTransform);
 
-    if (action == DO_SOLID || action == DO_PATTERN) {
+    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
 	CGContextStrokePath (surface->cgContext);
-    } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
+    } else if (surface->action == DO_IMAGE || surface->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) {
+	_cairo_quartz_draw_image (surface, op);
+    } else if (surface->action == DO_SHADING) {
 	CGContextReplacePathWithStrokedPath (surface->cgContext);
 	CGContextClip (surface->cgContext);
 
@@ -2265,8 +2269,6 @@ _cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
 
 	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
-    } else if (action != DO_NOTHING) {
-	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     _cairo_quartz_teardown_source (surface, source);
@@ -2353,7 +2355,6 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
 
     cairo_rectangle_int_t extents;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
-    cairo_quartz_action_t action;
     cairo_quartz_float_t xprev, yprev;
     int i;
     CGFontRef cgfref = NULL;
@@ -2378,23 +2379,21 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
     if (unlikely (rv))
 	return rv;
 
-    CGContextSaveGState (surface->cgContext);
-
     extents = surface->virtual_extents;
     extents.x -= surface->base.device_transform.x0;
     extents.y -= surface->base.device_transform.y0;
     _cairo_rectangle_union (&extents, &surface->extents);
-    action = _cairo_quartz_setup_source (surface, source, &extents);
+    rv = _cairo_quartz_setup_source_safe (surface, source, &extents);
+    if (unlikely (rv))
+	return rv;
+
+    CGContextSaveGState (surface->cgContext);
 
-    if (action == DO_SOLID || action == DO_PATTERN) {
+    if (surface->action == DO_SOLID || surface->action == DO_PATTERN) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-    } else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) {
+    } else if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE || surface->action == DO_SHADING) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
 	isClipping = TRUE;
-    } else {
-	if (action != DO_NOTHING)
-	    rv = CAIRO_INT_STATUS_UNSUPPORTED;
-	goto BAIL;
     }
 
     /* this doesn't addref */
@@ -2476,9 +2475,9 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
 
     CGContextSetCTM (surface->cgContext, ctm);
 
-    if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
-	_cairo_quartz_draw_image (surface, op, action);
-    } else if (action == DO_SHADING) {
+    if (surface->action == DO_IMAGE || surface->action == DO_TILED_IMAGE) {
+	_cairo_quartz_draw_image (surface, op);
+    } else if (surface->action == DO_SHADING) {
 	CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
     }


More information about the cairo-commit mailing list