gfx/cairo/quartz-cglayers.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.

michael@0 1 changeset: 42959:e1964291f8ff
michael@0 2 user: Robert O'Callahan <robert@ocallahan.org>
michael@0 3 date: Tue Jun 01 11:33:23 2010 +1200
michael@0 4 summary: Bug 568189. Implement CGLayer-backed cairo-quartz surfaces. r=jrmuizel
michael@0 5
michael@0 6 diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
michael@0 7 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h
michael@0 8 +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
michael@0 9 @@ -57,16 +57,21 @@ typedef struct cairo_quartz_surface {
michael@0 10
michael@0 11 /**
michael@0 12 * If non-null, this is a CGImage representing the contents of the surface.
michael@0 13 * We clear this out before any painting into the surface, so that we
michael@0 14 * don't force a copy to be created.
michael@0 15 */
michael@0 16 CGImageRef bitmapContextImage;
michael@0 17
michael@0 18 + /**
michael@0 19 + * If non-null, this is the CGLayer for the surface.
michael@0 20 + */
michael@0 21 + CGLayerRef cgLayer;
michael@0 22 +
michael@0 23 cairo_rectangle_int_t extents;
michael@0 24 } cairo_quartz_surface_t;
michael@0 25
michael@0 26 typedef struct cairo_quartz_image_surface {
michael@0 27 cairo_surface_t base;
michael@0 28
michael@0 29 cairo_rectangle_int_t extents;
michael@0 30
michael@0 31 diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
michael@0 32 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
michael@0 33 +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
michael@0 34 @@ -1110,18 +1110,17 @@ CreateRepeatingRadialGradientFunction (c
michael@0 35 static void
michael@0 36 DataProviderReleaseCallback (void *info, const void *data, size_t size)
michael@0 37 {
michael@0 38 cairo_surface_t *surface = (cairo_surface_t *) info;
michael@0 39 cairo_surface_destroy (surface);
michael@0 40 }
michael@0 41
michael@0 42 static cairo_status_t
michael@0 43 -_cairo_surface_to_cgimage (cairo_surface_t *target,
michael@0 44 - cairo_surface_t *source,
michael@0 45 +_cairo_surface_to_cgimage (cairo_surface_t *source,
michael@0 46 CGImageRef *image_out)
michael@0 47 {
michael@0 48 cairo_status_t status = CAIRO_STATUS_SUCCESS;
michael@0 49 cairo_surface_type_t stype = cairo_surface_get_type (source);
michael@0 50 cairo_image_surface_t *isurf;
michael@0 51 CGImageRef image;
michael@0 52 void *image_extra;
michael@0 53
michael@0 54 @@ -1267,17 +1266,17 @@ _cairo_quartz_cairo_repeating_surface_pa
michael@0 55 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 56
michael@0 57 spattern = (cairo_surface_pattern_t *) apattern;
michael@0 58 pat_surf = spattern->surface;
michael@0 59
michael@0 60 is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
michael@0 61 assert (is_bounded);
michael@0 62
michael@0 63 - status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image);
michael@0 64 + status = _cairo_surface_to_cgimage (pat_surf, &image);
michael@0 65 if (status)
michael@0 66 return status;
michael@0 67 if (image == NULL)
michael@0 68 return CAIRO_INT_STATUS_NOTHING_TO_DO;
michael@0 69
michael@0 70 info = malloc(sizeof(SurfacePatternDrawInfo));
michael@0 71 if (!info)
michael@0 72 return CAIRO_STATUS_NO_MEMORY;
michael@0 73 @@ -1339,33 +1338,39 @@ _cairo_quartz_cairo_repeating_surface_pa
michael@0 74 }
michael@0 75
michael@0 76 typedef enum {
michael@0 77 DO_SOLID,
michael@0 78 DO_SHADING,
michael@0 79 DO_PATTERN,
michael@0 80 DO_IMAGE,
michael@0 81 DO_TILED_IMAGE,
michael@0 82 + DO_LAYER,
michael@0 83 DO_UNSUPPORTED,
michael@0 84 DO_NOTHING
michael@0 85 } cairo_quartz_action_t;
michael@0 86
michael@0 87 /* State used during a drawing operation. */
michael@0 88 typedef struct {
michael@0 89 CGContextRef context;
michael@0 90 cairo_quartz_action_t action;
michael@0 91
michael@0 92 - // Used with DO_SHADING, DO_IMAGE and DO_TILED_IMAGE
michael@0 93 + // Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
michael@0 94 CGAffineTransform transform;
michael@0 95
michael@0 96 // Used with DO_IMAGE and DO_TILED_IMAGE
michael@0 97 CGImageRef image;
michael@0 98 cairo_surface_t *imageSurface;
michael@0 99 +
michael@0 100 + // Used with DO_IMAGE, DO_TILED_IMAGE and DO_LAYER
michael@0 101 CGRect imageRect;
michael@0 102
michael@0 103 + // Used with DO_LAYER
michael@0 104 + CGLayerRef layer;
michael@0 105 +
michael@0 106 // Used with DO_SHADING
michael@0 107 CGShadingRef shading;
michael@0 108
michael@0 109 // Used with DO_PATTERN
michael@0 110 CGPatternRef pattern;
michael@0 111 } cairo_quartz_drawing_state_t;
michael@0 112
michael@0 113 static void
michael@0 114 @@ -1423,17 +1428,17 @@ _cairo_quartz_setup_fallback_source (cai
michael@0 115 _cairo_pattern_transform (&pattern.base,
michael@0 116 &fallback->device_transform_inverse);
michael@0 117 status = _cairo_surface_paint (fallback,
michael@0 118 CAIRO_OPERATOR_SOURCE,
michael@0 119 &pattern.base, NULL);
michael@0 120 }
michael@0 121 #endif
michael@0 122
michael@0 123 - status = _cairo_surface_to_cgimage (&surface->base, fallback, &img);
michael@0 124 + status = _cairo_surface_to_cgimage (fallback, &img);
michael@0 125 if (status) {
michael@0 126 state->action = DO_UNSUPPORTED;
michael@0 127 return;
michael@0 128 }
michael@0 129 if (img == NULL) {
michael@0 130 state->action = DO_NOTHING;
michael@0 131 return;
michael@0 132 }
michael@0 133 @@ -1624,16 +1629,17 @@ _cairo_quartz_setup_state (cairo_quartz_
michael@0 134 {
michael@0 135 CGContextRef context = surface->cgContext;
michael@0 136 cairo_quartz_drawing_state_t state;
michael@0 137 cairo_status_t status;
michael@0 138
michael@0 139 state.context = context;
michael@0 140 state.image = NULL;
michael@0 141 state.imageSurface = NULL;
michael@0 142 + state.layer = NULL;
michael@0 143 state.shading = NULL;
michael@0 144 state.pattern = NULL;
michael@0 145
michael@0 146 _cairo_quartz_surface_will_change (surface);
michael@0 147
michael@0 148 // Save before we change the pattern, colorspace, etc. so that
michael@0 149 // we can restore and make sure that quartz releases our
michael@0 150 // pattern (which may be stack allocated)
michael@0 151 @@ -1689,33 +1695,43 @@ _cairo_quartz_setup_state (cairo_quartz_
michael@0 152 CGImageRef img;
michael@0 153 cairo_matrix_t m = spat->base.matrix;
michael@0 154 cairo_rectangle_int_t extents;
michael@0 155 CGAffineTransform xform;
michael@0 156 CGRect srcRect;
michael@0 157 cairo_fixed_t fw, fh;
michael@0 158 cairo_bool_t is_bounded;
michael@0 159
michael@0 160 - status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
michael@0 161 + cairo_matrix_invert(&m);
michael@0 162 + _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
michael@0 163 +
michael@0 164 + if (cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
michael@0 165 + cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf;
michael@0 166 + if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) {
michael@0 167 + state.imageRect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height);
michael@0 168 + state.layer = quartz_surf->cgLayer;
michael@0 169 + state.action = DO_LAYER;
michael@0 170 + return state;
michael@0 171 + }
michael@0 172 + }
michael@0 173 +
michael@0 174 + status = _cairo_surface_to_cgimage (pat_surf, &img);
michael@0 175 if (status) {
michael@0 176 state.action = DO_UNSUPPORTED;
michael@0 177 return state;
michael@0 178 }
michael@0 179 if (img == NULL) {
michael@0 180 state.action = DO_NOTHING;
michael@0 181 return state;
michael@0 182 }
michael@0 183
michael@0 184 CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
michael@0 185
michael@0 186 state.image = img;
michael@0 187
michael@0 188 - cairo_matrix_invert(&m);
michael@0 189 - _cairo_quartz_cairo_matrix_to_quartz (&m, &state.transform);
michael@0 190 -
michael@0 191 is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
michael@0 192 assert (is_bounded);
michael@0 193
michael@0 194 if (source->extend == CAIRO_EXTEND_NONE) {
michael@0 195 state.imageRect = CGRectMake (0, 0, extents.width, extents.height);
michael@0 196 state.action = DO_IMAGE;
michael@0 197 return state;
michael@0 198 }
michael@0 199 @@ -1820,33 +1836,48 @@ _cairo_quartz_teardown_state (cairo_quar
michael@0 200
michael@0 201 CGContextRestoreGState(state->context);
michael@0 202 }
michael@0 203
michael@0 204
michael@0 205 static void
michael@0 206 _cairo_quartz_draw_image (cairo_quartz_drawing_state_t *state, cairo_operator_t op)
michael@0 207 {
michael@0 208 - assert (state && state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE));
michael@0 209 + assert (state &&
michael@0 210 + ((state->image && (state->action == DO_IMAGE || state->action == DO_TILED_IMAGE)) ||
michael@0 211 + (state->layer && state->action == DO_LAYER)));
michael@0 212
michael@0 213 CGContextConcatCTM (state->context, state->transform);
michael@0 214 CGContextTranslateCTM (state->context, 0, state->imageRect.size.height);
michael@0 215 CGContextScaleCTM (state->context, 1, -1);
michael@0 216
michael@0 217 - if (state->action == DO_IMAGE) {
michael@0 218 - CGContextDrawImage (state->context, state->imageRect, state->image);
michael@0 219 + if (state->action == DO_TILED_IMAGE) {
michael@0 220 + CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
michael@0 221 + /* no need to worry about unbounded operators, since tiled images
michael@0 222 + fill the entire clip region */
michael@0 223 + } else {
michael@0 224 + if (state->action == DO_LAYER) {
michael@0 225 + /* Note that according to Apple docs it's completely legal
michael@0 226 + * to draw a CGLayer to any CGContext, even one it wasn't
michael@0 227 + * created for.
michael@0 228 + */
michael@0 229 + CGContextDrawLayerAtPoint (state->context, state->imageRect.origin,
michael@0 230 + state->layer);
michael@0 231 + } else {
michael@0 232 + CGContextDrawImage (state->context, state->imageRect, state->image);
michael@0 233 + }
michael@0 234 +
michael@0 235 if (!_cairo_operator_bounded_by_source (op)) {
michael@0 236 CGContextBeginPath (state->context);
michael@0 237 CGContextAddRect (state->context, state->imageRect);
michael@0 238 CGContextAddRect (state->context, CGContextGetClipBoundingBox (state->context));
michael@0 239 CGContextSetRGBFillColor (state->context, 0, 0, 0, 0);
michael@0 240 CGContextEOFillPath (state->context);
michael@0 241 }
michael@0 242 - } else
michael@0 243 - CGContextDrawTiledImagePtr (state->context, state->imageRect, state->image);
michael@0 244 + }
michael@0 245 }
michael@0 246
michael@0 247
michael@0 248 /*
michael@0 249 * get source/dest image implementation
michael@0 250 */
michael@0 251
michael@0 252 /* Read the image from the surface's front buffer */
michael@0 253 @@ -1971,95 +2002,153 @@ _cairo_quartz_surface_finish (void *abst
michael@0 254 surface->imageSurfaceEquiv = NULL;
michael@0 255 }
michael@0 256
michael@0 257 if (surface->imageData) {
michael@0 258 free (surface->imageData);
michael@0 259 surface->imageData = NULL;
michael@0 260 }
michael@0 261
michael@0 262 + if (surface->cgLayer) {
michael@0 263 + CGLayerRelease (surface->cgLayer);
michael@0 264 + }
michael@0 265 +
michael@0 266 return CAIRO_STATUS_SUCCESS;
michael@0 267 }
michael@0 268
michael@0 269 static cairo_status_t
michael@0 270 -_cairo_quartz_surface_acquire_source_image (void *abstract_surface,
michael@0 271 - cairo_image_surface_t **image_out,
michael@0 272 - void **image_extra)
michael@0 273 +_cairo_quartz_surface_acquire_image (void *abstract_surface,
michael@0 274 + cairo_image_surface_t **image_out,
michael@0 275 + void **image_extra)
michael@0 276 {
michael@0 277 cairo_int_status_t status;
michael@0 278 cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
michael@0 279
michael@0 280 - //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface));
michael@0 281 + *image_extra = NULL;
michael@0 282 +
michael@0 283 + /* ND((stderr, "%p _cairo_quartz_surface_acquire_image\n", surface)); */
michael@0 284
michael@0 285 status = _cairo_quartz_get_image (surface, image_out);
michael@0 286 +
michael@0 287 + if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->cgLayer) {
michael@0 288 + /* copy the layer into a Quartz bitmap context so we can get the data */
michael@0 289 + cairo_surface_t *tmp =
michael@0 290 + cairo_quartz_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
michael@0 291 + surface->extents.width,
michael@0 292 + surface->extents.height);
michael@0 293 + cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) tmp;
michael@0 294 +
michael@0 295 + /* if surface creation failed, we won't have a Quartz surface here */
michael@0 296 + if (cairo_surface_get_type (tmp) == CAIRO_SURFACE_TYPE_QUARTZ &&
michael@0 297 + tmp_surface->imageSurfaceEquiv) {
michael@0 298 + CGContextSaveGState (tmp_surface->cgContext);
michael@0 299 + CGContextTranslateCTM (tmp_surface->cgContext, 0, surface->extents.height);
michael@0 300 + CGContextScaleCTM (tmp_surface->cgContext, 1, -1);
michael@0 301 + /* Note that according to Apple docs it's completely legal
michael@0 302 + * to draw a CGLayer to any CGContext, even one it wasn't
michael@0 303 + * created for.
michael@0 304 + */
michael@0 305 + CGContextDrawLayerAtPoint (tmp_surface->cgContext,
michael@0 306 + CGPointMake (0.0, 0.0),
michael@0 307 + surface->cgLayer);
michael@0 308 + CGContextRestoreGState (tmp_surface->cgContext);
michael@0 309 +
michael@0 310 + *image_out = (cairo_image_surface_t*)
michael@0 311 + cairo_surface_reference(tmp_surface->imageSurfaceEquiv);
michael@0 312 + *image_extra = tmp;
michael@0 313 + } else {
michael@0 314 + cairo_surface_destroy (tmp);
michael@0 315 + }
michael@0 316 + }
michael@0 317 +
michael@0 318 if (status)
michael@0 319 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
michael@0 320
michael@0 321 - *image_extra = NULL;
michael@0 322 -
michael@0 323 return CAIRO_STATUS_SUCCESS;
michael@0 324 }
michael@0 325
michael@0 326 static void
michael@0 327 _cairo_quartz_surface_release_source_image (void *abstract_surface,
michael@0 328 cairo_image_surface_t *image,
michael@0 329 void *image_extra)
michael@0 330 {
michael@0 331 cairo_surface_destroy ((cairo_surface_t *) image);
michael@0 332 +
michael@0 333 + if (image_extra) {
michael@0 334 + cairo_surface_destroy ((cairo_surface_t *) image_extra);
michael@0 335 + }
michael@0 336 }
michael@0 337
michael@0 338
michael@0 339 static cairo_status_t
michael@0 340 _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
michael@0 341 cairo_rectangle_int_t *interest_rect,
michael@0 342 cairo_image_surface_t **image_out,
michael@0 343 cairo_rectangle_int_t *image_rect,
michael@0 344 void **image_extra)
michael@0 345 {
michael@0 346 cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
michael@0 347 - cairo_int_status_t status;
michael@0 348
michael@0 349 ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface));
michael@0 350
michael@0 351 - _cairo_quartz_surface_will_change (surface);
michael@0 352 -
michael@0 353 - status = _cairo_quartz_get_image (surface, image_out);
michael@0 354 - if (status)
michael@0 355 - return _cairo_error (CAIRO_STATUS_NO_MEMORY);
michael@0 356 -
michael@0 357 *image_rect = surface->extents;
michael@0 358 *image_extra = NULL;
michael@0 359
michael@0 360 - return CAIRO_STATUS_SUCCESS;
michael@0 361 + _cairo_quartz_surface_will_change (surface);
michael@0 362 +
michael@0 363 + return _cairo_quartz_surface_acquire_image (abstract_surface,
michael@0 364 + image_out, image_extra);
michael@0 365 }
michael@0 366
michael@0 367 static void
michael@0 368 _cairo_quartz_surface_release_dest_image (void *abstract_surface,
michael@0 369 cairo_rectangle_int_t *interest_rect,
michael@0 370 cairo_image_surface_t *image,
michael@0 371 cairo_rectangle_int_t *image_rect,
michael@0 372 void *image_extra)
michael@0 373 {
michael@0 374 - //cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
michael@0 375 -
michael@0 376 - //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface));
michael@0 377 + /* ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); */
michael@0 378
michael@0 379 cairo_surface_destroy ((cairo_surface_t *) image);
michael@0 380 +
michael@0 381 + if (image_extra) {
michael@0 382 + /* we need to write the data from the temp surface back to the layer */
michael@0 383 + cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
michael@0 384 + cairo_quartz_surface_t *tmp_surface = (cairo_quartz_surface_t *) image_extra;
michael@0 385 + CGImageRef img;
michael@0 386 + cairo_status_t status = _cairo_surface_to_cgimage (&tmp_surface->base, &img);
michael@0 387 + if (status) {
michael@0 388 + cairo_surface_destroy (&tmp_surface->base);
michael@0 389 + return;
michael@0 390 + }
michael@0 391 +
michael@0 392 + CGContextSaveGState (surface->cgContext);
michael@0 393 + CGContextTranslateCTM (surface->cgContext, 0, surface->extents.height);
michael@0 394 + CGContextScaleCTM (surface->cgContext, 1, -1);
michael@0 395 + CGContextDrawImage (surface->cgContext,
michael@0 396 + CGRectMake (0.0, 0.0, surface->extents.width, surface->extents.height),
michael@0 397 + img);
michael@0 398 + CGContextRestoreGState (surface->cgContext);
michael@0 399 +
michael@0 400 + cairo_surface_destroy (&tmp_surface->base);
michael@0 401 + }
michael@0 402 }
michael@0 403
michael@0 404 static cairo_surface_t *
michael@0 405 _cairo_quartz_surface_create_similar (void *abstract_surface,
michael@0 406 cairo_content_t content,
michael@0 407 int width,
michael@0 408 int height)
michael@0 409 {
michael@0 410 - /*cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;*/
michael@0 411 -
michael@0 412 + cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
michael@0 413 cairo_format_t format;
michael@0 414
michael@0 415 + if (surface->cgLayer)
michael@0 416 + return cairo_quartz_surface_create_cg_layer (abstract_surface, width, height);
michael@0 417 +
michael@0 418 if (content == CAIRO_CONTENT_COLOR_ALPHA)
michael@0 419 format = CAIRO_FORMAT_ARGB32;
michael@0 420 else if (content == CAIRO_CONTENT_COLOR)
michael@0 421 format = CAIRO_FORMAT_RGB24;
michael@0 422 else if (content == CAIRO_CONTENT_ALPHA)
michael@0 423 format = CAIRO_FORMAT_A8;
michael@0 424 else
michael@0 425 return NULL;
michael@0 426 @@ -2113,17 +2202,17 @@ _cairo_quartz_surface_clone_similar (voi
michael@0 427 _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
michael@0 428 qsurf->extents.width, qsurf->extents.height);
michael@0 429 *clone_offset_x = 0;
michael@0 430 *clone_offset_y = 0;
michael@0 431 return CAIRO_STATUS_SUCCESS;
michael@0 432 }
michael@0 433 }
michael@0 434
michael@0 435 - status = _cairo_surface_to_cgimage ((cairo_surface_t*) abstract_surface, src, &quartz_image);
michael@0 436 + status = _cairo_surface_to_cgimage (src, &quartz_image);
michael@0 437 if (status)
michael@0 438 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 439
michael@0 440 new_format = CAIRO_FORMAT_ARGB32; /* assumed */
michael@0 441 if (_cairo_surface_is_image (src)) {
michael@0 442 new_format = ((cairo_image_surface_t *) src)->format;
michael@0 443 }
michael@0 444
michael@0 445 @@ -2194,17 +2283,18 @@ _cairo_quartz_surface_paint (void *abstr
michael@0 446 if (state.action == DO_SOLID || state.action == DO_PATTERN) {
michael@0 447 CGContextFillRect (state.context, CGRectMake(surface->extents.x,
michael@0 448 surface->extents.y,
michael@0 449 surface->extents.width,
michael@0 450 surface->extents.height));
michael@0 451 } else if (state.action == DO_SHADING) {
michael@0 452 CGContextConcatCTM (state.context, state.transform);
michael@0 453 CGContextDrawShading (state.context, state.shading);
michael@0 454 - } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
michael@0 455 + } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
michael@0 456 + state.action == DO_LAYER) {
michael@0 457 _cairo_quartz_draw_image (&state, op);
michael@0 458 } else if (state.action != DO_NOTHING) {
michael@0 459 rv = CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 460 }
michael@0 461
michael@0 462 _cairo_quartz_teardown_state (&state);
michael@0 463
michael@0 464 ND((stderr, "-- paint\n"));
michael@0 465 @@ -2291,17 +2381,18 @@ _cairo_quartz_surface_fill (void *abstra
michael@0 466 // with the shading
michael@0 467 if (fill_rule == CAIRO_FILL_RULE_WINDING)
michael@0 468 CGContextClip (state.context);
michael@0 469 else
michael@0 470 CGContextEOClip (state.context);
michael@0 471
michael@0 472 CGContextConcatCTM (state.context, state.transform);
michael@0 473 CGContextDrawShading (state.context, state.shading);
michael@0 474 - } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
michael@0 475 + } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
michael@0 476 + state.action == DO_LAYER) {
michael@0 477 if (fill_rule == CAIRO_FILL_RULE_WINDING)
michael@0 478 CGContextClip (state.context);
michael@0 479 else
michael@0 480 CGContextEOClip (state.context);
michael@0 481
michael@0 482 _cairo_quartz_draw_image (&state, op);
michael@0 483 } else if (state.action != DO_NOTHING) {
michael@0 484 rv = CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 485 @@ -2416,17 +2507,18 @@ _cairo_quartz_surface_stroke (void *abst
michael@0 486 if (rv)
michael@0 487 goto BAIL;
michael@0 488
michael@0 489 if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr)
michael@0 490 path_for_unbounded = CGContextCopyPathPtr (state.context);
michael@0 491
michael@0 492 if (state.action == DO_SOLID || state.action == DO_PATTERN) {
michael@0 493 CGContextStrokePath (state.context);
michael@0 494 - } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
michael@0 495 + } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
michael@0 496 + state.action == DO_LAYER) {
michael@0 497 CGContextReplacePathWithStrokedPath (state.context);
michael@0 498 CGContextClip (state.context);
michael@0 499
michael@0 500 CGContextSetCTM (state.context, origCTM);
michael@0 501 _cairo_quartz_draw_image (&state, op);
michael@0 502 } else if (state.action == DO_SHADING) {
michael@0 503 CGContextReplacePathWithStrokedPath (state.context);
michael@0 504 CGContextClip (state.context);
michael@0 505 @@ -2511,17 +2603,18 @@ _cairo_quartz_surface_show_glyphs (void
michael@0 506 &glyph_extents, NULL);
michael@0 507 state = _cairo_quartz_setup_state (surface, source, op, &glyph_extents);
michael@0 508 } else {
michael@0 509 state = _cairo_quartz_setup_state (surface, source, op, NULL);
michael@0 510 }
michael@0 511
michael@0 512 if (state.action == DO_SOLID || state.action == DO_PATTERN) {
michael@0 513 CGContextSetTextDrawingMode (state.context, kCGTextFill);
michael@0 514 - } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE || state.action == DO_SHADING) {
michael@0 515 + } else if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
michael@0 516 + state.action == DO_SHADING || state.action == DO_LAYER) {
michael@0 517 CGContextSetTextDrawingMode (state.context, kCGTextClip);
michael@0 518 isClipping = TRUE;
michael@0 519 } else {
michael@0 520 if (state.action != DO_NOTHING)
michael@0 521 rv = CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 522 goto BAIL;
michael@0 523 }
michael@0 524
michael@0 525 @@ -2622,17 +2715,18 @@ _cairo_quartz_surface_show_glyphs (void
michael@0 526
michael@0 527 CGContextShowGlyphsWithAdvances (state.context,
michael@0 528 cg_glyphs,
michael@0 529 cg_advances,
michael@0 530 num_glyphs);
michael@0 531
michael@0 532 CGContextSetCTM (state.context, ctm);
michael@0 533
michael@0 534 - if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE) {
michael@0 535 + if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
michael@0 536 + state.action == DO_LAYER) {
michael@0 537 _cairo_quartz_draw_image (&state, op);
michael@0 538 } else if (state.action == DO_SHADING) {
michael@0 539 CGContextConcatCTM (state.context, state.transform);
michael@0 540 CGContextDrawShading (state.context, state.shading);
michael@0 541 }
michael@0 542
michael@0 543 BAIL:
michael@0 544 if (didForceFontSmoothing)
michael@0 545 @@ -2679,17 +2773,17 @@ _cairo_quartz_surface_mask_with_surface
michael@0 546 cairo_clip_t *clip)
michael@0 547 {
michael@0 548 CGRect rect;
michael@0 549 CGImageRef img;
michael@0 550 cairo_surface_t *pat_surf = mask->surface;
michael@0 551 cairo_status_t status = CAIRO_STATUS_SUCCESS;
michael@0 552 CGAffineTransform ctm, mask_matrix;
michael@0 553
michael@0 554 - status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
michael@0 555 + status = _cairo_surface_to_cgimage (pat_surf, &img);
michael@0 556 if (status)
michael@0 557 return status;
michael@0 558 if (img == NULL) {
michael@0 559 if (!_cairo_operator_bounded_by_mask (op))
michael@0 560 CGContextClearRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
michael@0 561 return CAIRO_STATUS_SUCCESS;
michael@0 562 }
michael@0 563
michael@0 564 @@ -2869,17 +2963,17 @@ _cairo_quartz_surface_clipper_intersect_
michael@0 565 }
michael@0 566
michael@0 567 // XXXtodo implement show_page; need to figure out how to handle begin/end
michael@0 568
michael@0 569 static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
michael@0 570 CAIRO_SURFACE_TYPE_QUARTZ,
michael@0 571 _cairo_quartz_surface_create_similar,
michael@0 572 _cairo_quartz_surface_finish,
michael@0 573 - _cairo_quartz_surface_acquire_source_image,
michael@0 574 + _cairo_quartz_surface_acquire_image,
michael@0 575 _cairo_quartz_surface_release_source_image,
michael@0 576 _cairo_quartz_surface_acquire_dest_image,
michael@0 577 _cairo_quartz_surface_release_dest_image,
michael@0 578 _cairo_quartz_surface_clone_similar,
michael@0 579 NULL, /* composite */
michael@0 580 NULL, /* fill_rectangles */
michael@0 581 NULL, /* composite_trapezoids */
michael@0 582 NULL, /* create_span_renderer */
michael@0 583 @@ -2950,16 +3044,17 @@ _cairo_quartz_surface_create_internal (C
michael@0 584 CGContextSaveGState (cgContext);
michael@0 585
michael@0 586 surface->cgContext = cgContext;
michael@0 587 surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
michael@0 588
michael@0 589 surface->imageData = NULL;
michael@0 590 surface->imageSurfaceEquiv = NULL;
michael@0 591 surface->bitmapContextImage = NULL;
michael@0 592 + surface->cgLayer = NULL;
michael@0 593
michael@0 594 return surface;
michael@0 595 }
michael@0 596
michael@0 597 /**
michael@0 598 * cairo_quartz_surface_create_for_cg_context
michael@0 599 * @cgContext: the existing CGContext for which to create the surface
michael@0 600 * @width: width of the surface, in pixels
michael@0 601 @@ -3002,16 +3097,88 @@ cairo_quartz_surface_create_for_cg_conte
michael@0 602 // create_internal will have set an error
michael@0 603 return (cairo_surface_t*) surf;
michael@0 604 }
michael@0 605
michael@0 606 return (cairo_surface_t *) surf;
michael@0 607 }
michael@0 608
michael@0 609 /**
michael@0 610 + * cairo_quartz_cglayer_surface_create_similar
michael@0 611 + * @surface: The returned surface can be efficiently drawn into this
michael@0 612 + * destination surface (if tiling is not used)."
michael@0 613 + * @width: width of the surface, in pixels
michael@0 614 + * @height: height of the surface, in pixels
michael@0 615 + *
michael@0 616 + * Creates a Quartz surface backed by a CGLayer, if the given surface
michael@0 617 + * is a Quartz surface; the CGLayer is created to match the surface's
michael@0 618 + * Quartz context. Otherwise just calls cairo_surface_create_similar
michael@0 619 + * with CAIRO_CONTENT_COLOR_ALPHA.
michael@0 620 + * The returned surface can be efficiently blitted to the given surface,
michael@0 621 + * but tiling and 'extend' modes other than NONE are not so efficient.
michael@0 622 + *
michael@0 623 + * Return value: the newly created surface.
michael@0 624 + *
michael@0 625 + * Since: 1.10
michael@0 626 + **/
michael@0 627 +cairo_surface_t *
michael@0 628 +cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
michael@0 629 + unsigned int width,
michael@0 630 + unsigned int height)
michael@0 631 +{
michael@0 632 + cairo_quartz_surface_t *surf;
michael@0 633 + CGLayerRef layer;
michael@0 634 + CGContextRef ctx;
michael@0 635 + CGContextRef cgContext;
michael@0 636 +
michael@0 637 + cgContext = cairo_quartz_surface_get_cg_context (surface);
michael@0 638 + if (!cgContext)
michael@0 639 + return cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
michael@0 640 + width, height);
michael@0 641 +
michael@0 642 + if (!_cairo_quartz_verify_surface_size(width, height))
michael@0 643 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
michael@0 644 +
michael@0 645 + /* If we pass zero width or height into CGLayerCreateWithContext below,
michael@0 646 + * it will fail.
michael@0 647 + */
michael@0 648 + if (width == 0 || height == 0) {
michael@0 649 + return (cairo_surface_t*)
michael@0 650 + _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
michael@0 651 + width, height);
michael@0 652 + }
michael@0 653 +
michael@0 654 + layer = CGLayerCreateWithContext (cgContext,
michael@0 655 + CGSizeMake (width, height),
michael@0 656 + NULL);
michael@0 657 + if (!layer)
michael@0 658 + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
michael@0 659 +
michael@0 660 + ctx = CGLayerGetContext (layer);
michael@0 661 + /* Flip it when we draw into it, so that when we finally composite it
michael@0 662 + * to a flipped target, the directions match and Quartz will optimize
michael@0 663 + * the composition properly
michael@0 664 + */
michael@0 665 + CGContextTranslateCTM (ctx, 0, height);
michael@0 666 + CGContextScaleCTM (ctx, 1, -1);
michael@0 667 +
michael@0 668 + CGContextRetain (ctx);
michael@0 669 + surf = _cairo_quartz_surface_create_internal (ctx, CAIRO_CONTENT_COLOR_ALPHA,
michael@0 670 + width, height);
michael@0 671 + if (surf->base.status) {
michael@0 672 + CGLayerRelease (layer);
michael@0 673 + // create_internal will have set an error
michael@0 674 + return (cairo_surface_t*) surf;
michael@0 675 + }
michael@0 676 + surf->cgLayer = layer;
michael@0 677 +
michael@0 678 + return (cairo_surface_t *) surf;
michael@0 679 +}
michael@0 680 +
michael@0 681 +/**
michael@0 682 * cairo_quartz_surface_create
michael@0 683 * @format: format of pixels in the surface to create
michael@0 684 * @width: width of the surface, in pixels
michael@0 685 * @height: height of the surface, in pixels
michael@0 686 *
michael@0 687 * Creates a Quartz surface backed by a CGBitmap. The surface is
michael@0 688 * created using the Device RGB (or Device Gray, for A8) color space.
michael@0 689 * All Cairo operations, including those that require software
michael@0 690 diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
michael@0 691 --- a/gfx/cairo/cairo/src/cairo-quartz.h
michael@0 692 +++ b/gfx/cairo/cairo/src/cairo-quartz.h
michael@0 693 @@ -45,16 +45,21 @@
michael@0 694 CAIRO_BEGIN_DECLS
michael@0 695
michael@0 696 cairo_public cairo_surface_t *
michael@0 697 cairo_quartz_surface_create (cairo_format_t format,
michael@0 698 unsigned int width,
michael@0 699 unsigned int height);
michael@0 700
michael@0 701 cairo_public cairo_surface_t *
michael@0 702 +cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
michael@0 703 + unsigned int width,
michael@0 704 + unsigned int height);
michael@0 705 +
michael@0 706 +cairo_public cairo_surface_t *
michael@0 707 cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
michael@0 708 unsigned int width,
michael@0 709 unsigned int height);
michael@0 710
michael@0 711 cairo_public CGContextRef
michael@0 712 cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
michael@0 713
michael@0 714 cairo_public CGContextRef
michael@0 715

mercurial