summaryrefslogtreecommitdiff
path: root/src/cairo-quartz-image-surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-quartz-image-surface.c')
-rw-r--r--src/cairo-quartz-image-surface.c141
1 files changed, 58 insertions, 83 deletions
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;
+}