gecko/gfx/cairo/quartz-image-surface.patch
2008-02-07 12:02:40 -08:00

730 lines
26 KiB
Diff

diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
@@ -46,12 +46,11 @@ typedef struct cairo_quartz_surface {
typedef struct cairo_quartz_surface {
cairo_surface_t base;
- void *imageData;
-
- cairo_surface_t *imageSurfaceEquiv;
-
CGContextRef cgContext;
CGAffineTransform cgContextBaseCTM;
+
+ void *imageData;
+ cairo_surface_t *imageSurfaceEquiv;
cairo_rectangle_int_t extents;
@@ -66,6 +65,30 @@ typedef struct cairo_quartz_surface {
CGShadingRef sourceShading;
CGPatternRef sourcePattern;
} cairo_quartz_surface_t;
+
+typedef struct cairo_quartz_image_surface {
+ cairo_surface_t base;
+
+ cairo_rectangle_int_t extents;
+
+ CGImageRef image;
+ cairo_image_surface_t *imageSurface;
+} cairo_quartz_image_surface_t;
+
+cairo_bool_t
+_cairo_quartz_verify_surface_size(int width, int height);
+
+CGImageRef
+_cairo_quartz_create_cgimage (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);
+
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
#if CAIRO_HAS_ATSUI_FONT
diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -140,7 +140,8 @@ static void quartz_ensure_symbols(void)
#define CG_MAX_WIDTH USHRT_MAX
/* is the desired size of the surface within bounds? */
-static cairo_bool_t verify_surface_size(int width, int height)
+cairo_bool_t
+_cairo_quartz_verify_surface_size(int width, int height)
{
/* hmmm, allow width, height == 0 ? */
if (width < 0 || height < 0) {
@@ -393,114 +394,93 @@ CreateGradientFunction (cairo_gradient_p
&callbacks);
}
-/* generic cairo surface -> cairo_quartz_surface_t function */
-static cairo_int_status_t
-_cairo_quartz_surface_to_quartz (cairo_surface_t *target,
- cairo_surface_t *pat_surf,
- cairo_quartz_surface_t **quartz_surf)
+/* Obtain a CGImageRef from a cairo_surface_t * */
+
+static CGImageRef
+_cairo_surface_to_cgimage (cairo_surface_t *target,
+ cairo_surface_t *source)
{
+ cairo_surface_type_t stype = cairo_surface_get_type (source);
+ cairo_image_surface_t *isurf;
+ CGImageRef image, image2;
+ void *image_extra;
- if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
- /* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
- * just create the CGImage directly!
- */
-
- cairo_surface_t *ref_type = target;
- cairo_surface_t *new_surf = NULL;
- cairo_rectangle_int_t rect;
- cairo_status_t status;
-
- if (ref_type == NULL)
- ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-
- status = _cairo_surface_get_extents (pat_surf, &rect);
- if (status)
- return status;
-
- status = _cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
- rect.width, rect.height, &new_surf);
- if (target == NULL)
- cairo_surface_destroy(ref_type);
-
- if (status)
- return status;
-
- if (new_surf &&
- cairo_surface_get_type (new_surf) != CAIRO_SURFACE_TYPE_QUARTZ)
- {
- ND((stderr, "got a non-quartz surface, format=%d width=%u height=%u type=%d\n", cairo_surface_get_type (pat_surf), rect.width, rect.height, cairo_surface_get_type (new_surf)));
- cairo_surface_destroy (new_surf);
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- *quartz_surf = (cairo_quartz_surface_t *) new_surf;
- } else {
- /* If it's a quartz surface, we can try to see if it's a CGBitmapContext;
- * we do this when we call CGBitmapContextCreateImage below.
- */
- cairo_surface_reference (pat_surf);
- *quartz_surf = (cairo_quartz_surface_t*) pat_surf;
+ if (stype == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
+ cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source;
+ return CGImageRetain (surface->image);
}
- return CAIRO_STATUS_SUCCESS;
+ if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source;
+ image = CGBitmapContextCreateImage (surface->cgContext);
+ if (image)
+ return image;
+ }
+
+ if (stype != CAIRO_SURFACE_TYPE_IMAGE) {
+ cairo_status_t status =
+ _cairo_surface_acquire_source_image (source, &isurf, &image_extra);
+ if (status)
+ return NULL;
+ } else {
+ isurf = (cairo_image_surface_t *) source;
+ }
+
+ image2 = _cairo_quartz_create_cgimage (isurf->format,
+ isurf->width,
+ isurf->height,
+ isurf->stride,
+ isurf->data,
+ FALSE,
+ NULL, NULL, NULL);
+
+ image = CGImageCreateCopy (image2);
+ CGImageRelease (image2);
+
+ if ((cairo_surface_t*) isurf != source)
+ _cairo_surface_release_source_image (source, isurf, image_extra);
+
+ return image;
}
/* Generic cairo_pattern -> CGPattern function */
+
+typedef struct {
+ CGImageRef image;
+ CGRect imageBounds;
+ cairo_bool_t do_reflect;
+} SurfacePatternDrawInfo;
+
static void
-SurfacePatternDrawFunc (void *info, CGContextRef context)
+SurfacePatternDrawFunc (void *ainfo, CGContextRef context)
{
- cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
- cairo_surface_t *pat_surf = spat->surface;
- cairo_int_status_t status;
+ SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo;
- cairo_quartz_surface_t *quartz_surf;
- CGImageRef img;
- CGRect imageBounds;
+ CGContextTranslateCTM (context, 0, info->imageBounds.size.height);
+ CGContextScaleCTM (context, 1, -1);
- status = _cairo_quartz_surface_to_quartz (NULL, pat_surf, &quartz_surf);
- if (status)
- return;
+ CGContextDrawImage (context, info->imageBounds, info->image);
+ if (info->do_reflect) {
+ /* draw 3 more copies of the image, flipped. */
+ CGContextTranslateCTM (context, 0, 2 * info->imageBounds.size.height);
+ CGContextScaleCTM (context, 1, -1);
+ CGContextDrawImage (context, info->imageBounds, info->image);
+ CGContextTranslateCTM (context, 2 * info->imageBounds.size.width, 0);
+ CGContextScaleCTM (context, -1, 1);
+ CGContextDrawImage (context, info->imageBounds, info->image);
+ CGContextTranslateCTM (context, 0, 2 * info->imageBounds.size.height);
+ CGContextScaleCTM (context, 1, -1);
+ CGContextDrawImage (context, info->imageBounds, info->image);
+ }
+}
- img = CGBitmapContextCreateImage (quartz_surf->cgContext);
- if (!img) {
- // ... give up.
- ND((stderr, "CGBitmapContextCreateImage failed\n"));
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- cairo_surface_destroy ((cairo_surface_t*)quartz_surf);
- return;
- }
+static void
+SurfacePatternReleaseInfoFunc (void *ainfo)
+{
+ SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo;
- /* XXXtodo WHY does this need to be flipped? Writing this stuff
- * to disk shows that in both this path and the path above the source image
- * has an identical orientation, and the destination context at all times has a Y
- * flip. So why do we need to flip in this case?
- */
- if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
- CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
- CGContextScaleCTM (context, 1, -1);
- }
-
- imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
- imageBounds.origin.x = 0;
- imageBounds.origin.y = 0;
-
- CGContextDrawImage (context, imageBounds, img);
- if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
- /* draw 3 more copies of the image, flipped. */
- CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
- CGContextScaleCTM (context, 1, -1);
- CGContextDrawImage (context, imageBounds, img);
- CGContextTranslateCTM (context, 2 * imageBounds.size.width, 0);
- CGContextScaleCTM (context, -1, 1);
- CGContextDrawImage (context, imageBounds, img);
- CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
- CGContextScaleCTM (context, 1, -1);
- CGContextDrawImage (context, imageBounds, img);
- }
-
- CGImageRelease (img);
-
- cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
+ CGImageRelease (info->image);
+ free (info);
}
/* Borrowed from cairo-meta-surface */
@@ -532,48 +512,62 @@ _init_pattern_with_snapshot (cairo_patte
static cairo_int_status_t
_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest,
- cairo_pattern_t *abspat,
+ cairo_pattern_t *apattern,
CGPatternRef *cgpat)
{
- cairo_surface_pattern_t *spat;
+ cairo_surface_pattern_t *spattern;
cairo_surface_t *pat_surf;
cairo_rectangle_int_t extents;
+ CGImageRef image;
CGRect pbounds;
CGAffineTransform ptransform, stransform;
CGPatternCallbacks cb = { 0,
SurfacePatternDrawFunc,
- (CGFunctionReleaseInfoCallback) cairo_pattern_destroy };
+ SurfacePatternReleaseInfoFunc };
+ SurfacePatternDrawInfo *info;
float rw, rh;
cairo_status_t status;
- cairo_pattern_union_t *snap_pattern = NULL;
- cairo_pattern_t *target_pattern = abspat;
+ cairo_matrix_t m;
- cairo_matrix_t m;
/* SURFACE is the only type we'll handle here */
- if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
+ if (apattern->type != CAIRO_PATTERN_TYPE_SURFACE)
return CAIRO_INT_STATUS_UNSUPPORTED;
- spat = (cairo_surface_pattern_t *) abspat;
- pat_surf = spat->surface;
+ spattern = (cairo_surface_pattern_t *) apattern;
+ pat_surf = spattern->surface;
status = _cairo_surface_get_extents (pat_surf, &extents);
if (status)
return status;
+ image = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf);
+ if (image == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ info = malloc(sizeof(SurfacePatternDrawInfo));
+ if (!info)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ /* XXX -- if we're printing, we may need to call CGImageCreateCopy to make sure
+ * that the data will stick around for this image when the printer gets to it.
+ * Otherwise, the underlying data store may disappear from under us!
+ *
+ * _cairo_surface_to_cgimage will copy when it converts non-Quartz surfaces,
+ * since the Quartz surfaces have a higher chance of sticking around. If the
+ * source is a quartz image surface, then it's set up to retain a ref to the
+ * image surface that it's backed by.
+ */
+ info->image = image;
+
+ info->imageBounds = CGRectMake (0, 0, extents.width, extents.height);
+ info->do_reflect = (spattern->base.extend == CAIRO_EXTEND_REFLECT);
+
pbounds.origin.x = 0;
pbounds.origin.y = 0;
- // kjs seems to indicate this should work (setting to 0,0 to avoid
- // tiling); however, the pattern CTM scaling ends up being NaN in
- // the pattern draw function if either rw or rh are 0.
- // XXXtodo get pattern drawing working with extend options
- // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
- if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
- /* XXX broken; need to emulate by reflecting the image into 4 quadrants
- * and then tiling that
- */
+ if (spattern->base.extend == CAIRO_EXTEND_REFLECT) {
pbounds.size.width = 2 * extents.width;
pbounds.size.height = 2 * extents.height;
} else {
@@ -583,7 +577,7 @@ _cairo_quartz_cairo_repeating_surface_pa
rw = pbounds.size.width;
rh = pbounds.size.height;
- m = spat->base.matrix;
+ m = spattern->base.matrix;
cairo_matrix_invert(&m);
_cairo_quartz_cairo_matrix_to_quartz (&m, &stransform);
@@ -601,25 +595,14 @@ _cairo_quartz_cairo_repeating_surface_pa
ND((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
#endif
+ *cgpat = CGPatternCreate (info,
+ pbounds,
+ ptransform,
+ rw, rh,
+ kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
+ TRUE,
+ &cb);
- /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
- other block if it doesn't fafect performance */
- if (1 /* context is for printing */) {
- snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
- target_pattern = (cairo_pattern_t*) snap_pattern;
- _init_pattern_with_snapshot (target_pattern, abspat);
- } else {
- cairo_pattern_reference (abspat);
- target_pattern = abspat;
- }
-
- *cgpat = CGPatternCreate (target_pattern,
- pbounds,
- ptransform,
- rw, rh,
- kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */
- TRUE,
- &cb);
return CAIRO_STATUS_SUCCESS;
}
@@ -785,7 +768,6 @@ _cairo_quartz_setup_source (cairo_quartz
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
cairo_surface_t *pat_surf = spat->surface;
- cairo_quartz_surface_t *quartz_surf;
CGImageRef img;
cairo_matrix_t m = spat->base.matrix;
cairo_rectangle_int_t extents;
@@ -794,16 +776,7 @@ _cairo_quartz_setup_source (cairo_quartz
CGRect srcRect;
cairo_fixed_t fw, fh;
- status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf);
- if (status)
- return DO_UNSUPPORTED;
-
- surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
-
- if (IS_EMPTY(quartz_surf))
- return DO_NOTHING;
-
- img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+ img = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf);
if (!img)
return DO_UNSUPPORTED;
@@ -1132,7 +1105,7 @@ _cairo_quartz_surface_create_similar (vo
return NULL;
// verify width and height of surface
- if (!verify_surface_size(width, height)) {
+ if (!_cairo_quartz_verify_surface_size(width, height)) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
@@ -1142,12 +1115,12 @@ _cairo_quartz_surface_create_similar (vo
static cairo_status_t
_cairo_quartz_surface_clone_similar (void *abstract_surface,
- cairo_surface_t *src,
- int src_x,
- int src_y,
- int width,
- int height,
- cairo_surface_t **clone_out)
+ cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ cairo_surface_t **clone_out)
{
cairo_quartz_surface_t *new_surface = NULL;
cairo_format_t new_format;
@@ -1156,97 +1129,58 @@ _cairo_quartz_surface_clone_similar (voi
*clone_out = NULL;
// verify width and height of surface
- if (!verify_surface_size(width, height)) {
+ if (!_cairo_quartz_verify_surface_size(width, height)) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_QUARTZ) {
+ if (width == 0 || height == 0) {
+ *clone_out = (cairo_surface_t*)
+ _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
+ width, height);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (src->backend->type == CAIRO_SURFACE_TYPE_QUARTZ) {
cairo_quartz_surface_t *qsurf = (cairo_quartz_surface_t *) src;
if (IS_EMPTY(qsurf)) {
- *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, qsurf->extents.width, qsurf->extents.height);
+ *clone_out = (cairo_surface_t*)
+ _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
+ qsurf->extents.width, qsurf->extents.height);
return CAIRO_STATUS_SUCCESS;
}
-
- quartz_image = CGBitmapContextCreateImage (qsurf->cgContext);
- new_format = CAIRO_FORMAT_ARGB32; /* XXX bogus; recover a real format from the image */
- } else if (_cairo_surface_is_image (src)) {
- cairo_image_surface_t *isurf = (cairo_image_surface_t *) src;
- CGDataProviderRef dataProvider;
- CGColorSpaceRef cgColorspace;
- CGBitmapInfo bitinfo;
- int bitsPerComponent, bitsPerPixel;
-
- if (isurf->width == 0 || isurf->height == 0) {
- *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, isurf->width, isurf->height);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (isurf->format == CAIRO_FORMAT_ARGB32) {
- cgColorspace = CGColorSpaceCreateDeviceRGB();
- bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
- bitsPerComponent = 8;
- bitsPerPixel = 32;
- } else if (isurf->format == CAIRO_FORMAT_RGB24) {
- cgColorspace = CGColorSpaceCreateDeviceRGB();
- bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
- bitsPerComponent = 8;
- bitsPerPixel = 32;
- } else if (isurf->format == CAIRO_FORMAT_A8) {
- cgColorspace = CGColorSpaceCreateDeviceGray();
- bitinfo = kCGImageAlphaNone;
- bitsPerComponent = 8;
- bitsPerPixel = 8;
- } else {
- /* SUPPORT A1, maybe */
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- new_format = isurf->format;
-
- dataProvider = CGDataProviderCreateWithData (NULL,
- isurf->data,
- isurf->height * isurf->stride,
- NULL);
-
- quartz_image = CGImageCreate (isurf->width, isurf->height,
- bitsPerComponent,
- bitsPerPixel,
- isurf->stride,
- cgColorspace,
- bitinfo,
- dataProvider,
- NULL,
- false,
- kCGRenderingIntentDefault);
- CGDataProviderRelease (dataProvider);
- CGColorSpaceRelease (cgColorspace);
- } else {
- return CAIRO_INT_STATUS_UNSUPPORTED;
}
+ quartz_image = _cairo_surface_to_cgimage ((cairo_surface_t*) abstract_surface, src);
if (!quartz_image)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ new_format = CAIRO_FORMAT_ARGB32; /* assumed */
+ if (_cairo_surface_is_image (src)) {
+ new_format = ((cairo_image_surface_t *) src)->format;
+ }
+
new_surface = (cairo_quartz_surface_t *)
- cairo_quartz_surface_create (new_format,
- CGImageGetWidth (quartz_image),
- CGImageGetHeight (quartz_image));
+ cairo_quartz_surface_create (new_format, width, height);
if (!new_surface || new_surface->base.status) {
CGImageRelease (quartz_image);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
+ CGContextSaveGState (new_surface->cgContext);
+
CGContextSetCompositeOperation (new_surface->cgContext,
kPrivateCGCompositeCopy);
- quartz_image_to_png (quartz_image, NULL);
+ CGContextTranslateCTM (new_surface->cgContext, -src_x, -src_y);
+ CGContextDrawImage (new_surface->cgContext,
+ CGRectMake (0, 0, CGImageGetWidth(quartz_image), CGImageGetHeight(quartz_image)),
+ quartz_image);
- CGContextDrawImage (new_surface->cgContext,
- CGRectMake (src_x, src_y, width, height),
- quartz_image);
+ CGContextRestoreGState (new_surface->cgContext);
+
CGImageRelease (quartz_image);
-
+
*clone_out = (cairo_surface_t*) new_surface;
return CAIRO_STATUS_SUCCESS;
@@ -1265,8 +1199,8 @@ _cairo_quartz_surface_get_extents (void
static cairo_int_status_t
_cairo_quartz_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- cairo_pattern_t *source)
+ cairo_operator_t op,
+ cairo_pattern_t *source)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1292,17 +1226,11 @@ _cairo_quartz_surface_paint (void *abstr
} else if (action == DO_SHADING) {
CGContextDrawShading (surface->cgContext, surface->sourceShading);
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
- cairo_surface_pattern_t *surface_pattern =
- (cairo_surface_pattern_t *) source;
- cairo_surface_t *pat_surf = surface_pattern->surface;
-
CGContextSaveGState (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
- if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
- CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
- CGContextScaleCTM (surface->cgContext, 1, -1);
- }
+ CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
+ CGContextScaleCTM (surface->cgContext, 1, -1);
if (action == DO_IMAGE)
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
@@ -1372,19 +1300,14 @@ _cairo_quartz_surface_fill (void *abstra
CGContextDrawShading (surface->cgContext, surface->sourceShading);
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
- cairo_surface_pattern_t *surface_pattern =
- (cairo_surface_pattern_t *) source;
- cairo_surface_t *pat_surf = surface_pattern->surface;
if (fill_rule == CAIRO_FILL_RULE_WINDING)
CGContextClip (surface->cgContext);
else
CGContextEOClip (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
- if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
- CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
- CGContextScaleCTM (surface->cgContext, 1, -1);
- }
+ CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
+ CGContextScaleCTM (surface->cgContext, 1, -1);
if (action == DO_IMAGE)
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
@@ -1481,10 +1404,8 @@ _cairo_quartz_surface_stroke (void *abst
CGContextClip (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
- if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
- CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
- CGContextScaleCTM (surface->cgContext, 1, -1);
- }
+ CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
+ CGContextScaleCTM (surface->cgContext, 1, -1);
if (action == DO_IMAGE)
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
@@ -1633,10 +1554,8 @@ _cairo_quartz_surface_show_glyphs (void
if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
- if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
- CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
- CGContextScaleCTM (surface->cgContext, 1, -1);
- }
+ CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
+ CGContextScaleCTM (surface->cgContext, 1, -1);
if (action == DO_IMAGE)
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
@@ -1670,7 +1589,6 @@ _cairo_quartz_surface_mask_with_surface
cairo_surface_pattern_t *mask)
{
cairo_rectangle_int_t extents;
- cairo_quartz_surface_t *quartz_surf;
CGRect rect;
CGImageRef img;
cairo_surface_t *pat_surf = mask->surface;
@@ -1680,15 +1598,11 @@ _cairo_quartz_surface_mask_with_surface
if (status)
return status;
- status = _cairo_quartz_surface_to_quartz (NULL, pat_surf, &quartz_surf);
- if (status)
- return status;
-
// everything would be masked out, so do nothing
- if (IS_EMPTY(quartz_surf))
+ if (extents.width == 0 || extents.height == 0)
goto BAIL;
- img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+ img = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf);
if (!img) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL;
@@ -1702,7 +1616,6 @@ _cairo_quartz_surface_mask_with_surface
CGContextRestoreGState (surface->cgContext);
CGImageRelease (img);
BAIL:
- cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
return status;
}
@@ -1965,7 +1878,7 @@ cairo_quartz_surface_create (cairo_forma
int bitsPerComponent;
// verify width and height of surface
- if (!verify_surface_size(width, height))
+ if (!_cairo_quartz_verify_surface_size(width, height))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
if (width == 0 || height == 0) {
@@ -2006,6 +1919,7 @@ cairo_quartz_surface_create (cairo_forma
CGColorSpaceRelease (cgColorspace);
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
+
/* zero the memory to match the image surface behaviour */
memset (imageData, 0, height * stride);
@@ -2164,15 +2078,3 @@ quartz_surface_to_png (cairo_quartz_surf
CGImageRelease(imgref);
#endif
}
-
-cairo_surface_t *
-cairo_quartz_surface_get_image (cairo_surface_t *surface)
-{
- cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface;
-
- if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ)
- return NULL;
-
- return quartz->imageSurfaceEquiv;
-}
-
diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
--- a/gfx/cairo/cairo/src/cairo-quartz.h
+++ b/gfx/cairo/cairo/src/cairo-quartz.h
@@ -58,7 +58,10 @@ cairo_quartz_surface_get_cg_context (cai
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
cairo_public cairo_surface_t *
-cairo_quartz_surface_get_image (cairo_surface_t *surface);
+cairo_quartz_image_surface_create (cairo_surface_t *image_surface);
+
+cairo_public cairo_surface_t *
+cairo_quartz_image_surface_get_image (cairo_surface_t *surface);
CAIRO_END_DECLS
diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h
--- a/gfx/cairo/cairo/src/cairo.h
+++ b/gfx/cairo/cairo/src/cairo.h
@@ -1481,7 +1481,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG,
CAIRO_SURFACE_TYPE_OS2,
- CAIRO_SURFACE_TYPE_WIN32_PRINTING
+ CAIRO_SURFACE_TYPE_WIN32_PRINTING,
+ CAIRO_SURFACE_TYPE_QUARTZ_IMAGE
} cairo_surface_type_t;
cairo_public cairo_surface_type_t