diff options
Diffstat (limited to 'gfx/cairo/quartz-state.patch')
-rw-r--r-- | gfx/cairo/quartz-state.patch | 1190 |
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; - |