diff --git a/gfx/cairo/cairo/src/cairo-atsui-font.c b/gfx/cairo/cairo/src/cairo-atsui-font.c index e93cc458eb9f..425a682e9889 100644 --- a/gfx/cairo/cairo/src/cairo-atsui-font.c +++ b/gfx/cairo/cairo/src/cairo-atsui-font.c @@ -218,8 +218,6 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, cairo_status_t status; font = malloc(sizeof(cairo_atsui_font_t)); - if (font == NULL) - return CAIRO_STATUS_NO_MEMORY; _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options, &cairo_atsui_scaled_font_backend); @@ -596,134 +594,105 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, int num_glyphs) { cairo_atsui_font_t *font = abstract_font; - CGContextRef myBitmapContext = 0, drawingContext; + CGContextRef myBitmapContext; + CGColorSpaceRef colorSpace; cairo_image_surface_t *destImageSurface; - int i; + int i, bits_per_comp, alpha; void *extra = NULL; - cairo_bool_t can_draw_directly; - cairo_rectangle_fixed_t rect; - /* Check if we can draw directly to the destination surface */ - can_draw_directly = _cairo_surface_is_quartz (generic_surface) && - _cairo_pattern_is_opaque_solid (pattern) && - op == CAIRO_OPERATOR_OVER; + cairo_rectangle_fixed_t rect = {dest_x, dest_y, width, height}; + _cairo_surface_acquire_dest_image(generic_surface, + &rect, + &destImageSurface, + &rect, + &extra); - if (!can_draw_directly) { - CGColorSpaceRef colorSpace = 0; - int bits_per_comp, alpha; - - rect.x = dest_x; - rect.y = dest_y; - rect.width = width; - rect.height = height; - - _cairo_surface_acquire_dest_image(generic_surface, - &rect, - &destImageSurface, - &rect, - &extra); - - /* Create a CGBitmapContext for the dest surface for drawing into */ - if (destImageSurface->depth == 1) { - colorSpace = CGColorSpaceCreateDeviceGray(); - bits_per_comp = 1; - alpha = kCGImageAlphaNone; - } else if (destImageSurface->depth == 8) { - colorSpace = CGColorSpaceCreateDeviceGray(); - bits_per_comp = 8; - alpha = kCGImageAlphaNone; - } else if (destImageSurface->depth == 24) { - colorSpace = CGColorSpaceCreateDeviceRGB(); - bits_per_comp = 8; - alpha = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - } else if (destImageSurface->depth == 32) { - colorSpace = CGColorSpaceCreateDeviceRGB(); - bits_per_comp = 8; - alpha = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; - } else { - // not reached - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* Create a CGBitmapContext for the dest surface for drawing into */ - colorSpace = CGColorSpaceCreateDeviceRGB(); - - myBitmapContext = CGBitmapContextCreate(destImageSurface->data, - destImageSurface->width, - destImageSurface->height, - bits_per_comp, - destImageSurface->stride, - colorSpace, - alpha); - CGColorSpaceRelease(colorSpace); - - CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); - CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); - - drawingContext = myBitmapContext; + /* Create a CGBitmapContext for the dest surface for drawing into */ + if (destImageSurface->depth == 1) { + colorSpace = CGColorSpaceCreateDeviceGray(); + bits_per_comp = 1; + alpha = kCGImageAlphaNone; + } else if (destImageSurface->depth == 8) { + colorSpace = CGColorSpaceCreateDeviceGray(); + bits_per_comp = 8; + alpha = kCGImageAlphaNone; + } else if (destImageSurface->depth == 24) { + colorSpace = CGColorSpaceCreateDeviceRGB(); + bits_per_comp = 8; + alpha = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; + } else if (destImageSurface->depth == 32) { + colorSpace = CGColorSpaceCreateDeviceRGB(); + bits_per_comp = 8; + alpha = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; } else { - drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context; - CGContextSaveGState (drawingContext); + // not reached + return CAIRO_INT_STATUS_UNSUPPORTED; } + myBitmapContext = CGBitmapContextCreate(destImageSurface->data, + destImageSurface->width, + destImageSurface->height, + bits_per_comp, + destImageSurface->stride, + colorSpace, + alpha); + CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); + CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); + ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont); - CGContextSetFont(drawingContext, cgFont); + CGContextSetFont(myBitmapContext, cgFont); CGAffineTransform textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale); textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); - CGContextSetFontSize(drawingContext, 1.0); - CGContextSetTextMatrix(drawingContext, textTransform); + CGContextSetFontSize(myBitmapContext, 1.0); + CGContextSetTextMatrix(myBitmapContext, textTransform); if (pattern->type == CAIRO_PATTERN_TYPE_SOLID && _cairo_pattern_is_opaque_solid(pattern)) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; - CGContextSetRGBFillColor(drawingContext, + CGContextSetRGBFillColor(myBitmapContext, solid->color.red, solid->color.green, solid->color.blue, 1.0f); } else { - CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f); + CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f); } - if (_cairo_surface_is_quartz (generic_surface)) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; - if (surface->clip_region) { - pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); - int num_boxes = pixman_region_num_rects (surface->clip_region); - CGRect stack_rects[10]; - CGRect *rects; - int i; - - /* XXX: Return-value of malloc needs to be checked for - * NULL. Can someone fix this who is more familiar with - * the cleanup needed in this function? - */ - if (num_boxes > 10) - rects = malloc (sizeof (CGRect) * num_boxes); - else - rects = stack_rects; - - for (i = 0; i < num_boxes; i++) { - rects[i].origin.x = boxes[i].x1; - rects[i].origin.y = boxes[i].y1; - rects[i].size.width = boxes[i].x2 - boxes[i].x1; - rects[i].size.height = boxes[i].y2 - boxes[i].y1; - } - - CGContextClipToRects (drawingContext, rects, num_boxes); - - if (rects != stack_rects) - free(rects); + if (_cairo_surface_is_quartz (generic_surface)) { + cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; + if (surface->clip_region) { + pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); + int num_boxes = pixman_region_num_rects (surface->clip_region); + CGRect stack_rects[10]; + CGRect *rects; + int i; + + if (num_boxes > 10) + rects = malloc (sizeof (CGRect) * num_boxes); + else + rects = stack_rects; + + for (i = 0; i < num_boxes; i++) { + rects[i].origin.x = boxes[i].x1; + rects[i].origin.y = boxes[i].y1; + rects[i].size.width = boxes[i].x2 - boxes[i].x1; + rects[i].size.height = boxes[i].y2 - boxes[i].y1; + } + + CGContextClipToRects (myBitmapContext, rects, num_boxes); + + if (rects != stack_rects) + free(rects); + } + } else { + /* XXX: Need to get the text clipped */ } - } else { - /* XXX: Need to get the text clipped */ - } /* TODO - bold and italic text * @@ -736,23 +705,21 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, for (i = 0; i < num_glyphs; i++) { CGGlyph theGlyph = glyphs[i].index; - CGContextShowGlyphsAtPoint(drawingContext, + CGContextShowGlyphsAtPoint(myBitmapContext, glyphs[i].x, glyphs[i].y, &theGlyph, 1); } - if (!can_draw_directly) { - CGContextRelease(myBitmapContext); - - _cairo_surface_release_dest_image(generic_surface, - &rect, - destImageSurface, - &rect, - extra); - } else { - CGContextRestoreGState (drawingContext); - } + + CGColorSpaceRelease(colorSpace); + CGContextRelease(myBitmapContext); + + _cairo_surface_release_dest_image(generic_surface, + &rect, + destImageSurface, + &rect, + extra); return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h index 442b925958d4..de6b91531428 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h @@ -44,11 +44,15 @@ typedef struct cairo_quartz_surface { CGContextRef context; - cairo_bool_t y_grows_down; + cairo_bool_t flipped; - cairo_rectangle_fixed_t extents; + int width; + int height; - pixman_region16_t *clip_region; + cairo_image_surface_t *image; + pixman_region16_t *clip_region; + + CGImageRef cgImage; } cairo_quartz_surface_t; cairo_bool_t diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index 698b1490c2bb..546da105fa75 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -37,13 +37,27 @@ #include "cairo-private.h" #include "cairo-quartz-private.h" +static void +ImageDataReleaseFunc(void *info, const void *data, size_t size) +{ + if (data != NULL) { + free((void *) data); + } +} + static cairo_status_t _cairo_quartz_surface_finish(void *abstract_surface) { cairo_quartz_surface_t *surface = abstract_surface; - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); + 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); return CAIRO_STATUS_SUCCESS; } @@ -52,128 +66,118 @@ static cairo_status_t _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; - - if (CGBitmapContextGetBitmapInfo (surface->context) != 0) { - /* XXX: We can create an image out of the bitmap here */ - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -_cairo_quartz_surface_acquire_dest_image(void *abstract_surface, - cairo_rectangle_fixed_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_fixed_t *image_rect, - void **image_extra) { cairo_quartz_surface_t *surface = abstract_surface; - cairo_surface_t *image_surface; - unsigned char *data; - int x1, y1, x2, y2; + CGColorSpaceRef colorSpace; + void *imageData; + UInt32 imageDataSize, rowBytes; + CGDataProviderRef dataProvider; - x1 = surface->extents.x; - x2 = surface->extents.x + surface->extents.width; - y1 = surface->extents.y; - y2 = surface->extents.y + surface->extents.height; + /* 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 (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; - + *image_out = surface->image; return CAIRO_STATUS_SUCCESS; } - image_rect->x = x1; - image_rect->y = y1; - image_rect->width = x2 - x1; - image_rect->height = y2 - y1; + colorSpace = CGColorSpaceCreateDeviceRGB(); - 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; + 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 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, - cairo_rectangle_fixed_t *intersect_rect, - cairo_image_surface_t *image, - cairo_rectangle_fixed_t *image_rect, - void *image_extra) +static cairo_status_t +_cairo_quartz_surface_acquire_dest_image(void *abstract_surface, + cairo_rectangle_fixed_t * interest_rect, + cairo_image_surface_t ** + image_out, + cairo_rectangle_fixed_t * image_rect, + void **image_extra) { cairo_quartz_surface_t *surface = abstract_surface; - CGImageRef image_ref; - CGRect rect; - - image_ref = create_image_from_surface (image, image_extra); - rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); + image_rect->x = 0; + image_rect->y = 0; + image_rect->width = surface->image->width; + image_rect->height = surface->image->height; - if (surface->y_grows_down) { - CGContextSaveGState (surface->context); - CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); - CGContextScaleCTM (surface->context, 1, -1); + *image_out = surface->image; + if (image_extra) + *image_extra = NULL; + + return CAIRO_STATUS_SUCCESS; +} + + +static void +_cairo_quartz_surface_release_dest_image(void *abstract_surface, + cairo_rectangle_fixed_t * + intersect_rect, + cairo_image_surface_t * image, + cairo_rectangle_fixed_t * image_rect, + void *image_extra) +{ + cairo_quartz_surface_t *surface = abstract_surface; + + if (surface->image == image) { + CGRect rect; + + 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); } - - CGContextDrawImage(surface->context, rect, image_ref); - CFRelease (image_ref); - - if (surface->y_grows_down) { - CGContextRestoreGState (surface->context); - } - - cairo_surface_destroy ((cairo_surface_t *)image); - free (image_extra); } static cairo_int_status_t @@ -181,26 +185,33 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface, pixman_region16_t * region) { cairo_quartz_surface_t *surface = abstract_surface; + unsigned int serial; - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); + 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; - - return CAIRO_STATUS_SUCCESS; + 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); } static cairo_int_status_t -_cairo_quartz_surface_get_extents (void *abstract_surface, - cairo_rectangle_fixed_t *rectangle) +_cairo_quartz_surface_get_extents (void *abstract_surface, + cairo_rectangle_fixed_t * rectangle) { cairo_quartz_surface_t *surface = abstract_surface; - *rectangle = surface->extents; + rectangle->x = 0; + rectangle->y = 0; + rectangle->width = surface->width; + rectangle->height = surface->height; return CAIRO_STATUS_SUCCESS; } @@ -227,12 +238,10 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, - int width, - int height, - cairo_bool_t y_grows_down) + cairo_bool_t flipped, + int width, int height) { cairo_quartz_surface_t *surface; - CGRect clip_box; surface = malloc(sizeof(cairo_quartz_surface_t)); if (surface == NULL) { @@ -240,19 +249,19 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, return (cairo_surface_t*) &_cairo_surface_nil; } - /* XXX: The content value here might be totally wrong. */ - _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); + _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend); surface->context = context; - surface->clip_region = NULL; - surface->y_grows_down = y_grows_down; + surface->width = width; + surface->height = height; + surface->image = NULL; + surface->cgImage = NULL; + surface->clip_region = NULL; + surface->flipped = flipped; - 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; + /* 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); return (cairo_surface_t *) surface; }