summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Schlachter <psychon@znc.in>2023-02-17 16:56:55 +0000
committerUli Schlachter <psychon@znc.in>2023-02-17 16:56:55 +0000
commitd7b9695ee431dfe43a2ae48ebfd907623c6cb6e0 (patch)
treea7c3be3ecbe83cf61fa4b795da3b72c41d866d26
parentb7d8da7d1fb36f5257feba643d0d28e99a25ab09 (diff)
parente5ed09a1ab0a8452c2f5753c3391ba66a74a3461 (diff)
downloadcairo-d7b9695ee431dfe43a2ae48ebfd907623c6cb6e0.tar.gz
Merge branch 'quartz-image-surface' into 'master'
[quartz] Cleanup and make better use of cairo_quartz_image_surface_t. See merge request cairo/cairo!317
-rw-r--r--.gitlab-ci/ignore-quartz-argb32.txt1
-rw-r--r--.gitlab-ci/ignore-quartz-rgb24.txt1
-rw-r--r--src/cairo-quartz-image-surface.c141
-rw-r--r--src/cairo-quartz-private.h20
-rw-r--r--src/cairo-quartz-surface.c267
-rw-r--r--test/reference/surface-pattern.quartz.xfail.pngbin9216 -> 9216 bytes
6 files changed, 150 insertions, 280 deletions
diff --git a/.gitlab-ci/ignore-quartz-argb32.txt b/.gitlab-ci/ignore-quartz-argb32.txt
index e00077831..fb30f4bb0 100644
--- a/.gitlab-ci/ignore-quartz-argb32.txt
+++ b/.gitlab-ci/ignore-quartz-argb32.txt
@@ -12,7 +12,6 @@ fallback
ft-show-glyphs-positioning
ft-text-vertical-layout-type1
ft-text-vertical-layout-type3
-negative-stride-image
operator-www
radial-gradient
radial-gradient-mask
diff --git a/.gitlab-ci/ignore-quartz-rgb24.txt b/.gitlab-ci/ignore-quartz-rgb24.txt
index 0941d59cd..92416e16b 100644
--- a/.gitlab-ci/ignore-quartz-rgb24.txt
+++ b/.gitlab-ci/ignore-quartz-rgb24.txt
@@ -31,7 +31,6 @@ image-surface-source
linear-gradient-one-stop
mask-ctm
mask-surface-ctm
-negative-stride-image
nil-surface
operator-www
overlapping-boxes
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index e05523459..5d7f96018 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -49,12 +49,6 @@
#define SURFACE_ERROR_INVALID_SIZE (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE)))
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
-static void
-DataProviderReleaseCallback (void *image_info, const void *data, size_t size)
-{
- free (image_info);
-}
-
static cairo_surface_t *
_cairo_quartz_image_surface_create_similar (void *asurface,
cairo_content_t content,
@@ -87,8 +81,9 @@ _cairo_quartz_image_surface_finish (void *asurface)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
- CGImageRelease (surface->image);
- cairo_surface_destroy ( (cairo_surface_t*) surface->imageSurface);
+ CGContextRelease (surface->cgContext);
+ if (surface->imageSurface)
+ cairo_surface_destroy ( (cairo_surface_t*) surface->imageSurface);
return CAIRO_STATUS_SUCCESS;
}
@@ -134,47 +129,6 @@ _cairo_quartz_image_surface_get_extents (void *asurface,
return TRUE;
}
-/* we assume some drawing happened to the image buffer; make sure it's
- * represented in the CGImage on flush()
- */
-
-static cairo_status_t
-_cairo_quartz_image_surface_flush (void *asurface,
- unsigned flags)
-{
- cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
- CGImageRef oldImage = surface->image;
- CGImageRef newImage = NULL;
- void *image_data;
-
- if (flags)
- return CAIRO_STATUS_SUCCESS;
-
- /* XXX only flush if the image has been modified. */
-
- image_data = _cairo_malloc_ab ( surface->imageSurface->height,
- surface->imageSurface->stride);
- if (unlikely (!image_data))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (image_data, surface->imageSurface->data,
- surface->imageSurface->height * surface->imageSurface->stride);
- newImage = CairoQuartzCreateCGImage (surface->imageSurface->format,
- surface->imageSurface->width,
- surface->imageSurface->height,
- surface->imageSurface->stride,
- image_data,
- TRUE,
- NULL,
- DataProviderReleaseCallback,
- image_data);
-
- surface->image = newImage;
- CGImageRelease (oldImage);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_int_status_t
_cairo_quartz_image_surface_paint (void *abstract_surface,
cairo_operator_t op,
@@ -275,7 +229,7 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
_cairo_quartz_image_surface_get_extents,
NULL, /* get_font_options */
- _cairo_quartz_image_surface_flush,
+ NULL, /*surface_flush */
NULL, /* mark_dirty_rectangle */
_cairo_quartz_image_surface_paint,
@@ -290,12 +244,9 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
* cairo_quartz_image_surface_create:
* @image_surface: a cairo image surface to wrap with a quartz image surface
*
- * Creates a Quartz surface backed by a CGImageRef that references the
+ * Creates a Quartz surface backed by a CGBitmapContext that references the
* given image surface. The resulting surface can be rendered quickly
- * when used as a source when rendering to a #cairo_quartz_surface. If
- * the data in the image surface is ever updated, cairo_surface_flush()
- * must be called on the #cairo_quartz_image_surface to ensure that the
- * CGImageRef refers to the updated data.
+ * when used as a source when rendering to a #cairo_quartz_surface.
*
* Return value: the newly created surface.
*
@@ -305,13 +256,11 @@ cairo_surface_t *
cairo_quartz_image_surface_create (cairo_surface_t *surface)
{
cairo_quartz_image_surface_t *qisurf;
-
- CGImageRef image;
-
cairo_image_surface_t *image_surface;
int width, height, stride;
cairo_format_t format;
- void *image_data;
+ CGBitmapInfo bitinfo = kCGBitmapByteOrder32Host;
+ CGColorSpaceRef colorspace;
if (surface->status)
return surface;
@@ -338,41 +287,22 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
if (qisurf == NULL)
return SURFACE_ERROR_NO_MEMORY;
- memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t));
-
- image_data = _cairo_malloc_ab (height, stride);
- if (unlikely (!image_data)) {
- free(qisurf);
- return SURFACE_ERROR_NO_MEMORY;
- }
-
- memcpy (image_data, image_surface->data, height * stride);
- image = CairoQuartzCreateCGImage (format,
- width, height,
- stride,
- image_data,
- TRUE,
- NULL,
- DataProviderReleaseCallback,
- image_data);
-
- if (!image) {
- free (qisurf);
- return SURFACE_ERROR_NO_MEMORY;
- }
-
_cairo_surface_init (&qisurf->base,
&cairo_quartz_image_surface_backend,
NULL, /* device */
_cairo_content_from_format (format),
FALSE); /* is_vector */
+ colorspace = CGColorSpaceCreateDeviceRGB ();
+ bitinfo |= format == CAIRO_FORMAT_ARGB32 ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
qisurf->width = width;
qisurf->height = height;
- qisurf->image = image;
+ qisurf->cgContext = CGBitmapContextCreate (image_surface->data, width, height, 8, image_surface->stride,
+ colorspace, bitinfo);
qisurf->imageSurface = (cairo_image_surface_t*) cairo_surface_reference(surface);
+ CGColorSpaceRelease (colorspace);
return &qisurf->base;
}
@@ -401,3 +331,48 @@ cairo_quartz_image_surface_get_image (cairo_surface_t *surface)
return (cairo_surface_t*) qsurface->imageSurface;
}
+
+/*
+ * _cairo_quartz_image_surface_get_cg_context:
+ * @surface: the Cairo Quartz surface
+ *
+ * Returns the CGContextRef that the given Quartz surface is backed
+ * by.
+ *
+ * A call to cairo_surface_flush() is required before using the
+ * CGContextRef to ensure that all pending drawing operations are
+ * finished and to restore any temporary modification cairo has made
+ * to its state. A call to cairo_surface_mark_dirty() is required
+ * after the state or the content of the CGContextRef has been
+ * modified.
+ *
+ * Return value: the CGContextRef for the given surface.
+ *
+ **/
+CGContextRef
+_cairo_quartz_image_surface_get_cg_context (cairo_surface_t *surface)
+{
+ if (surface && _cairo_surface_is_quartz_image (surface)) {
+ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *) surface;
+ return quartz->cgContext;
+ } else
+ return NULL;
+}
+
+/*
+ * _cairo_surface_is_quartz_image:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is a #cairo_quartz_surface_t
+ *
+ * Return value: True if the surface is an quartz surface
+ **/
+cairo_bool_t
+_cairo_surface_is_quartz_image (const cairo_surface_t *surface) {
+ return surface->backend == &cairo_quartz_image_surface_backend;
+}
+
+cairo_bool_t
+_cairo_quartz_image_surface_is_zero (const cairo_quartz_image_surface_t *surface) {
+ return surface->width == 0 || surface->height == 0;
+}
diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index f142f8471..4b6d2a99a 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -81,8 +81,7 @@ typedef struct cairo_quartz_image_surface {
cairo_surface_t base;
int width, height;
-
- CGImageRef image;
+ CGContextRef cgContext;
cairo_image_surface_t *imageSurface;
} cairo_quartz_image_surface_t;
@@ -92,16 +91,13 @@ _cairo_quartz_verify_surface_size(int width, int height);
cairo_private cairo_bool_t
_cairo_surface_is_quartz (const cairo_surface_t *surface);
-cairo_private CGImageRef
-CairoQuartzCreateCGImage (cairo_format_t format,
- unsigned int width,
- unsigned int height,
- unsigned int stride,
- void *data,
- cairo_bool_t interpolate,
- CGColorSpaceRef colorSpaceOverride,
- CGDataProviderReleaseDataCallback releaseCallback,
- void *releaseInfo);
+cairo_private cairo_bool_t
+_cairo_surface_is_quartz_image (const cairo_surface_t *surface);
+cairo_private cairo_bool_t
+_cairo_quartz_image_surface_is_zero (const cairo_quartz_image_surface_t *surface);
+
+cairo_private CGContextRef
+_cairo_quartz_image_surface_get_cg_context (cairo_surface_t *surface);
cairo_private CGFontRef
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index dbb6aa46f..789b110fd 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -37,6 +37,7 @@
#include "cairoint.h"
#include "cairo-quartz-private.h"
+#include "cairo-quartz-image.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-compositor-private.h"
@@ -55,6 +56,7 @@
#endif
#include <limits.h>
+#include <assert.h>
#undef QUARTZ_DEBUG
@@ -64,13 +66,30 @@
#define ND(_x) do {} while(0)
#endif
-#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0)
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation
#else
#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal
#endif
+static inline cairo_bool_t
+_is_quartz_surface (cairo_surface_t *surface) {
+ return _cairo_surface_is_quartz (surface) || _cairo_surface_is_quartz_image (surface);
+}
+
+static inline cairo_bool_t
+_cairo_quartz_surface_is_zero (cairo_quartz_surface_t* surface) {
+ return surface->extents.width == 0 || surface->extents.height == 0;
+}
+
+static inline cairo_bool_t
+_cairo_quartz_is_zero_surface (cairo_surface_t* surface) {
+ assert (_is_quartz_surface (surface));
+ if (_cairo_surface_is_quartz (surface))
+ return (_cairo_quartz_surface_is_zero ((cairo_quartz_surface_t*) surface));
+ else
+ return (_cairo_quartz_image_surface_is_zero ((cairo_quartz_image_surface_t*) surface));
+}
/**
* SECTION:cairo-quartz
@@ -119,9 +138,9 @@ typedef struct
CGImageRef image;
} cairo_quartz_snapshot_t;
-static cairo_surface_t* _cairo_quartz_snapshot_create (cairo_quartz_surface_t *surface);
-static cairo_status_t _cairo_quartz_snapshot_finish (void* surface);
-static CGImageRef _cairo_quartz_surface_snapshot_get_image (cairo_quartz_surface_t *surface);
+static cairo_surface_t* _cairo_quartz_snapshot_create (cairo_surface_t *surface);
+static cairo_status_t _cairo_quartz_snapshot_finish (void *surface);
+static CGImageRef _cairo_quartz_surface_snapshot_get_image (cairo_surface_t *surface);
static const cairo_surface_backend_t cairo_quartz_snapshot_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_QUARTZ_SNAPSHOT,
@@ -134,104 +153,6 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
unsigned int width,
unsigned int height);
-CGImageRef
-CairoQuartzCreateCGImage (cairo_format_t format,
- unsigned int width,
- unsigned int height,
- unsigned int stride,
- void *data,
- cairo_bool_t interpolate,
- CGColorSpaceRef colorSpaceOverride,
- CGDataProviderReleaseDataCallback releaseCallback,
- void *releaseInfo)
-{
- CGImageRef image = NULL;
- CGDataProviderRef dataProvider = NULL;
- CGColorSpaceRef colorSpace = colorSpaceOverride;
- CGBitmapInfo bitinfo = kCGBitmapByteOrder32Host;
- int bitsPerComponent, bitsPerPixel;
-
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- if (colorSpace == NULL)
- colorSpace = CGColorSpaceCreateDeviceRGB ();
- bitinfo |= kCGImageAlphaPremultipliedFirst;
- bitsPerComponent = 8;
- bitsPerPixel = 32;
- break;
-
- case CAIRO_FORMAT_RGB24:
- if (colorSpace == NULL)
- colorSpace = CGColorSpaceCreateDeviceRGB ();
- bitinfo |= kCGImageAlphaNoneSkipFirst;
- bitsPerComponent = 8;
- bitsPerPixel = 32;
- break;
-
- case CAIRO_FORMAT_A8:
- bitsPerComponent = 8;
- bitsPerPixel = 8;
- break;
-
- case CAIRO_FORMAT_A1:
-#ifdef WORDS_BIGENDIAN
- bitsPerComponent = 1;
- bitsPerPixel = 1;
- break;
-#endif
-
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB96F:
- case CAIRO_FORMAT_RGBA128F:
- case CAIRO_FORMAT_INVALID:
- default:
- return NULL;
- }
-
- dataProvider = CGDataProviderCreateWithData (releaseInfo,
- data,
- height * stride,
- releaseCallback);
-
- if (unlikely (!dataProvider)) {
- // manually release
- if (releaseCallback)
- releaseCallback (releaseInfo, data, height * stride);
- goto FINISH;
- }
-
- if (format == CAIRO_FORMAT_A8 || format == CAIRO_FORMAT_A1) {
- cairo_quartz_float_t decode[] = {1.0, 0.0};
- image = CGImageMaskCreate (width, height,
- bitsPerComponent,
- bitsPerPixel,
- stride,
- dataProvider,
- decode,
- interpolate);
- } else
- image = CGImageCreate (width, height,
- bitsPerComponent,
- bitsPerPixel,
- stride,
- colorSpace,
- bitinfo,
- dataProvider,
- NULL,
- interpolate,
- kCGRenderingIntentDefault);
-
-FINISH:
-
- CGDataProviderRelease (dataProvider);
-
- if (colorSpace != colorSpaceOverride)
- CGColorSpaceRelease (colorSpace);
-
- return image;
-}
-
static inline cairo_bool_t
_cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc)
{
@@ -682,12 +603,6 @@ CairoQuartzCreateGradientFunction (const cairo_gradient_pattern_t *gradient,
&gradient_callbacks);
}
-static void
-DataProviderReleaseCallback (void *info, const void *data, size_t size)
-{
- free (info);
-}
-
static cairo_status_t
_cairo_surface_to_cgimage (cairo_surface_t *source,
cairo_rectangle_int_t *extents,
@@ -697,25 +612,19 @@ _cairo_surface_to_cgimage (cairo_surface_t *source,
CGImageRef *image_out)
{
cairo_status_t status;
- cairo_image_surface_t *image_surface;
- void *image_data, *image_extra;
+ cairo_quartz_image_surface_t *image_surface;
+ void *image_extra;
cairo_bool_t acquired = FALSE;
- if (source->backend && source->backend->type == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
- cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source;
- *image_out = CGImageRetain (surface->image);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (_cairo_surface_is_quartz (source)) {
- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source;
- if (IS_EMPTY (surface)) {
+ if (_is_quartz_surface (source)) {
+ CGContextRef cgContext = cairo_quartz_surface_get_cg_context(source);
+ if (_cairo_quartz_is_zero_surface (source)) {
*image_out = NULL;
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
- if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) {
- *image_out = _cairo_quartz_surface_snapshot_get_image (surface);
+ if (_cairo_quartz_is_cgcontext_bitmap_context (cgContext)) {
+ *image_out = _cairo_quartz_surface_snapshot_get_image (source);
return CAIRO_STATUS_SUCCESS;
}
@@ -724,80 +633,60 @@ _cairo_surface_to_cgimage (cairo_surface_t *source,
}
if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
- image_surface = (cairo_image_surface_t *)
- cairo_image_surface_create (format, extents->width, extents->height);
- if (unlikely (image_surface->base.status)) {
- status = image_surface->base.status;
- cairo_surface_destroy (&image_surface->base);
+ cairo_image_surface_t *surface =
+ (cairo_image_surface_t*)cairo_image_surface_create (format, extents->width,
+ extents->height);
+ if (unlikely (surface->base.status)) {
+ status = surface->base.status;
+ cairo_surface_destroy (&surface->base);
return status;
}
status = _cairo_recording_surface_replay_with_clip (source,
matrix,
- &image_surface->base,
+ &surface->base,
NULL,
FALSE);
if (unlikely (status)) {
- cairo_surface_destroy (&image_surface->base);
+ cairo_surface_destroy (&surface->base);
return status;
}
+ image_surface =
+ (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
cairo_matrix_init_identity (matrix);
}
else {
- status = _cairo_surface_acquire_source_image (source, &image_surface,
+ cairo_image_surface_t *surface;
+ status = _cairo_surface_acquire_source_image (source, &surface,
&image_extra);
if (unlikely (status))
return status;
- acquired = TRUE;
- }
-
- if (image_surface->width == 0 || image_surface->height == 0) {
- *image_out = NULL;
- if (acquired)
- _cairo_surface_release_source_image (source, image_surface, image_extra);
+ image_surface =
+ (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
+ status = image_surface->base.status;
+ if (status)
+ _cairo_surface_release_source_image (source, surface, image_extra);
else
- cairo_surface_destroy (&image_surface->base);
-
- return status;
+ acquired = TRUE;
}
- image_data = _cairo_malloc_ab (image_surface->height, image_surface->stride);
- if (unlikely (!image_data))
- {
- if (acquired)
- _cairo_surface_release_source_image (source, image_surface, image_extra);
- else
- cairo_surface_destroy (&image_surface->base);
-
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ *image_out = NULL;
+ if (image_surface->width > 0 && image_surface->height > 0) {
+ *image_out = _cairo_quartz_surface_snapshot_get_image (&image_surface->base);
+ status = CAIRO_STATUS_SUCCESS;
}
- // The last row of data may have less than stride bytes so make sure we
- // only copy the minimum amount required from that row.
- memcpy (image_data, image_surface->data,
- (image_surface->height - 1) * image_surface->stride +
- cairo_format_stride_for_width (image_surface->format,
- image_surface->width));
- *image_out = CairoQuartzCreateCGImage (image_surface->format,
- image_surface->width,
- image_surface->height,
- image_surface->stride,
- image_data,
- TRUE,
- NULL,
- DataProviderReleaseCallback,
- image_data);
+ if (acquired) {
+ _cairo_surface_release_source_image (source, image_surface->imageSurface, image_extra);
+ image_surface->imageSurface = NULL;
+ }
+ cairo_surface_destroy (&image_surface->base);
/* TODO: differentiate memory error and unsupported surface type */
if (unlikely (*image_out == NULL))
status = CAIRO_INT_STATUS_UNSUPPORTED;
- if (acquired)
- _cairo_surface_release_source_image (source, image_surface, image_extra);
- else
- cairo_surface_destroy (&image_surface->base);
-
return status;
}
@@ -1367,7 +1256,7 @@ _cairo_quartz_surface_map_to_image (void *abstract_surface,
unsigned char *imageData;
cairo_format_t format;
- if (IS_EMPTY (surface))
+ if (_cairo_quartz_is_zero_surface (&surface->base))
return (cairo_image_surface_t *) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
if (! _cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext))
@@ -1439,7 +1328,7 @@ _cairo_quartz_surface_finish (void *abstract_surface)
ND ((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
- if (IS_EMPTY (surface))
+ if (_cairo_quartz_is_zero_surface (&surface->base))
return CAIRO_STATUS_SUCCESS;
/* Restore our saved gstate that we use to reset clipping */
@@ -2086,7 +1975,7 @@ _cairo_quartz_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clip
ND ((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path));
- if (IS_EMPTY (surface))
+ if (_cairo_quartz_is_zero_surface (&surface->base))
return CAIRO_STATUS_SUCCESS;
if (path == NULL) {
@@ -2184,7 +2073,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
surface->extents.height = height;
surface->virtual_extents = surface->extents;
- if (IS_EMPTY (surface)) {
+ if (_cairo_quartz_is_zero_surface (&surface->base)) {
surface->cgContext = NULL;
surface->cgContextBaseCTM = CGAffineTransformIdentity;
surface->base.is_clear = TRUE;
@@ -2372,8 +2261,14 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface)
if (surface && _cairo_surface_is_quartz (surface)) {
cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *) surface;
return quartz->cgContext;
- } else
- return NULL;
+ }
+
+ if (surface && _cairo_surface_is_quartz_image (surface)) {
+ cairo_quartz_image_surface_t *quartz = (cairo_quartz_image_surface_t *) surface;
+ return quartz->cgContext;
+ }
+
+ return NULL;
}
/**
@@ -2391,12 +2286,15 @@ _cairo_surface_is_quartz (const cairo_surface_t *surface)
}
cairo_surface_t*
-_cairo_quartz_snapshot_create (cairo_quartz_surface_t *surface)
+_cairo_quartz_snapshot_create (cairo_surface_t *surface)
{
cairo_quartz_snapshot_t *snapshot = NULL;
+ CGContextRef cgContext;
+ if (!surface || ! _is_quartz_surface (surface) || _cairo_quartz_is_zero_surface (surface))
+ return NULL;
- if (!surface || !_cairo_surface_is_quartz (&surface->base) || IS_EMPTY (surface) ||
- ! _cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext))
+ if (_cairo_surface_is_quartz (surface) &&
+ ! _cairo_quartz_is_cgcontext_bitmap_context (((cairo_quartz_surface_t*)surface)->cgContext))
return NULL;
snapshot = _cairo_malloc (sizeof (cairo_quartz_snapshot_t));
@@ -2405,10 +2303,13 @@ _cairo_quartz_snapshot_create (cairo_quartz_surface_t *surface)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
memset (snapshot, 0, sizeof (cairo_quartz_snapshot_t));
+ cgContext = cairo_quartz_surface_get_cg_context (surface);
_cairo_surface_init (&snapshot->base,
&cairo_quartz_snapshot_backend,
NULL, CAIRO_CONTENT_COLOR_ALPHA, FALSE);
- snapshot->image = CGBitmapContextCreateImage (surface->cgContext);
+ snapshot->image = CGBitmapContextCreateImage (cgContext);
+ _cairo_surface_attach_snapshot (surface, &snapshot->base, NULL);
+ cairo_surface_destroy (&snapshot->base); // The surface has reffed the snapshot so we must unref it here.
return &snapshot->base;
}
@@ -2423,18 +2324,18 @@ _cairo_quartz_snapshot_finish (void *surface)
}
CGImageRef
-_cairo_quartz_surface_snapshot_get_image (cairo_quartz_surface_t *surface)
+_cairo_quartz_surface_snapshot_get_image (cairo_surface_t *surface)
{
- cairo_surface_t *snapshot =
- _cairo_surface_has_snapshot (&surface->base, &cairo_quartz_snapshot_backend);
+ cairo_surface_t *snapshot;
+ assert (_is_quartz_surface (surface));
+ snapshot =
+ _cairo_surface_has_snapshot (surface, &cairo_quartz_snapshot_backend);
if (unlikely (!snapshot))
{
snapshot = _cairo_quartz_snapshot_create (surface);
if (unlikely (!snapshot || cairo_surface_status (snapshot)))
return NULL;
- _cairo_surface_attach_snapshot (&surface->base, snapshot, NULL);
- cairo_surface_destroy (snapshot);
}
return CGImageRetain (((cairo_quartz_snapshot_t*)snapshot)->image);
diff --git a/test/reference/surface-pattern.quartz.xfail.png b/test/reference/surface-pattern.quartz.xfail.png
index 4ac47de5e..42938f026 100644
--- a/test/reference/surface-pattern.quartz.xfail.png
+++ b/test/reference/surface-pattern.quartz.xfail.png
Binary files differ