gfx/cairo/quartz-cglayers.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/quartz-cglayers.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,715 @@
     1.4 +changeset:   42959:e1964291f8ff
     1.5 +user:        Robert O'Callahan <robert@ocallahan.org>
     1.6 +date:        Tue Jun 01 11:33:23 2010 +1200
     1.7 +summary:     Bug 568189. Implement CGLayer-backed cairo-quartz surfaces. r=jrmuizel
     1.8 +
     1.9 +diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
    1.10 +--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
    1.11 ++++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
    1.12 +@@ -57,16 +57,21 @@ typedef struct cairo_quartz_surface {
    1.13 + 
    1.14 +     /**
    1.15 +      * If non-null, this is a CGImage representing the contents of the surface.
    1.16 +      * We clear this out before any painting into the surface, so that we
    1.17 +      * don't force a copy to be created.
    1.18 +      */
    1.19 +     CGImageRef bitmapContextImage;
    1.20 + 
    1.21 ++    /**
    1.22 ++     * If non-null, this is the CGLayer for the surface.
    1.23 ++     */
    1.24 ++    CGLayerRef cgLayer;
    1.25 ++
    1.26 +     cairo_rectangle_int_t extents;
    1.27 + } cairo_quartz_surface_t;
    1.28 + 
    1.29 + typedef struct cairo_quartz_image_surface {
    1.30 +     cairo_surface_t base;
    1.31 + 
    1.32 +     cairo_rectangle_int_t extents;
    1.33 + 
    1.34 +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
    1.35 +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
    1.36 ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
    1.37 +@@ -1110,18 +1110,17 @@ CreateRepeatingRadialGradientFunction (c
    1.38 + static void
    1.39 + DataProviderReleaseCallback (void *info, const void *data, size_t size)
    1.40 + {
    1.41 +     cairo_surface_t *surface = (cairo_surface_t *) info;
    1.42 +     cairo_surface_destroy (surface);
    1.43 + }
    1.44 + 
    1.45 + static cairo_status_t
    1.46 +-_cairo_surface_to_cgimage (cairo_surface_t *target,
    1.47 +-			   cairo_surface_t *source,
    1.48 ++_cairo_surface_to_cgimage (cairo_surface_t *source,
    1.49 + 			   CGImageRef *image_out)
    1.50 + {
    1.51 +     cairo_status_t status = CAIRO_STATUS_SUCCESS;
    1.52 +     cairo_surface_type_t stype = cairo_surface_get_type (source);
    1.53 +     cairo_image_surface_t *isurf;
    1.54 +     CGImageRef image;
    1.55 +     void *image_extra;
    1.56 + 
    1.57 +@@ -1267,17 +1266,17 @@ _cairo_quartz_cairo_repeating_surface_pa
    1.58 + 	return CAIRO_INT_STATUS_UNSUPPORTED;
    1.59 + 
    1.60 +     spattern = (cairo_surface_pattern_t *) apattern;
    1.61 +     pat_surf = spattern->surface;
    1.62 + 
    1.63 +     is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
    1.64 +     assert (is_bounded);
    1.65 + 
    1.66 +-    status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image);
    1.67 ++    status = _cairo_surface_to_cgimage (pat_surf, &image);
    1.68 +     if (status)
    1.69 + 	return status;
    1.70 +     if (image == NULL)
    1.71 + 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    1.72 + 
    1.73 +     info = malloc(sizeof(SurfacePatternDrawInfo));
    1.74 +     if (!info)
    1.75 + 	return CAIRO_STATUS_NO_MEMORY;
    1.76 +@@ -1339,33 +1338,39 @@ _cairo_quartz_cairo_repeating_surface_pa
    1.77 + }
    1.78 + 
    1.79 + typedef enum {
    1.80 +     DO_SOLID,
    1.81 +     DO_SHADING,
    1.82 +     DO_PATTERN,
    1.83 +     DO_IMAGE,
    1.84 +     DO_TILED_IMAGE,
    1.85 ++    DO_LAYER,
    1.86 +     DO_UNSUPPORTED,
    1.87 +     DO_NOTHING
    1.88 + } cairo_quartz_action_t;
    1.89 + 
    1.90 + /* State used during a drawing operation. */
    1.91 + typedef struct {
    1.92 +     CGContextRef context;
    1.93 +     cairo_quartz_action_t action;
    1.94 + 
    1.95 +-    // Used with DO_SHADING, DO_IMAGE and DO_TILED_IMAGE
    1.96 ++    // Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
    1.97 +     CGAffineTransform transform;
    1.98 + 
    1.99 +     // Used with DO_IMAGE and DO_TILED_IMAGE
   1.100 +     CGImageRef image;
   1.101 +     cairo_surface_t *imageSurface;
   1.102 ++
   1.103 ++    // Used with DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
   1.104 +     CGRect imageRect;
   1.105 + 
   1.106 ++    // Used with DO_LAYER
   1.107 ++    CGLayerRef layer;
   1.108 ++
   1.109 +     // Used with DO_SHADING
   1.110 +     CGShadingRef shading;
   1.111 + 
   1.112 +     // Used with DO_PATTERN
   1.113 +     CGPatternRef pattern;
   1.114 + } cairo_quartz_drawing_state_t;
   1.115 + 
   1.116 + static void
   1.117 +@@ -1423,17 +1428,17 @@ _cairo_quartz_setup_fallback_source (cai
   1.118 + 	_cairo_pattern_transform (&pattern.base,
   1.119 + 				  &fallback->device_transform_inverse);
   1.120 + 	status = _cairo_surface_paint (fallback,
   1.121 + 				       CAIRO_OPERATOR_SOURCE,
   1.122 + 				       &pattern.base, NULL);
   1.123 +     }
   1.124 + #endif
   1.125 + 
   1.126 +-    status = _cairo_surface_to_cgimage (&surface->base, fallback, &img);
   1.127 ++    status = _cairo_surface_to_cgimage (fallback, &img);
   1.128 +     if (status) {
   1.129 +         state->action = DO_UNSUPPORTED;
   1.130 + 	return;
   1.131 +     }
   1.132 +     if (img == NULL) {
   1.133 +         state->action = DO_NOTHING;
   1.134 + 	return;
   1.135 +     }
   1.136 +@@ -1624,16 +1629,17 @@ _cairo_quartz_setup_state (cairo_quartz_
   1.137 + {
   1.138 +     CGContextRef context = surface->cgContext;
   1.139 +     cairo_quartz_drawing_state_t state;
   1.140 +     cairo_status_t status;
   1.141 + 
   1.142 +     state.context = context;
   1.143 +     state.image = NULL;
   1.144 +     state.imageSurface = NULL;
   1.145 ++    state.layer = NULL;
   1.146 +     state.shading = NULL;
   1.147 +     state.pattern = NULL;
   1.148 + 
   1.149 +     _cairo_quartz_surface_will_change (surface);
   1.150 + 
   1.151 +     // Save before we change the pattern, colorspace, etc. so that
   1.152 +     // we can restore and make sure that quartz releases our
   1.153 +     // pattern (which may be stack allocated)
   1.154 +@@ -1689,33 +1695,43 @@ _cairo_quartz_setup_state (cairo_quartz_
   1.155 + 	CGImageRef img;
   1.156 + 	cairo_matrix_t m = spat->base.matrix;
   1.157 + 	cairo_rectangle_int_t extents;
   1.158 + 	CGAffineTransform xform;
   1.159 + 	CGRect srcRect;
   1.160 + 	cairo_fixed_t fw, fh;
   1.161 + 	cairo_bool_t is_bounded;
   1.162 + 
   1.163 +-	status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
   1.164 ++        cairo_matrix_invert(&m);
   1.165 ++        _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
   1.166 ++
   1.167 ++        if (cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
   1.168 ++            cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
   1.169 ++            if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) {
   1.170 ++         	state.imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
   1.171 ++                state.layer = quartz_surf->cgLayer;
   1.172 ++                state.action = DO_LAYER;
   1.173 ++                return state;
   1.174 ++            }
   1.175 ++        }
   1.176 ++
   1.177 ++	status = _cairo_surface_to_cgimage (pat_surf, &img);
   1.178 +         if (status) {
   1.179 +             state.action = DO_UNSUPPORTED;
   1.180 + 	    return state;
   1.181 +         }
   1.182 +         if (img == NULL) {
   1.183 +             state.action = DO_NOTHING;
   1.184 + 	    return state;
   1.185 +         }
   1.186 + 
   1.187 + 	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
   1.188 + 
   1.189 + 	state.image = img;
   1.190 + 
   1.191 +-	cairo_matrix_invert(&m);
   1.192 +-	_cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
   1.193 +-
   1.194 + 	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
   1.195 + 	assert (is_bounded);
   1.196 + 
   1.197 + 	if (source->extend == CAIRO_EXTEND_NONE) {
   1.198 + 	    state.imageRect = CGRectMake (0, 0, extents.width, extents.height);
   1.199 + 	    state.action = DO_IMAGE;
   1.200 + 	    return state;
   1.201 + 	}
   1.202 +@@ -1820,33 +1836,48 @@ _cairo_quartz_teardown_state (cairo_quar
   1.203 + 
   1.204 +     CGContextRestoreGState(state->context);
   1.205 + }
   1.206 + 
   1.207 + 
   1.208 + static void
   1.209 + _cairo_quartz_draw_image (cairo_quartz_drawing_state_t *state, cairo_operator_t op)
   1.210 + {
   1.211 +-    assert (state && state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE));
   1.212 ++    assert (state &&
   1.213 ++            ((state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE)) ||
   1.214 ++             (state->layer && state->action == DO_LAYER)));
   1.215 + 
   1.216 +     CGContextConcatCTM (state->context, state->transform);
   1.217 +     CGContextTranslateCTM (state->context, 0, state->imageRect.size.height);
   1.218 +     CGContextScaleCTM (state->context, 1, -1);
   1.219 + 
   1.220 +-    if (state->action == DO_IMAGE) {
   1.221 +-	CGContextDrawImage (state->context, state->imageRect, state->image);
   1.222 ++    if (state->action == DO_TILED_IMAGE) {
   1.223 ++	CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
   1.224 ++	/* no need to worry about unbounded operators, since tiled images
   1.225 ++	   fill the entire clip region */
   1.226 ++    } else {
   1.227 ++        if (state->action == DO_LAYER) {
   1.228 ++            /* Note that according to Apple docs it's completely legal
   1.229 ++             * to draw a CGLayer to any CGContext, even one it wasn't
   1.230 ++             * created for.
   1.231 ++             */
   1.232 ++            CGContextDrawLayerAtPoint (state->context, state->imageRect.origin,
   1.233 ++                                       state->layer);
   1.234 ++        } else {
   1.235 ++            CGContextDrawImage (state->context, state->imageRect, state->image);
   1.236 ++        }
   1.237 ++
   1.238 + 	if (!_cairo_operator_bounded_by_source (op)) {
   1.239 + 	    CGContextBeginPath (state->context);
   1.240 + 	    CGContextAddRect (state->context, state->imageRect);
   1.241 + 	    CGContextAddRect (state->context, CGContextGetClipBoundingBox (state->context));
   1.242 + 	    CGContextSetRGBFillColor (state->context, 0, 0, 0, 0);
   1.243 + 	    CGContextEOFillPath (state->context);
   1.244 + 	}
   1.245 +-    } else
   1.246 +-	CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
   1.247 ++    }
   1.248 + }
   1.249 + 
   1.250 + 
   1.251 + /*
   1.252 +  * get source/dest image implementation
   1.253 +  */
   1.254 + 
   1.255 + /* Read the image from the surface's front buffer */
   1.256 +@@ -1971,95 +2002,153 @@ _cairo_quartz_surface_finish (void *abst
   1.257 + 	surface->imageSurfaceEquiv = NULL;
   1.258 +     }
   1.259 + 
   1.260 +     if (surface->imageData) {
   1.261 + 	free (surface->imageData);
   1.262 + 	surface->imageData = NULL;
   1.263 +     }
   1.264 + 
   1.265 ++    if (surface->cgLayer) {
   1.266 ++        CGLayerRelease (surface->cgLayer);
   1.267 ++    }
   1.268 ++
   1.269 +     return CAIRO_STATUS_SUCCESS;
   1.270 + }
   1.271 + 
   1.272 + static cairo_status_t
   1.273 +-_cairo_quartz_surface_acquire_source_image (void *abstract_surface,
   1.274 +-					     cairo_image_surface_t **image_out,
   1.275 +-					     void **image_extra)
   1.276 ++_cairo_quartz_surface_acquire_image (void *abstract_surface,
   1.277 ++                                     cairo_image_surface_t **image_out,
   1.278 ++                                     void **image_extra)
   1.279 + {
   1.280 +     cairo_int_status_t status;
   1.281 +     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
   1.282 + 
   1.283 +-    //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface));
   1.284 ++    *image_extra = NULL;
   1.285 ++
   1.286 ++    /* ND((stderr, "%p _cairo_quartz_surface_acquire_image\n", surface)); */
   1.287 + 
   1.288 +     status = _cairo_quartz_get_image (surface, image_out);
   1.289 ++
   1.290 ++    if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->cgLayer) {
   1.291 ++        /* copy the layer into a Quartz bitmap context so we can get the data */
   1.292 ++        cairo_surface_t *tmp =
   1.293 ++            cairo_quartz_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
   1.294 ++                                         surface->extents.width,
   1.295 ++                                         surface->extents.height);
   1.296 ++        cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) tmp;
   1.297 ++
   1.298 ++        /* if surface creation failed, we won't have a Quartz surface here */
   1.299 ++        if (cairo_surface_get_type (tmp) == CAIRO_SURFACE_TYPE_QUARTZ &&
   1.300 ++            tmp_surface->imageSurfaceEquiv) {
   1.301 ++            CGContextSaveGState (tmp_surface->cgContext);
   1.302 ++            CGContextTranslateCTM (tmp_surface->cgContext, 0, surface->extents.height);
   1.303 ++            CGContextScaleCTM (tmp_surface->cgContext, 1, -1);
   1.304 ++            /* Note that according to Apple docs it's completely legal
   1.305 ++             * to draw a CGLayer to any CGContext, even one it wasn't
   1.306 ++             * created for.
   1.307 ++             */
   1.308 ++            CGContextDrawLayerAtPoint (tmp_surface->cgContext,
   1.309 ++                                       CGPointMake (0.0, 0.0),
   1.310 ++                                       surface->cgLayer);
   1.311 ++            CGContextRestoreGState (tmp_surface->cgContext);
   1.312 ++
   1.313 ++            *image_out = (cairo_image_surface_t*)
   1.314 ++                cairo_surface_reference(tmp_surface->imageSurfaceEquiv);
   1.315 ++            *image_extra = tmp;
   1.316 ++        } else {
   1.317 ++            cairo_surface_destroy (tmp);
   1.318 ++        }
   1.319 ++    }
   1.320 ++
   1.321 +     if (status)
   1.322 + 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
   1.323 + 
   1.324 +-    *image_extra = NULL;
   1.325 +-
   1.326 +     return CAIRO_STATUS_SUCCESS;
   1.327 + }
   1.328 + 
   1.329 + static void
   1.330 + _cairo_quartz_surface_release_source_image (void *abstract_surface,
   1.331 + 					     cairo_image_surface_t *image,
   1.332 + 					     void *image_extra)
   1.333 + {
   1.334 +     cairo_surface_destroy ((cairo_surface_t *) image);
   1.335 ++
   1.336 ++    if (image_extra) {
   1.337 ++        cairo_surface_destroy ((cairo_surface_t *) image_extra);
   1.338 ++    }
   1.339 + }
   1.340 + 
   1.341 + 
   1.342 + static cairo_status_t
   1.343 + _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
   1.344 + 					  cairo_rectangle_int_t *interest_rect,
   1.345 + 					  cairo_image_surface_t **image_out,
   1.346 + 					  cairo_rectangle_int_t *image_rect,
   1.347 + 					  void **image_extra)
   1.348 + {
   1.349 +     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
   1.350 +-    cairo_int_status_t status;
   1.351 + 
   1.352 +     ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface));
   1.353 + 
   1.354 +-    _cairo_quartz_surface_will_change (surface);
   1.355 +-
   1.356 +-    status = _cairo_quartz_get_image (surface, image_out);
   1.357 +-    if (status)
   1.358 +-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
   1.359 +-
   1.360 +     *image_rect = surface->extents;
   1.361 +     *image_extra = NULL;
   1.362 + 
   1.363 +-    return CAIRO_STATUS_SUCCESS;
   1.364 ++    _cairo_quartz_surface_will_change (surface);
   1.365 ++
   1.366 ++    return _cairo_quartz_surface_acquire_image (abstract_surface,
   1.367 ++        image_out, image_extra);
   1.368 + }
   1.369 + 
   1.370 + static void
   1.371 + _cairo_quartz_surface_release_dest_image (void *abstract_surface,
   1.372 + 					  cairo_rectangle_int_t *interest_rect,
   1.373 + 					  cairo_image_surface_t *image,
   1.374 + 					  cairo_rectangle_int_t *image_rect,
   1.375 + 					  void *image_extra)
   1.376 + {
   1.377 +-    //cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
   1.378 +-
   1.379 +-    //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface));
   1.380 ++    /* ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); */
   1.381 + 
   1.382 +     cairo_surface_destroy ((cairo_surface_t *) image);
   1.383 ++
   1.384 ++    if (image_extra) {
   1.385 ++        /* we need to write the data from the temp surface back to the layer */
   1.386 ++        cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
   1.387 ++        cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) image_extra;
   1.388 ++        CGImageRef img;
   1.389 ++        cairo_status_t status = _cairo_surface_to_cgimage (&tmp_surface->base, &img);
   1.390 ++        if (status) {
   1.391 ++            cairo_surface_destroy (&tmp_surface->base);
   1.392 ++            return;
   1.393 ++        }
   1.394 ++
   1.395 ++        CGContextSaveGState (surface->cgContext);
   1.396 ++        CGContextTranslateCTM (surface->cgContext, 0, surface->extents.height);
   1.397 ++        CGContextScaleCTM (surface->cgContext, 1, -1);
   1.398 ++        CGContextDrawImage (surface->cgContext,
   1.399 ++                            CGRectMake (0.0, 0.0, surface->extents.width, surface->extents.height),
   1.400 ++                            img);
   1.401 ++        CGContextRestoreGState (surface->cgContext);
   1.402 ++
   1.403 ++        cairo_surface_destroy (&tmp_surface->base);
   1.404 ++    }
   1.405 + }
   1.406 + 
   1.407 + static cairo_surface_t *
   1.408 + _cairo_quartz_surface_create_similar (void *abstract_surface,
   1.409 + 				       cairo_content_t content,
   1.410 + 				       int width,
   1.411 + 				       int height)
   1.412 + {
   1.413 +-    /*cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;*/
   1.414 +-
   1.415 ++    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
   1.416 +     cairo_format_t format;
   1.417 + 
   1.418 ++    if (surface->cgLayer)
   1.419 ++        return cairo_quartz_surface_create_cg_layer (abstract_surface, width, height);
   1.420 ++
   1.421 +     if (content == CAIRO_CONTENT_COLOR_ALPHA)
   1.422 + 	format = CAIRO_FORMAT_ARGB32;
   1.423 +     else if (content == CAIRO_CONTENT_COLOR)
   1.424 + 	format = CAIRO_FORMAT_RGB24;
   1.425 +     else if (content == CAIRO_CONTENT_ALPHA)
   1.426 + 	format = CAIRO_FORMAT_A8;
   1.427 +     else
   1.428 + 	return NULL;
   1.429 +@@ -2113,17 +2202,17 @@ _cairo_quartz_surface_clone_similar (voi
   1.430 + 		_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
   1.431 + 						       qsurf->extents.width, qsurf->extents.height);
   1.432 + 	    *clone_offset_x = 0;
   1.433 + 	    *clone_offset_y = 0;
   1.434 + 	    return CAIRO_STATUS_SUCCESS;
   1.435 + 	}
   1.436 +     }
   1.437 + 
   1.438 +-    status = _cairo_surface_to_cgimage ((cairo_surface_t*) abstract_surface, src, &quartz_image);
   1.439 ++    status = _cairo_surface_to_cgimage (src, &quartz_image);
   1.440 +     if (status)
   1.441 + 	return CAIRO_INT_STATUS_UNSUPPORTED;
   1.442 + 
   1.443 +     new_format = CAIRO_FORMAT_ARGB32;  /* assumed */
   1.444 +     if (_cairo_surface_is_image (src)) {
   1.445 + 	new_format = ((cairo_image_surface_t *) src)->format;
   1.446 +     }
   1.447 + 
   1.448 +@@ -2194,17 +2283,18 @@ _cairo_quartz_surface_paint (void *abstr
   1.449 +     if (state.action == DO_SOLID || state.action == DO_PATTERN) {
   1.450 + 	CGContextFillRect (state.context, CGRectMake(surface->extents.x,
   1.451 + 						     surface->extents.y,
   1.452 + 						     surface->extents.width,
   1.453 + 						     surface->extents.height));
   1.454 +     } else if (state.action == DO_SHADING) {
   1.455 + 	CGContextConcatCTM (state.context, state.transform);
   1.456 + 	CGContextDrawShading (state.context, state.shading);
   1.457 +-    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
   1.458 ++    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
   1.459 ++               state.action == DO_LAYER) {
   1.460 + 	_cairo_quartz_draw_image (&state, op);
   1.461 +     } else if (state.action != DO_NOTHING) {
   1.462 + 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
   1.463 +     }
   1.464 + 
   1.465 +     _cairo_quartz_teardown_state (&state);
   1.466 + 
   1.467 +     ND((stderr, "-- paint\n"));
   1.468 +@@ -2291,17 +2381,18 @@ _cairo_quartz_surface_fill (void *abstra
   1.469 + 	// with the shading
   1.470 + 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
   1.471 + 	    CGContextClip (state.context);
   1.472 + 	else
   1.473 +             CGContextEOClip (state.context);
   1.474 + 
   1.475 + 	CGContextConcatCTM (state.context, state.transform);
   1.476 + 	CGContextDrawShading (state.context, state.shading);
   1.477 +-    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
   1.478 ++    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
   1.479 ++               state.action == DO_LAYER) {
   1.480 + 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
   1.481 + 	    CGContextClip (state.context);
   1.482 + 	else
   1.483 + 	    CGContextEOClip (state.context);
   1.484 + 
   1.485 + 	_cairo_quartz_draw_image (&state, op);
   1.486 +     } else if (state.action != DO_NOTHING) {
   1.487 + 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
   1.488 +@@ -2416,17 +2507,18 @@ _cairo_quartz_surface_stroke (void *abst
   1.489 +     if (rv)
   1.490 + 	goto BAIL;
   1.491 + 
   1.492 +     if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
   1.493 + 	path_for_unbounded = CGContextCopyPathPtr (state.context);
   1.494 + 
   1.495 +     if (state.action == DO_SOLID || state.action == DO_PATTERN) {
   1.496 + 	CGContextStrokePath (state.context);
   1.497 +-    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
   1.498 ++    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
   1.499 ++               state.action == DO_LAYER) {
   1.500 + 	CGContextReplacePathWithStrokedPath (state.context);
   1.501 + 	CGContextClip (state.context);
   1.502 + 
   1.503 + 	CGContextSetCTM (state.context, origCTM);
   1.504 + 	_cairo_quartz_draw_image (&state, op);
   1.505 +     } else if (state.action == DO_SHADING) {
   1.506 + 	CGContextReplacePathWithStrokedPath (state.context);
   1.507 + 	CGContextClip (state.context);
   1.508 +@@ -2511,17 +2603,18 @@ _cairo_quartz_surface_show_glyphs (void 
   1.509 +                                                  &glyph_extents, NULL);
   1.510 +         state = _cairo_quartz_setup_state (surface, source, op, &glyph_extents);
   1.511 +     } else {
   1.512 +         state = _cairo_quartz_setup_state (surface, source, op, NULL);
   1.513 +     }
   1.514 + 
   1.515 +     if (state.action == DO_SOLID || state.action == DO_PATTERN) {
   1.516 + 	CGContextSetTextDrawingMode (state.context, kCGTextFill);
   1.517 +-    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE || state.action == DO_SHADING) {
   1.518 ++    } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
   1.519 ++               state.action == DO_SHADING || state.action == DO_LAYER) {
   1.520 + 	CGContextSetTextDrawingMode (state.context, kCGTextClip);
   1.521 + 	isClipping = TRUE;
   1.522 +     } else {
   1.523 + 	if (state.action != DO_NOTHING)
   1.524 + 	    rv = CAIRO_INT_STATUS_UNSUPPORTED;
   1.525 + 	goto BAIL;
   1.526 +     }
   1.527 + 
   1.528 +@@ -2622,17 +2715,18 @@ _cairo_quartz_surface_show_glyphs (void 
   1.529 + 
   1.530 +     CGContextShowGlyphsWithAdvances (state.context,
   1.531 + 				     cg_glyphs,
   1.532 + 				     cg_advances,
   1.533 + 				     num_glyphs);
   1.534 + 
   1.535 +     CGContextSetCTM (state.context, ctm);
   1.536 + 
   1.537 +-    if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
   1.538 ++    if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
   1.539 ++        state.action == DO_LAYER) {
   1.540 + 	_cairo_quartz_draw_image (&state, op);
   1.541 +     } else if (state.action == DO_SHADING) {
   1.542 + 	CGContextConcatCTM (state.context, state.transform);
   1.543 + 	CGContextDrawShading (state.context, state.shading);
   1.544 +     }
   1.545 + 
   1.546 + BAIL:
   1.547 +     if (didForceFontSmoothing)
   1.548 +@@ -2679,17 +2773,17 @@ _cairo_quartz_surface_mask_with_surface 
   1.549 + 					 cairo_clip_t *clip)
   1.550 + {
   1.551 +     CGRect rect;
   1.552 +     CGImageRef img;
   1.553 +     cairo_surface_t *pat_surf = mask->surface;
   1.554 +     cairo_status_t status = CAIRO_STATUS_SUCCESS;
   1.555 +     CGAffineTransform ctm, mask_matrix;
   1.556 + 
   1.557 +-    status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
   1.558 ++    status = _cairo_surface_to_cgimage (pat_surf, &img);
   1.559 +     if (status)
   1.560 + 	return status;
   1.561 +     if (img == NULL) {
   1.562 + 	if (!_cairo_operator_bounded_by_mask (op))
   1.563 + 	    CGContextClearRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
   1.564 + 	return CAIRO_STATUS_SUCCESS;
   1.565 +     }
   1.566 + 
   1.567 +@@ -2869,17 +2963,17 @@ _cairo_quartz_surface_clipper_intersect_
   1.568 + }
   1.569 + 
   1.570 + // XXXtodo implement show_page; need to figure out how to handle begin/end
   1.571 + 
   1.572 + static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
   1.573 +     CAIRO_SURFACE_TYPE_QUARTZ,
   1.574 +     _cairo_quartz_surface_create_similar,
   1.575 +     _cairo_quartz_surface_finish,
   1.576 +-    _cairo_quartz_surface_acquire_source_image,
   1.577 ++    _cairo_quartz_surface_acquire_image,
   1.578 +     _cairo_quartz_surface_release_source_image,
   1.579 +     _cairo_quartz_surface_acquire_dest_image,
   1.580 +     _cairo_quartz_surface_release_dest_image,
   1.581 +     _cairo_quartz_surface_clone_similar,
   1.582 +     NULL, /* composite */
   1.583 +     NULL, /* fill_rectangles */
   1.584 +     NULL, /* composite_trapezoids */
   1.585 +     NULL, /* create_span_renderer */
   1.586 +@@ -2950,16 +3044,17 @@ _cairo_quartz_surface_create_internal (C
   1.587 +     CGContextSaveGState (cgContext);
   1.588 + 
   1.589 +     surface->cgContext = cgContext;
   1.590 +     surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
   1.591 + 
   1.592 +     surface->imageData = NULL;
   1.593 +     surface->imageSurfaceEquiv = NULL;
   1.594 +     surface->bitmapContextImage = NULL;
   1.595 ++    surface->cgLayer = NULL;
   1.596 + 
   1.597 +     return surface;
   1.598 + }
   1.599 + 
   1.600 + /**
   1.601 +  * cairo_quartz_surface_create_for_cg_context
   1.602 +  * @cgContext: the existing CGContext for which to create the surface
   1.603 +  * @width: width of the surface, in pixels
   1.604 +@@ -3002,16 +3097,88 @@ cairo_quartz_surface_create_for_cg_conte
   1.605 + 	// create_internal will have set an error
   1.606 + 	return (cairo_surface_t*) surf;
   1.607 +     }
   1.608 + 
   1.609 +     return (cairo_surface_t *) surf;
   1.610 + }
   1.611 + 
   1.612 + /**
   1.613 ++ * cairo_quartz_cglayer_surface_create_similar
   1.614 ++ * @surface: The returned surface can be efficiently drawn into this
   1.615 ++ * destination surface (if tiling is not used)."
   1.616 ++ * @width: width of the surface, in pixels
   1.617 ++ * @height: height of the surface, in pixels
   1.618 ++ *
   1.619 ++ * Creates a Quartz surface backed by a CGLayer, if the given surface
   1.620 ++ * is a Quartz surface; the CGLayer is created to match the surface's
   1.621 ++ * Quartz context. Otherwise just calls cairo_surface_create_similar
   1.622 ++ * with CAIRO_CONTENT_COLOR_ALPHA.
   1.623 ++ * The returned surface can be efficiently blitted to the given surface,
   1.624 ++ * but tiling and 'extend' modes other than NONE are not so efficient.
   1.625 ++ *
   1.626 ++ * Return value: the newly created surface.
   1.627 ++ *
   1.628 ++ * Since: 1.10
   1.629 ++ **/
   1.630 ++cairo_surface_t *
   1.631 ++cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
   1.632 ++                                      unsigned int width,
   1.633 ++                                      unsigned int height)
   1.634 ++{
   1.635 ++    cairo_quartz_surface_t *surf;
   1.636 ++    CGLayerRef layer;
   1.637 ++    CGContextRef ctx;
   1.638 ++    CGContextRef cgContext;
   1.639 ++
   1.640 ++    cgContext = cairo_quartz_surface_get_cg_context (surface);
   1.641 ++    if (!cgContext)
   1.642 ++        return cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
   1.643 ++                                             width, height);
   1.644 ++
   1.645 ++    if (!_cairo_quartz_verify_surface_size(width, height))
   1.646 ++        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
   1.647 ++
   1.648 ++    /* If we pass zero width or height into CGLayerCreateWithContext below,
   1.649 ++     * it will fail.
   1.650 ++     */
   1.651 ++    if (width == 0 || height == 0) {
   1.652 ++        return (cairo_surface_t*)
   1.653 ++            _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
   1.654 ++                                                   width, height);
   1.655 ++    }
   1.656 ++
   1.657 ++    layer = CGLayerCreateWithContext (cgContext,
   1.658 ++                                      CGSizeMake (width, height),
   1.659 ++                                      NULL);
   1.660 ++    if (!layer)
   1.661 ++      return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
   1.662 ++
   1.663 ++    ctx = CGLayerGetContext (layer);
   1.664 ++    /* Flip it when we draw into it, so that when we finally composite it
   1.665 ++     * to a flipped target, the directions match and Quartz will optimize
   1.666 ++     * the composition properly
   1.667 ++     */
   1.668 ++    CGContextTranslateCTM (ctx, 0, height);
   1.669 ++    CGContextScaleCTM (ctx, 1, -1);
   1.670 ++
   1.671 ++    CGContextRetain (ctx);
   1.672 ++    surf = _cairo_quartz_surface_create_internal (ctx, CAIRO_CONTENT_COLOR_ALPHA,
   1.673 ++              width, height);
   1.674 ++    if (surf->base.status) {
   1.675 ++        CGLayerRelease (layer);
   1.676 ++        // create_internal will have set an error
   1.677 ++        return (cairo_surface_t*) surf;
   1.678 ++    }
   1.679 ++    surf->cgLayer = layer;
   1.680 ++
   1.681 ++    return (cairo_surface_t *) surf;
   1.682 ++}
   1.683 ++
   1.684 ++/**
   1.685 +  * cairo_quartz_surface_create
   1.686 +  * @format: format of pixels in the surface to create
   1.687 +  * @width: width of the surface, in pixels
   1.688 +  * @height: height of the surface, in pixels
   1.689 +  *
   1.690 +  * Creates a Quartz surface backed by a CGBitmap.  The surface is
   1.691 +  * created using the Device RGB (or Device Gray, for A8) color space.
   1.692 +  * All Cairo operations, including those that require software
   1.693 +diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
   1.694 +--- a/gfx/cairo/cairo/src/cairo-quartz.h
   1.695 ++++ b/gfx/cairo/cairo/src/cairo-quartz.h
   1.696 +@@ -45,16 +45,21 @@
   1.697 + CAIRO_BEGIN_DECLS
   1.698 + 
   1.699 + cairo_public cairo_surface_t *
   1.700 + cairo_quartz_surface_create (cairo_format_t format,
   1.701 +                              unsigned int width,
   1.702 +                              unsigned int height);
   1.703 + 
   1.704 + cairo_public cairo_surface_t *
   1.705 ++cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
   1.706 ++                                      unsigned int width,
   1.707 ++                                      unsigned int height);
   1.708 ++
   1.709 ++cairo_public cairo_surface_t *
   1.710 + cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
   1.711 +                                             unsigned int width,
   1.712 +                                             unsigned int height);
   1.713 + 
   1.714 + cairo_public CGContextRef
   1.715 + cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
   1.716 + 
   1.717 + cairo_public CGContextRef
   1.718 +

mercurial