gfx/cairo/quartz-refactor-surface-setup.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/quartz-refactor-surface-setup.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,290 @@
     1.4 +From: Robert O'Callahan <robert@ocallahan.org>
     1.5 +Bug 593270. Part 1: Move surface setup code to a helper function. r=jrmuizel,a=joe
     1.6 +
     1.7 +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
     1.8 +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
     1.9 ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
    1.10 +@@ -1455,16 +1455,147 @@ _cairo_quartz_setup_radial_source (cairo
    1.11 + 					    extend, extend);
    1.12 + 
    1.13 +     CGColorSpaceRelease(rgb);
    1.14 +     CGFunctionRelease(gradFunc);
    1.15 + 
    1.16 +     state->action = DO_SHADING;
    1.17 + }
    1.18 + 
    1.19 ++static void
    1.20 ++_cairo_quartz_setup_surface_source (cairo_quartz_surface_t *surface,
    1.21 ++				    const cairo_surface_pattern_t *spat,
    1.22 ++				    cairo_rectangle_int_t *extents,
    1.23 ++				    cairo_quartz_drawing_state_t *state)
    1.24 ++{
    1.25 ++    const cairo_pattern_t *source = &spat->base;
    1.26 ++    CGContextRef context = state->context;
    1.27 ++
    1.28 ++    if (source->extend == CAIRO_EXTEND_NONE ||
    1.29 ++        (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
    1.30 ++    {
    1.31 ++	cairo_surface_t *pat_surf = spat->surface;
    1.32 ++	CGImageRef img;
    1.33 ++	cairo_matrix_t m = spat->base.matrix;
    1.34 ++	cairo_rectangle_int_t extents;
    1.35 ++	CGAffineTransform xform;
    1.36 ++	CGRect srcRect;
    1.37 ++	cairo_fixed_t fw, fh;
    1.38 ++	cairo_bool_t is_bounded;
    1.39 ++        cairo_status_t status;
    1.40 ++
    1.41 ++        cairo_matrix_invert(&m);
    1.42 ++        _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
    1.43 ++
    1.44 ++        /* Draw nonrepeating CGLayer surface using DO_LAYER */
    1.45 ++        if (source->extend == CAIRO_EXTEND_NONE ||
    1.46 ++            (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))
    1.47 ++            cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
    1.48 ++            if (quartz_surf->cgLayer) {
    1.49 ++         	state->imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
    1.50 ++                state->layer = quartz_surf->cgLayer;
    1.51 ++                state->action = DO_LAYER;
    1.52 ++                return;
    1.53 ++            }
    1.54 ++        }
    1.55 ++
    1.56 ++	status = _cairo_surface_to_cgimage (pat_surf, &img);
    1.57 ++        if (status) {
    1.58 ++            state->action = DO_UNSUPPORTED;
    1.59 ++	    return;
    1.60 ++        }
    1.61 ++        if (img == NULL) {
    1.62 ++            state->action = DO_NOTHING;
    1.63 ++	    return;
    1.64 ++        }
    1.65 ++
    1.66 ++        /* XXXroc what is this for? */
    1.67 ++	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
    1.68 ++
    1.69 ++	state->image = img;
    1.70 ++
    1.71 ++	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
    1.72 ++	assert (is_bounded);
    1.73 ++
    1.74 ++	if (source->extend == CAIRO_EXTEND_NONE) {
    1.75 ++	    state->imageRect = CGRectMake (0, 0, extents.width, extents.height);
    1.76 ++	    state->action = DO_IMAGE;
    1.77 ++	    return;
    1.78 ++	}
    1.79 ++
    1.80 ++	/* Quartz seems to tile images at pixel-aligned regions only -- this
    1.81 ++	 * leads to seams if the image doesn't end up scaling to fill the
    1.82 ++	 * space exactly.  The CGPattern tiling approach doesn't have this
    1.83 ++	 * problem.  Check if we're going to fill up the space (within some
    1.84 ++	 * epsilon), and if not, fall back to the CGPattern type.
    1.85 ++	 */
    1.86 ++
    1.87 ++	xform = CGAffineTransformConcat (CGContextGetCTM (context),
    1.88 ++					 state->transform);
    1.89 ++
    1.90 ++	srcRect = CGRectMake (0, 0, extents.width, extents.height);
    1.91 ++	srcRect = CGRectApplyAffineTransform (srcRect, xform);
    1.92 ++
    1.93 ++	fw = _cairo_fixed_from_double (srcRect.size.width);
    1.94 ++	fh = _cairo_fixed_from_double (srcRect.size.height);
    1.95 ++
    1.96 ++	if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
    1.97 ++	    (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
    1.98 ++	{
    1.99 ++	    /* We're good to use DrawTiledImage, but ensure that
   1.100 ++	     * the math works out */
   1.101 ++
   1.102 ++	    srcRect.size.width = round(srcRect.size.width);
   1.103 ++	    srcRect.size.height = round(srcRect.size.height);
   1.104 ++
   1.105 ++	    xform = CGAffineTransformInvert (xform);
   1.106 ++
   1.107 ++	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
   1.108 ++
   1.109 ++	    state->imageRect = srcRect;
   1.110 ++            state->action = DO_TILED_IMAGE;
   1.111 ++            return;
   1.112 ++	}
   1.113 ++
   1.114 ++	/* Fall through to generic SURFACE case */
   1.115 ++    }
   1.116 ++
   1.117 ++    CGFloat patternAlpha = 1.0f;
   1.118 ++    CGColorSpaceRef patternSpace;
   1.119 ++    CGPatternRef pattern;
   1.120 ++    cairo_int_status_t status;
   1.121 ++
   1.122 ++    status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
   1.123 ++    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
   1.124 ++        state->action = DO_NOTHING;
   1.125 ++	return;
   1.126 ++    }
   1.127 ++    if (status) {
   1.128 ++	state->action = DO_UNSUPPORTED;
   1.129 ++	return;
   1.130 ++    }
   1.131 ++
   1.132 ++    patternSpace = CGColorSpaceCreatePattern (NULL);
   1.133 ++    CGContextSetFillColorSpace (context, patternSpace);
   1.134 ++    CGContextSetFillPattern (context, pattern, &patternAlpha);
   1.135 ++    CGContextSetStrokeColorSpace (context, patternSpace); 
   1.136 ++    CGContextSetStrokePattern (context, pattern, &patternAlpha);
   1.137 ++    CGColorSpaceRelease (patternSpace);
   1.138 ++
   1.139 ++    /* Quartz likes to munge the pattern phase (as yet unexplained
   1.140 ++     * why); force it to 0,0 as we've already baked in the correct
   1.141 ++     * pattern translation into the pattern matrix
   1.142 ++     */
   1.143 ++    CGContextSetPatternPhase (context, CGSizeMake(0,0));
   1.144 ++
   1.145 ++    state->pattern = pattern;
   1.146 ++    state->action = DO_PATTERN;
   1.147 ++    return;
   1.148 ++}
   1.149 ++
   1.150 + /**
   1.151 +  * Call this before any operation that can modify the contents of a
   1.152 +  * cairo_quartz_surface_t.
   1.153 +  */
   1.154 + static void
   1.155 + _cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
   1.156 + {
   1.157 +     if (surface->bitmapContextImage) {
   1.158 +@@ -1566,133 +1697,19 @@ _cairo_quartz_setup_state (cairo_quartz_
   1.159 +     }
   1.160 + 
   1.161 +     if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
   1.162 + 	const cairo_radial_pattern_t *rpat = (const cairo_radial_pattern_t *)source;
   1.163 + 	_cairo_quartz_setup_radial_source (surface, rpat, extents, &state);
   1.164 + 	return state;
   1.165 +     }
   1.166 + 
   1.167 +-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
   1.168 +-	(source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
   1.169 +-    {
   1.170 ++    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
   1.171 + 	const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source;
   1.172 +-	cairo_surface_t *pat_surf = spat->surface;
   1.173 +-	CGImageRef img;
   1.174 +-	cairo_matrix_t m = spat->base.matrix;
   1.175 +-	cairo_rectangle_int_t extents;
   1.176 +-	CGAffineTransform xform;
   1.177 +-	CGRect srcRect;
   1.178 +-	cairo_fixed_t fw, fh;
   1.179 +-	cairo_bool_t is_bounded;
   1.180 +-
   1.181 +-        cairo_matrix_invert(&m);
   1.182 +-        _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
   1.183 +-
   1.184 +-        if (cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
   1.185 +-            cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
   1.186 +-            if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) {
   1.187 +-         	state.imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
   1.188 +-                state.layer = quartz_surf->cgLayer;
   1.189 +-                state.action = DO_LAYER;
   1.190 +-                return state;
   1.191 +-            }
   1.192 +-        }
   1.193 +-
   1.194 +-	status = _cairo_surface_to_cgimage (pat_surf, &img);
   1.195 +-        if (status) {
   1.196 +-            state.action = DO_UNSUPPORTED;
   1.197 +-	    return state;
   1.198 +-        }
   1.199 +-        if (img == NULL) {
   1.200 +-            state.action = DO_NOTHING;
   1.201 +-	    return state;
   1.202 +-        }
   1.203 +-
   1.204 +-	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
   1.205 +-
   1.206 +-	state.image = img;
   1.207 +-
   1.208 +-	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
   1.209 +-	assert (is_bounded);
   1.210 +-
   1.211 +-	if (source->extend == CAIRO_EXTEND_NONE) {
   1.212 +-	    state.imageRect = CGRectMake (0, 0, extents.width, extents.height);
   1.213 +-	    state.action = DO_IMAGE;
   1.214 +-	    return state;
   1.215 +-	}
   1.216 +-
   1.217 +-	/* Quartz seems to tile images at pixel-aligned regions only -- this
   1.218 +-	 * leads to seams if the image doesn't end up scaling to fill the
   1.219 +-	 * space exactly.  The CGPattern tiling approach doesn't have this
   1.220 +-	 * problem.  Check if we're going to fill up the space (within some
   1.221 +-	 * epsilon), and if not, fall back to the CGPattern type.
   1.222 +-	 */
   1.223 +-
   1.224 +-	xform = CGAffineTransformConcat (CGContextGetCTM (context),
   1.225 +-					 state.transform);
   1.226 +-
   1.227 +-	srcRect = CGRectMake (0, 0, extents.width, extents.height);
   1.228 +-	srcRect = CGRectApplyAffineTransform (srcRect, xform);
   1.229 +-
   1.230 +-	fw = _cairo_fixed_from_double (srcRect.size.width);
   1.231 +-	fh = _cairo_fixed_from_double (srcRect.size.height);
   1.232 +-
   1.233 +-	if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
   1.234 +-	    (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
   1.235 +-	{
   1.236 +-	    /* We're good to use DrawTiledImage, but ensure that
   1.237 +-	     * the math works out */
   1.238 +-
   1.239 +-	    srcRect.size.width = round(srcRect.size.width);
   1.240 +-	    srcRect.size.height = round(srcRect.size.height);
   1.241 +-
   1.242 +-	    xform = CGAffineTransformInvert (xform);
   1.243 +-
   1.244 +-	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
   1.245 +-
   1.246 +-	    state.imageRect = srcRect;
   1.247 +-            state.action = DO_TILED_IMAGE;
   1.248 +-            return state;
   1.249 +-	}
   1.250 +-
   1.251 +-	/* Fall through to generic SURFACE case */
   1.252 +-    }
   1.253 +-
   1.254 +-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
   1.255 +-	CGFloat patternAlpha = 1.0f;
   1.256 +-	CGColorSpaceRef patternSpace;
   1.257 +-	CGPatternRef pattern;
   1.258 +-	cairo_int_status_t status;
   1.259 +-
   1.260 +-	status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
   1.261 +-	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
   1.262 +-	    state.action = DO_NOTHING;
   1.263 +-	    return state;
   1.264 +-	}
   1.265 +-	if (status) {
   1.266 +-	    state.action = DO_UNSUPPORTED;
   1.267 +-	    return state;
   1.268 +-	}
   1.269 +-
   1.270 +-	patternSpace = CGColorSpaceCreatePattern (NULL);
   1.271 +-	CGContextSetFillColorSpace (context, patternSpace);
   1.272 +-	CGContextSetFillPattern (context, pattern, &patternAlpha);
   1.273 +-	CGContextSetStrokeColorSpace (context, patternSpace); 
   1.274 +-	CGContextSetStrokePattern (context, pattern, &patternAlpha);
   1.275 +-	CGColorSpaceRelease (patternSpace);
   1.276 +-
   1.277 +-	/* Quartz likes to munge the pattern phase (as yet unexplained
   1.278 +-	 * why); force it to 0,0 as we've already baked in the correct
   1.279 +-	 * pattern translation into the pattern matrix
   1.280 +-	 */
   1.281 +-	CGContextSetPatternPhase (context, CGSizeMake(0,0));
   1.282 +-
   1.283 +-	state.pattern = pattern;
   1.284 +-        state.action = DO_PATTERN;
   1.285 ++        _cairo_quartz_setup_surface_source (surface, spat, extents, &state);
   1.286 +         return state;
   1.287 +     }
   1.288 + 
   1.289 +     state.action = DO_UNSUPPORTED;
   1.290 +     return state;
   1.291 + }
   1.292 + 
   1.293 + /**

mercurial