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

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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;
    14  }
    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)
    21 +{
    22 +    const cairo_pattern_t *source = &spat->base;
    23 +    CGContextRef context = state->context;
    24 +
    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;
    37 +
    38 +        cairo_matrix_invert(&m);
    39 +        _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
    40 +
    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 +        }
    52 +
    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 +        }
    62 +
    63 +        /* XXXroc what is this for? */
    64 +	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
    65 +
    66 +	state->image = img;
    67 +
    68 +	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
    69 +	assert (is_bounded);
    70 +
    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 +	}
    76 +
    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 +	 */
    83 +
    84 +	xform = CGAffineTransformConcat (CGContextGetCTM (context),
    85 +					 state->transform);
    86 +
    87 +	srcRect = CGRectMake (0, 0, extents.width, extents.height);
    88 +	srcRect = CGRectApplyAffineTransform (srcRect, xform);
    89 +
    90 +	fw = _cairo_fixed_from_double (srcRect.size.width);
    91 +	fh = _cairo_fixed_from_double (srcRect.size.height);
    92 +
    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 */
    98 +
    99 +	    srcRect.size.width = round(srcRect.size.width);
   100 +	    srcRect.size.height = round(srcRect.size.height);
   101 +
   102 +	    xform = CGAffineTransformInvert (xform);
   103 +
   104 +	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
   105 +
   106 +	    state->imageRect = srcRect;
   107 +            state->action = DO_TILED_IMAGE;
   108 +            return;
   109 +	}
   110 +
   111 +	/* Fall through to generic SURFACE case */
   112 +    }
   113 +
   114 +    CGFloat patternAlpha = 1.0f;
   115 +    CGColorSpaceRef patternSpace;
   116 +    CGPatternRef pattern;
   117 +    cairo_int_status_t status;
   118 +
   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;
   123 +    }
   124 +    if (status) {
   125 +	state->action = DO_UNSUPPORTED;
   126 +	return;
   127 +    }
   128 +
   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);
   135 +
   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));
   141 +
   142 +    state->pattern = pattern;
   143 +    state->action = DO_PATTERN;
   144 +    return;
   145 +}
   146 +
   147  /**
   148   * Call this before any operation that can modify the contents of a
   149   * cairo_quartz_surface_t.
   150   */
   151  static void
   152  _cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
   153  {
   154      if (surface->bitmapContextImage) {
   155 @@ -1566,133 +1697,19 @@ _cairo_quartz_setup_state (cairo_quartz_
   156      }
   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;
   162      }
   164 -    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
   165 -	(source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
   166 -    {
   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;
   177 -
   178 -        cairo_matrix_invert(&m);
   179 -        _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
   180 -
   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;
   188 -            }
   189 -        }
   190 -
   191 -	status = _cairo_surface_to_cgimage (pat_surf, &img);
   192 -        if (status) {
   193 -            state.action = DO_UNSUPPORTED;
   194 -	    return state;
   195 -        }
   196 -        if (img == NULL) {
   197 -            state.action = DO_NOTHING;
   198 -	    return state;
   199 -        }
   200 -
   201 -	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
   202 -
   203 -	state.image = img;
   204 -
   205 -	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
   206 -	assert (is_bounded);
   207 -
   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;
   212 -	}
   213 -
   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 -	 */
   220 -
   221 -	xform = CGAffineTransformConcat (CGContextGetCTM (context),
   222 -					 state.transform);
   223 -
   224 -	srcRect = CGRectMake (0, 0, extents.width, extents.height);
   225 -	srcRect = CGRectApplyAffineTransform (srcRect, xform);
   226 -
   227 -	fw = _cairo_fixed_from_double (srcRect.size.width);
   228 -	fh = _cairo_fixed_from_double (srcRect.size.height);
   229 -
   230 -	if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
   231 -	    (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
   232 -	{
   233 -	    /* We're good to use DrawTiledImage, but ensure that
   234 -	     * the math works out */
   235 -
   236 -	    srcRect.size.width = round(srcRect.size.width);
   237 -	    srcRect.size.height = round(srcRect.size.height);
   238 -
   239 -	    xform = CGAffineTransformInvert (xform);
   240 -
   241 -	    srcRect = CGRectApplyAffineTransform (srcRect, xform);
   242 -
   243 -	    state.imageRect = srcRect;
   244 -            state.action = DO_TILED_IMAGE;
   245 -            return state;
   246 -	}
   247 -
   248 -	/* Fall through to generic SURFACE case */
   249 -    }
   250 -
   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;
   256 -
   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;
   261 -	}
   262 -	if (status) {
   263 -	    state.action = DO_UNSUPPORTED;
   264 -	    return state;
   265 -	}
   266 -
   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);
   273 -
   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));
   279 -
   280 -	state.pattern = pattern;
   281 -        state.action = DO_PATTERN;
   282 +        _cairo_quartz_setup_surface_source (surface, spat, extents, &state);
   283          return state;
   284      }
   286      state.action = DO_UNSUPPORTED;
   287      return state;
   288  }
   290  /**

mercurial