diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h index d291c7666..a57e0786f 100644 --- a/src/cairo-quartz-private.h +++ b/src/cairo-quartz-private.h @@ -46,13 +46,9 @@ typedef struct cairo_quartz_surface { cairo_bool_t flipped; - int width; - int height; + cairo_rectangle_t extents; - cairo_image_surface_t *image; - pixman_region16_t *clip_region; - - CGImageRef cgImage; + pixman_region16_t *clip_region; } cairo_quartz_surface_t; cairo_bool_t diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 5bf01bb12..0f8466106 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -50,14 +50,8 @@ _cairo_quartz_surface_finish(void *abstract_surface) { cairo_quartz_surface_t *surface = abstract_surface; - if (surface->image) - cairo_surface_destroy(&surface->image->base); - - if (surface->cgImage) - CGImageRelease(surface->cgImage); - - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); return CAIRO_STATUS_SUCCESS; } @@ -67,64 +61,13 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { - cairo_quartz_surface_t *surface = abstract_surface; - CGColorSpaceRef colorSpace; - void *imageData; - UInt32 imageDataSize, rowBytes; - CGDataProviderRef dataProvider; + cairo_quartz_surface_t *surface = abstract_surface; - /* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t - * struct. If the window is ever drawn to without going through Cairo, then - * we would need to refetch the pixel data from the window into the cached - * image surface. - */ - if (surface->image) { - cairo_surface_reference(&surface->image->base); + if (CGBitmapContextGetBitmapInfo (surface->context) != 0) { + /* XXX: We can create an image out of the bitmap here */ + } - *image_out = surface->image; - return CAIRO_STATUS_SUCCESS; - } - - colorSpace = CGColorSpaceCreateDeviceRGB(); - - - rowBytes = surface->width * 4; - imageDataSize = rowBytes * surface->height; - imageData = malloc(imageDataSize); - - dataProvider = - CGDataProviderCreateWithData(NULL, imageData, imageDataSize, - ImageDataReleaseFunc); - - surface->cgImage = CGImageCreate(surface->width, - surface->height, - 8, - 32, - rowBytes, - colorSpace, - kCGImageAlphaPremultipliedFirst, - dataProvider, - NULL, - false, kCGRenderingIntentDefault); - - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(dataProvider); - - surface->image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data(imageData, - CAIRO_FORMAT_ARGB32, - surface->width, - surface->height, rowBytes); - if (surface->image->base.status) { - if (surface->cgImage) - CGImageRelease(surface->cgImage); - return CAIRO_STATUS_NO_MEMORY; - } - - *image_out = surface->image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_UNSUPPORTED; } static cairo_status_t @@ -136,19 +79,79 @@ _cairo_quartz_surface_acquire_dest_image(void *abstract_surface, void **image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + cairo_surface_t *image_surface; + unsigned char *data; + int x1, y1, x2, y2; - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = surface->image->width; - image_rect->height = surface->image->height; + x1 = surface->extents.x; + x2 = surface->extents.x + surface->extents.width; + y1 = surface->extents.y; + y2 = surface->extents.y + surface->extents.height; - *image_out = surface->image; - if (image_extra) + if (interest_rect->x > x1) + x1 = interest_rect->x; + if (interest_rect->y > y1) + y1 = interest_rect->y; + if (interest_rect->x + interest_rect->width < x2) + x2 = interest_rect->x + interest_rect->width; + if (interest_rect->y + interest_rect->height < y2) + y2 = interest_rect->y + interest_rect->height; + + if (x1 >= x2 || y1 >= y2) { + *image_out = NULL; *image_extra = NULL; + + return CAIRO_STATUS_SUCCESS; + } + + image_rect->x = x1; + image_rect->y = y1; + image_rect->width = x2 - x1; + image_rect->height = y2 - y1; + + data = calloc (image_rect->width * image_rect->height * 4, 1); + image_surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + image_rect->width, + image_rect->height, + image_rect->width * 4); + + *image_out = (cairo_image_surface_t *)image_surface; + *image_extra = data; return CAIRO_STATUS_SUCCESS; + + return CAIRO_INT_STATUS_UNSUPPORTED; } +static CGImageRef +create_image_from_surface (cairo_image_surface_t *image_surface, void *data) +{ + CGImageRef image; + CGColorSpaceRef color_space; + CGDataProviderRef data_provider; + int width, height; + + width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface); + height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface); + + color_space = CGColorSpaceCreateDeviceRGB(); + data_provider = CGDataProviderCreateWithData (NULL, data, + width * height * 4, NULL); + image = CGImageCreate (width, height, + 8, 32, + width * 4, + color_space, + kCGImageAlphaPremultipliedFirst, + data_provider, + NULL, + FALSE, kCGRenderingIntentDefault); + + CGColorSpaceRelease (color_space); + CGDataProviderRelease (data_provider); + + return image; +} static void _cairo_quartz_surface_release_dest_image(void *abstract_surface, @@ -159,25 +162,28 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface, void *image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + CGImageRef image_ref; + CGRect rect; + + image_ref = create_image_from_surface (image, image_extra); - if (surface->image == image) { - CGRect rect; + rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); - rect = CGRectMake(0, 0, surface->width, surface->height); - - if (surface->flipped) { - CGContextSaveGState (surface->context); - CGContextTranslateCTM (surface->context, 0, surface->height); - CGContextScaleCTM (surface->context, 1, -1); - } - - CGContextDrawImage(surface->context, rect, surface->cgImage); - - if (surface->flipped) - CGContextRestoreGState (surface->context); - - memset(surface->image->data, 0, surface->width * surface->height * 4); + if (surface->flipped) { + CGContextSaveGState (surface->context); + CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); + CGContextScaleCTM (surface->context, 1, -1); } + + CGContextDrawImage(surface->context, rect, image_ref); + CFRelease (image_ref); + + if (surface->flipped) { + CGContextRestoreGState (surface->context); + } + + cairo_surface_destroy ((cairo_surface_t *)image); + free (image_extra); } static cairo_int_status_t @@ -185,21 +191,17 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface, pixman_region16_t * region) { cairo_quartz_surface_t *surface = abstract_surface; - unsigned int serial; - serial = _cairo_surface_allocate_clip_serial (&surface->image->base); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); + + if (region) { + surface->clip_region = pixman_region_create (); + pixman_region_copy (surface->clip_region, region); + } else + surface->clip_region = NULL; - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); - - if (region) { - surface->clip_region = pixman_region_create (); - pixman_region_copy (surface->clip_region, region); - } else - surface->clip_region = NULL; - - return _cairo_surface_set_clip_region(&surface->image->base, - region, serial); + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -208,10 +210,7 @@ _cairo_quartz_surface_get_extents (void *abstract_surface, { cairo_quartz_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; + *rectangle = surface->extents; return CAIRO_STATUS_SUCCESS; } @@ -242,6 +241,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, int width, int height) { cairo_quartz_surface_t *surface; + CGRect clip_box; surface = malloc(sizeof(cairo_quartz_surface_t)); if (surface == NULL) { @@ -252,16 +252,14 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend); surface->context = context; - surface->width = width; - surface->height = height; - surface->image = NULL; - surface->cgImage = NULL; - surface->clip_region = NULL; + surface->clip_region = NULL; surface->flipped = flipped; - /* Set up the image surface which Cairo draws into and we blit to & from. */ - void *foo; - _cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo); + clip_box = CGContextGetClipBoundingBox (context); + surface->extents.x = clip_box.origin.x; + surface->extents.y = clip_box.origin.y; + surface->extents.width = clip_box.size.width; + surface->extents.height = clip_box.size.height; return (cairo_surface_t *) surface; }