Skip to content

Commit

Permalink
quartz: Set operator when setting up source
Browse files Browse the repository at this point in the history
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@ocallahan.org>.
See https://bugzilla.mozilla.org/show_bug.cgi?id=522859
  • Loading branch information
Andrea Canciani committed Oct 12, 2010
1 parent 6bc1376 commit c22e75e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 50 deletions.
2 changes: 0 additions & 2 deletions src/cairo-quartz-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
69 changes: 21 additions & 48 deletions src/cairo-quartz-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -2488,8 +2463,6 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
if (didForceFontSmoothing)
CGContextSetAllowsFontSmoothingPtr (surface->cgContext, FALSE);

CGContextRestoreGState (surface->cgContext);

if (rv == CAIRO_STATUS_SUCCESS &&
cgfref &&
!_cairo_operator_bounded_by_mask (op))
Expand Down

0 comments on commit c22e75e

Please sign in to comment.