pjs/gfx/cairo/quartz-refactor-surface-set...

291 строка
9.5 KiB
Diff

From: Robert O'Callahan <robert@ocallahan.org>
Bug 593270. Part 1: Move surface setup code to a helper function. r=jrmuizel,a=joe
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
@@ -1455,16 +1455,147 @@ _cairo_quartz_setup_radial_source (cairo
extend, extend);
CGColorSpaceRelease(rgb);
CGFunctionRelease(gradFunc);
state->action = DO_SHADING;
}
+static void
+_cairo_quartz_setup_surface_source (cairo_quartz_surface_t *surface,
+ const cairo_surface_pattern_t *spat,
+ cairo_rectangle_int_t *extents,
+ cairo_quartz_drawing_state_t *state)
+{
+ const cairo_pattern_t *source = &spat->base;
+ CGContextRef context = state->context;
+
+ if (source->extend == CAIRO_EXTEND_NONE ||
+ (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
+ {
+ cairo_surface_t *pat_surf = spat->surface;
+ CGImageRef img;
+ cairo_matrix_t m = spat->base.matrix;
+ cairo_rectangle_int_t extents;
+ CGAffineTransform xform;
+ CGRect srcRect;
+ cairo_fixed_t fw, fh;
+ cairo_bool_t is_bounded;
+ cairo_status_t status;
+
+ cairo_matrix_invert(&m);
+ _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
+
+ /* Draw nonrepeating CGLayer surface using DO_LAYER */
+ if (source->extend == CAIRO_EXTEND_NONE ||
+ (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
+ cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
+ if (quartz_surf->cgLayer) {
+ state->imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
+ state->layer = quartz_surf->cgLayer;
+ state->action = DO_LAYER;
+ return;
+ }
+ }
+
+ status = _cairo_surface_to_cgimage (pat_surf, &img);
+ if (status) {
+ state->action = DO_UNSUPPORTED;
+ return;
+ }
+ if (img == NULL) {
+ state->action = DO_NOTHING;
+ return;
+ }
+
+ /* XXXroc what is this for? */
+ CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
+
+ state->image = img;
+
+ is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
+ assert (is_bounded);
+
+ if (source->extend == CAIRO_EXTEND_NONE) {
+ state->imageRect = CGRectMake (0, 0, extents.width, extents.height);
+ state->action = DO_IMAGE;
+ return;
+ }
+
+ /* Quartz seems to tile images at pixel-aligned regions only -- this
+ * 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 (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 &&
+ (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
+ {
+ /* We're good to use DrawTiledImage, but ensure that
+ * the math works out */
+
+ srcRect.size.width = round(srcRect.size.width);
+ srcRect.size.height = round(srcRect.size.height);
+
+ xform = CGAffineTransformInvert (xform);
+
+ srcRect = CGRectApplyAffineTransform (srcRect, xform);
+
+ state->imageRect = srcRect;
+ state->action = DO_TILED_IMAGE;
+ return;
+ }
+
+ /* Fall through to generic SURFACE case */
+ }
+
+ 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) {
+ state->action = DO_NOTHING;
+ return;
+ }
+ if (status) {
+ state->action = DO_UNSUPPORTED;
+ return;
+ }
+
+ patternSpace = CGColorSpaceCreatePattern (NULL);
+ CGContextSetFillColorSpace (context, patternSpace);
+ CGContextSetFillPattern (context, pattern, &patternAlpha);
+ CGContextSetStrokeColorSpace (context, patternSpace);
+ CGContextSetStrokePattern (context, pattern, &patternAlpha);
+ CGColorSpaceRelease (patternSpace);
+
+ /* Quartz likes to munge the pattern phase (as yet unexplained
+ * why); force it to 0,0 as we've already baked in the correct
+ * pattern translation into the pattern matrix
+ */
+ CGContextSetPatternPhase (context, CGSizeMake(0,0));
+
+ state->pattern = pattern;
+ state->action = DO_PATTERN;
+ return;
+}
+
/**
* Call this before any operation that can modify the contents of a
* cairo_quartz_surface_t.
*/
static void
_cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
{
if (surface->bitmapContextImage) {
@@ -1566,133 +1697,19 @@ _cairo_quartz_setup_state (cairo_quartz_
}
if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
const cairo_radial_pattern_t *rpat = (const cairo_radial_pattern_t *)source;
_cairo_quartz_setup_radial_source (surface, rpat, extents, &state);
return state;
}
- if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
- (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
- {
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
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;
- CGAffineTransform xform;
- CGRect srcRect;
- cairo_fixed_t fw, fh;
- cairo_bool_t is_bounded;
-
- cairo_matrix_invert(&m);
- _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
-
- if (cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
- cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
- if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) {
- state.imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
- state.layer = quartz_surf->cgLayer;
- state.action = DO_LAYER;
- return state;
- }
- }
-
- status = _cairo_surface_to_cgimage (pat_surf, &img);
- if (status) {
- state.action = DO_UNSUPPORTED;
- return state;
- }
- if (img == NULL) {
- state.action = DO_NOTHING;
- return state;
- }
-
- CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
-
- state.image = img;
-
- is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
- assert (is_bounded);
-
- if (source->extend == CAIRO_EXTEND_NONE) {
- 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 (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 &&
- (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
- {
- /* We're good to use DrawTiledImage, but ensure that
- * the math works out */
-
- srcRect.size.width = round(srcRect.size.width);
- srcRect.size.height = round(srcRect.size.height);
-
- xform = CGAffineTransformInvert (xform);
-
- srcRect = CGRectApplyAffineTransform (srcRect, xform);
-
- 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) {
- 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 (context, CGSizeMake(0,0));
-
- state.pattern = pattern;
- state.action = DO_PATTERN;
+ _cairo_quartz_setup_surface_source (surface, spat, extents, &state);
return state;
}
state.action = DO_UNSUPPORTED;
return state;
}
/**