Bumping manifests a=b2g-bump
[gecko.git] / gfx / cairo / quartz-refactor-surface-setup.patch
blob22e2d0ee18420f49180d2fefcf8139378a5169cd
1 From: Robert O'Callahan <robert@ocallahan.org>
2 Bug 593270. Part 1: Move surface setup code to a helper function. r=jrmuizel,a=joe
4 diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
5 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
6 +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
7 @@ -1455,16 +1455,147 @@ _cairo_quartz_setup_radial_source (cairo
8 extend, extend);
10 CGColorSpaceRelease(rgb);
11 CGFunctionRelease(gradFunc);
13 state->action = DO_SHADING;
16 +static void
17 +_cairo_quartz_setup_surface_source (cairo_quartz_surface_t *surface,
18 + const cairo_surface_pattern_t *spat,
19 + cairo_rectangle_int_t *extents,
20 + cairo_quartz_drawing_state_t *state)
22 + const cairo_pattern_t *source = &spat->base;
23 + CGContextRef context = state->context;
25 + if (source->extend == CAIRO_EXTEND_NONE ||
26 + (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
27 + {
28 + cairo_surface_t *pat_surf = spat->surface;
29 + CGImageRef img;
30 + cairo_matrix_t m = spat->base.matrix;
31 + cairo_rectangle_int_t extents;
32 + CGAffineTransform xform;
33 + CGRect srcRect;
34 + cairo_fixed_t fw, fh;
35 + cairo_bool_t is_bounded;
36 + cairo_status_t status;
38 + cairo_matrix_invert(&m);
39 + _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
41 + /* Draw nonrepeating CGLayer surface using DO_LAYER */
42 + if (source->extend == CAIRO_EXTEND_NONE ||
43 + (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
44 + cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
45 + if (quartz_surf->cgLayer) {
46 + state->imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
47 + state->layer = quartz_surf->cgLayer;
48 + state->action = DO_LAYER;
49 + return;
50 + }
51 + }
53 + status = _cairo_surface_to_cgimage (pat_surf, &img);
54 + if (status) {
55 + state->action = DO_UNSUPPORTED;
56 + return;
57 + }
58 + if (img == NULL) {
59 + state->action = DO_NOTHING;
60 + return;
61 + }
63 + /* XXXroc what is this for? */
64 + CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
66 + state->image = img;
68 + is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
69 + assert (is_bounded);
71 + if (source->extend == CAIRO_EXTEND_NONE) {
72 + state->imageRect = CGRectMake (0, 0, extents.width, extents.height);
73 + state->action = DO_IMAGE;
74 + return;
75 + }
77 + /* Quartz seems to tile images at pixel-aligned regions only -- this
78 + * leads to seams if the image doesn't end up scaling to fill the
79 + * space exactly. The CGPattern tiling approach doesn't have this
80 + * problem. Check if we're going to fill up the space (within some
81 + * epsilon), and if not, fall back to the CGPattern type.
82 + */
84 + xform = CGAffineTransformConcat (CGContextGetCTM (context),
85 + state->transform);
87 + srcRect = CGRectMake (0, 0, extents.width, extents.height);
88 + srcRect = CGRectApplyAffineTransform (srcRect, xform);
90 + fw = _cairo_fixed_from_double (srcRect.size.width);
91 + fh = _cairo_fixed_from_double (srcRect.size.height);
93 + if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
94 + (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
95 + {
96 + /* We're good to use DrawTiledImage, but ensure that
97 + * the math works out */
99 + srcRect.size.width = round(srcRect.size.width);
100 + srcRect.size.height = round(srcRect.size.height);
102 + xform = CGAffineTransformInvert (xform);
104 + srcRect = CGRectApplyAffineTransform (srcRect, xform);
106 + state->imageRect = srcRect;
107 + state->action = DO_TILED_IMAGE;
108 + return;
111 + /* Fall through to generic SURFACE case */
114 + CGFloat patternAlpha = 1.0f;
115 + CGColorSpaceRef patternSpace;
116 + CGPatternRef pattern;
117 + cairo_int_status_t status;
119 + status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
120 + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
121 + state->action = DO_NOTHING;
122 + return;
124 + if (status) {
125 + state->action = DO_UNSUPPORTED;
126 + return;
129 + patternSpace = CGColorSpaceCreatePattern (NULL);
130 + CGContextSetFillColorSpace (context, patternSpace);
131 + CGContextSetFillPattern (context, pattern, &patternAlpha);
132 + CGContextSetStrokeColorSpace (context, patternSpace);
133 + CGContextSetStrokePattern (context, pattern, &patternAlpha);
134 + CGColorSpaceRelease (patternSpace);
136 + /* Quartz likes to munge the pattern phase (as yet unexplained
137 + * why); force it to 0,0 as we've already baked in the correct
138 + * pattern translation into the pattern matrix
139 + */
140 + CGContextSetPatternPhase (context, CGSizeMake(0,0));
142 + state->pattern = pattern;
143 + state->action = DO_PATTERN;
144 + return;
148 * Call this before any operation that can modify the contents of a
149 * cairo_quartz_surface_t.
151 static void
152 _cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
154 if (surface->bitmapContextImage) {
155 @@ -1566,133 +1697,19 @@ _cairo_quartz_setup_state (cairo_quartz_
158 if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
159 const cairo_radial_pattern_t *rpat = (const cairo_radial_pattern_t *)source;
160 _cairo_quartz_setup_radial_source (surface, rpat, extents, &state);
161 return state;
164 - if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
165 - (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
167 + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
168 const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source;
169 - cairo_surface_t *pat_surf = spat->surface;
170 - CGImageRef img;
171 - cairo_matrix_t m = spat->base.matrix;
172 - cairo_rectangle_int_t extents;
173 - CGAffineTransform xform;
174 - CGRect srcRect;
175 - cairo_fixed_t fw, fh;
176 - cairo_bool_t is_bounded;
178 - cairo_matrix_invert(&m);
179 - _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
181 - if (cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
182 - cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
183 - if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) {
184 - state.imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
185 - state.layer = quartz_surf->cgLayer;
186 - state.action = DO_LAYER;
187 - return state;
191 - status = _cairo_surface_to_cgimage (pat_surf, &img);
192 - if (status) {
193 - state.action = DO_UNSUPPORTED;
194 - return state;
196 - if (img == NULL) {
197 - state.action = DO_NOTHING;
198 - return state;
201 - CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
203 - state.image = img;
205 - is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
206 - assert (is_bounded);
208 - if (source->extend == CAIRO_EXTEND_NONE) {
209 - state.imageRect = CGRectMake (0, 0, extents.width, extents.height);
210 - state.action = DO_IMAGE;
211 - return state;
214 - /* Quartz seems to tile images at pixel-aligned regions only -- this
215 - * leads to seams if the image doesn't end up scaling to fill the
216 - * space exactly. The CGPattern tiling approach doesn't have this
217 - * problem. Check if we're going to fill up the space (within some
218 - * epsilon), and if not, fall back to the CGPattern type.
219 - */
221 - xform = CGAffineTransformConcat (CGContextGetCTM (context),
222 - state.transform);
224 - srcRect = CGRectMake (0, 0, extents.width, extents.height);
225 - srcRect = CGRectApplyAffineTransform (srcRect, xform);
227 - fw = _cairo_fixed_from_double (srcRect.size.width);
228 - fh = _cairo_fixed_from_double (srcRect.size.height);
230 - if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
231 - (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
233 - /* We're good to use DrawTiledImage, but ensure that
234 - * the math works out */
236 - srcRect.size.width = round(srcRect.size.width);
237 - srcRect.size.height = round(srcRect.size.height);
239 - xform = CGAffineTransformInvert (xform);
241 - srcRect = CGRectApplyAffineTransform (srcRect, xform);
243 - state.imageRect = srcRect;
244 - state.action = DO_TILED_IMAGE;
245 - return state;
248 - /* Fall through to generic SURFACE case */
251 - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
252 - CGFloat patternAlpha = 1.0f;
253 - CGColorSpaceRef patternSpace;
254 - CGPatternRef pattern;
255 - cairo_int_status_t status;
257 - status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
258 - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
259 - state.action = DO_NOTHING;
260 - return state;
262 - if (status) {
263 - state.action = DO_UNSUPPORTED;
264 - return state;
267 - patternSpace = CGColorSpaceCreatePattern (NULL);
268 - CGContextSetFillColorSpace (context, patternSpace);
269 - CGContextSetFillPattern (context, pattern, &patternAlpha);
270 - CGContextSetStrokeColorSpace (context, patternSpace);
271 - CGContextSetStrokePattern (context, pattern, &patternAlpha);
272 - CGColorSpaceRelease (patternSpace);
274 - /* Quartz likes to munge the pattern phase (as yet unexplained
275 - * why); force it to 0,0 as we've already baked in the correct
276 - * pattern translation into the pattern matrix
277 - */
278 - CGContextSetPatternPhase (context, CGSizeMake(0,0));
280 - state.pattern = pattern;
281 - state.action = DO_PATTERN;
282 + _cairo_quartz_setup_surface_source (surface, spat, extents, &state);
283 return state;
286 state.action = DO_UNSUPPORTED;
287 return state;