mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-03-06 08:10:36 +01:00
[quartz] Cleanup and make better use of cairo_quartz_image_surface_t.
Use a CGBitmapContext mapping the underlying image surface's data instead of maintaining a CGImage. Generalize the quartz surface snapshot mechanism to work with both cairo_quartz_surface_t and cairo_quartz_image_surface_t and to use the latter to get a CGContext around non-quartz surfaces. Use this snapshot machanism to get a CGImageRef when needed from a cairo_quartz_image_surface_t.
This commit is contained in:
parent
6b5519626c
commit
198d1792cf
5 changed files with 135 additions and 276 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,45 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,11 @@ _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 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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -64,13 +65,24 @@
|
|||
#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_EMPTY(void *abstract_surface) {
|
||||
if (_cairo_surface_is_quartz ((cairo_surface_t*)abstract_surface)) {
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t*)abstract_surface;
|
||||
return surface->extents.width == 0 || surface->extents.height == 0;
|
||||
}
|
||||
if (_cairo_surface_is_quartz_image ((cairo_surface_t*)abstract_surface)) {
|
||||
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*)abstract_surface;
|
||||
return surface->width == 0 || surface->height == 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* SECTION:cairo-quartz
|
||||
|
|
@ -119,9 +131,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 +146,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 +596,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 +605,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 (_cairo_surface_is_quartz (source) || _cairo_surface_is_quartz_image (source)) {
|
||||
CGContextRef cgContext = cairo_quartz_surface_get_cg_context(source);
|
||||
if (IS_EMPTY (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 +626,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;
|
||||
}
|
||||
|
||||
|
|
@ -2372,8 +2254,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 +2279,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_EMPTY (surface)) //IS_EMPTY returns true if the surface type is wrong.
|
||||
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 +2296,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 +2317,19 @@ _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 (_cairo_surface_is_quartz (surface) ||
|
||||
_cairo_surface_is_quartz_image (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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue