summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/quartz-refactor-surface-setup.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/quartz-refactor-surface-setup.patch')
-rw-r--r--gfx/cairo/quartz-refactor-surface-setup.patch290
1 files changed, 290 insertions, 0 deletions
diff --git a/gfx/cairo/quartz-refactor-surface-setup.patch b/gfx/cairo/quartz-refactor-surface-setup.patch
new file mode 100644
index 0000000000..22e2d0ee18
--- /dev/null
+++ b/gfx/cairo/quartz-refactor-surface-setup.patch
@@ -0,0 +1,290 @@
+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;
+ }
+
+ /**