b=414685, optimize mac image decoding and rendering ; r=stuart

This commit is contained in:
vladimir@pobox.com 2008-02-05 22:48:47 -08:00
parent 393e796228
commit 95e9d58680
21 changed files with 752 additions and 306 deletions

View File

@ -163,7 +163,7 @@ EXPORTS += $(PDF_EXPORTS)
endif
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
CSRCS += cairo-quartz-surface.c cairo-atsui-font.c
CSRCS += cairo-quartz-surface.c cairo-quartz-image-surface.c cairo-atsui-font.c
EXPORTS += cairo-quartz.h cairo-atsui.h
endif

View File

@ -0,0 +1,340 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright <EFBFBD> 2008 Mozilla Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@mozilla.com>
*/
#include "cairoint.h"
#include "cairo-quartz-private.h"
#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
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)
{
CGImageRef image = NULL;
CGDataProviderRef dataProvider = NULL;
CGColorSpaceRef colorSpace = colorSpaceOverride;
CGBitmapInfo bitinfo;
int bitsPerComponent, bitsPerPixel;
switch (format) {
case CAIRO_FORMAT_ARGB32:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
case CAIRO_FORMAT_RGB24:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
case CAIRO_FORMAT_A8:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceGray();
bitinfo = kCGImageAlphaNone;
bitsPerComponent = 8;
bitsPerPixel = 8;
break;
default:
return NULL;
}
dataProvider = CGDataProviderCreateWithData (releaseInfo,
data,
height * stride,
releaseCallback);
if (!dataProvider) {
// manually release
if (releaseCallback)
releaseCallback (releaseInfo, data, height * stride);
goto FINISH;
}
image = CGImageCreate (width, height,
bitsPerComponent,
bitsPerPixel,
stride,
colorSpace,
bitinfo,
dataProvider,
NULL,
interpolate,
kCGRenderingIntentDefault);
FINISH:
CGDataProviderRelease (dataProvider);
if (colorSpace != colorSpaceOverride)
CGColorSpaceRelease (colorSpace);
return image;
}
static cairo_surface_t *
_cairo_quartz_image_surface_create_similar (void *asurface,
cairo_content_t content,
int width,
int height)
{
cairo_surface_t *result;
cairo_surface_t *isurf = cairo_image_surface_create (_cairo_format_from_content (content),
width,
height);
if (cairo_surface_status(isurf))
return isurf;
result = cairo_quartz_image_surface_create (isurf);
cairo_surface_destroy (isurf);
return result;
}
static cairo_status_t
_cairo_quartz_image_surface_finish (void *asurface)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
/* the imageSurface will be destroyed by the data provider's release callback */
CGImageRelease (surface->image);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_quartz_image_surface_acquire_source_image (void *asurface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
*image_out = surface->imageSurface;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_quartz_image_surface_acquire_dest_image (void *asurface,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
*image_out = surface->imageSurface;
*image_rect = surface->extents;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_image_surface_get_extents (void *asurface,
cairo_rectangle_int_t *extents)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
*extents = surface->extents;
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
_cairo_quartz_image_surface_create_similar,
_cairo_quartz_image_surface_finish,
_cairo_quartz_image_surface_acquire_source_image,
NULL, /* release_source_image */
_cairo_quartz_image_surface_acquire_dest_image,
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
NULL, /* intersect_clip_path */
_cairo_quartz_image_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
NULL, /* surface_show_glyphs */
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL /* fill_stroke */
};
static void
DataProviderReleaseCallback (void *info, const void *data, size_t size)
{
cairo_surface_t *surface = (cairo_surface_t *) info;
cairo_surface_destroy (surface);
}
/**
* cairo_quartz_image_surface_create
* @surface: a cairo image surface to wrap with a quartz image surface
*
* Creates a Quartz surface backed by a CGImageRef that references
* the given image surface.
*
* Data is to be loaded into this surface by calling
* cairo_quartz_image_surface_get_image, and performing operations on the
* resulting image surface.
*
* The resulting surface can be rendered quickly when used as a source
* when rendering to a cairo_quartz_surface.
*
* Return value: the newly created surface.
*
* Since: 1.6
*/
cairo_surface_t *
cairo_quartz_image_surface_create (cairo_surface_t *surface)
{
cairo_quartz_image_surface_t *qisurf;
CGImageRef image;
CGContextRef cgContext;
CGColorSpaceRef cgColorspace;
CGBitmapInfo bitinfo;
cairo_image_surface_t *image_surface;
int width, height, stride;
cairo_format_t format;
unsigned char *data;
if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE)
return SURFACE_ERROR_NO_MEMORY;
image_surface = (cairo_image_surface_t*) surface;
width = image_surface->width;
height = image_surface->height;
stride = image_surface->stride;
format = image_surface->format;
data = image_surface->data;
if (!_cairo_quartz_verify_surface_size(width, height))
return SURFACE_ERROR_NO_MEMORY;
if (width == 0 || height == 0)
return SURFACE_ERROR_NO_MEMORY;
if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24)
return SURFACE_ERROR_INVALID_FORMAT;
qisurf = malloc(sizeof(cairo_quartz_image_surface_t));
if (qisurf == NULL)
return SURFACE_ERROR_NO_MEMORY;
memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t));
// ref this here; in case the create_cgimage fails, it will
// be released by the callback.
cairo_surface_reference (surface);
image = _cairo_quartz_create_cgimage (format,
width, height,
stride,
data,
FALSE,
NULL,
DataProviderReleaseCallback,
surface);
if (!image) {
free (qisurf);
return SURFACE_ERROR_NO_MEMORY;
}
_cairo_surface_init (&qisurf->base,
&cairo_quartz_image_surface_backend,
_cairo_content_from_format (format));
qisurf->extents.x = qisurf->extents.y = 0;
qisurf->extents.width = width;
qisurf->extents.height = height;
qisurf->image = image;
qisurf->imageSurface = image_surface;
return &qisurf->base;
}
cairo_surface_t *
cairo_quartz_image_surface_get_image (cairo_surface_t *asurface)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*) asurface;
if (cairo_surface_get_type(asurface) != CAIRO_SURFACE_TYPE_QUARTZ_IMAGE)
return NULL;
return (cairo_surface_t*) surface->imageSurface;
}

View File

@ -46,13 +46,12 @@
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;
/* These are stored while drawing operations are in place, set up
@ -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

View File

@ -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_pattern_t *gpat)
&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 */
static void
SurfacePatternDrawFunc (void *info, CGContextRef context)
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
cairo_surface_t *pat_surf = spat->surface;
cairo_int_status_t status;
cairo_quartz_surface_t *quartz_surf;
CGImageRef img;
typedef struct {
CGImageRef image;
CGRect imageBounds;
cairo_bool_t do_reflect;
} SurfacePatternDrawInfo;
status = _cairo_quartz_surface_to_quartz (NULL, pat_surf, &quartz_surf);
if (status)
return;
static void
SurfacePatternDrawFunc (void *ainfo, CGContextRef context)
{
SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo;
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;
}
CGContextTranslateCTM (context, 0, info->imageBounds.size.height);
CGContextScaleCTM (context, 1, -1);
/* 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) {
CGContextDrawImage (context, info->imageBounds, info->image);
if (info->do_reflect) {
/* draw 3 more copies of the image, flipped. */
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
CGContextTranslateCTM (context, 0, 2 * info->imageBounds.size.height);
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, imageBounds, img);
CGContextTranslateCTM (context, 2 * imageBounds.size.width, 0);
CGContextDrawImage (context, info->imageBounds, info->image);
CGContextTranslateCTM (context, 2 * info->imageBounds.size.width, 0);
CGContextScaleCTM (context, -1, 1);
CGContextDrawImage (context, imageBounds, img);
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
CGContextDrawImage (context, info->imageBounds, info->image);
CGContextTranslateCTM (context, 0, 2 * info->imageBounds.size.height);
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, imageBounds, img);
CGContextDrawImage (context, info->imageBounds, info->image);
}
}
CGImageRelease (img);
static void
SurfacePatternReleaseInfoFunc (void *ainfo)
{
SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo;
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_pattern_t *pattern,
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;
/* 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_pattern_to_quartz (cairo_quartz_surface_t
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_pattern_to_quartz (cairo_quartz_surface_t
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_surface_t *surface,
{
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_surface_t *surface,
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 (void *abstract_surface,
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 (void *abstract_surface,
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 (void *abstract_surface,
*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 (src_x, src_y, width, height),
CGRectMake (0, 0, CGImageGetWidth(quartz_image), CGImageGetHeight(quartz_image)),
quartz_image);
CGImageRelease (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 *abstract_surface,
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 *abstract_surface,
} 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 *abstract_surface,
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 *abstract_surface,
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 *abstract_surface,
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_quartz_surface_t *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 (cairo_quartz_surface_t *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 (cairo_quartz_surface_t *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_format_t format,
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_format_t format,
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_surface_t *nq, char *dest)
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;
}

View File

@ -58,7 +58,10 @@ cairo_public CGContextRef
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

View File

@ -169,7 +169,8 @@
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
#define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
#define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
#define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image
#define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create
#define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image
#define cairo_rectangle _moz_cairo_rectangle
#define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy
#define cairo_reference _moz_cairo_reference

View File

@ -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

View File

@ -111,7 +111,7 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
mFormat = format;
#if defined(XP_WIN)
#ifdef XP_WIN
if (!ShouldUseImageSurfaces()) {
mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format);
if (mWinSurface && mWinSurface->CairoStatus() == 0) {
@ -122,16 +122,6 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
if (!mImageSurface)
mWinSurface = nsnull;
#elif defined(XP_MACOSX)
if (!ShouldUseImageSurfaces()) {
mQuartzSurface = new gfxQuartzSurface(gfxSize(mWidth, mHeight), format);
if (mQuartzSurface && mQuartzSurface->CairoStatus() == 0) {
mImageSurface = mQuartzSurface->GetImageSurface();
}
}
if (!mImageSurface)
mQuartzSurface = nsnull;
#endif
if (!mImageSurface)
@ -143,6 +133,10 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
return NS_ERROR_OUT_OF_MEMORY;
}
#ifdef XP_MACOSX
mQuartzSurface = new gfxQuartzImageSurface(mImageSurface);
#endif
mStride = mImageSurface->Stride();
return NS_OK;

View File

@ -47,7 +47,7 @@
#if defined(XP_WIN)
#include "gfxWindowsSurface.h"
#elif defined(XP_MACOSX)
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
#endif
class nsThebesImage : public nsIImage
@ -162,7 +162,7 @@ protected:
#if defined(XP_WIN)
nsRefPtr<gfxWindowsSurface> mWinSurface;
#elif defined(XP_MACOSX)
nsRefPtr<gfxQuartzSurface> mQuartzSurface;
nsRefPtr<gfxQuartzImageSurface> mQuartzSurface;
#endif
PRUint8 mAlphaDepth;

View File

@ -78,6 +78,7 @@ endif
ifneq (,$(filter $(MOZ_WIDGET_TOOLKIT),mac cocoa))
EXPORTS += gfxPlatformMac.h \
gfxQuartzSurface.h \
gfxQuartzImageSurface.h \
gfxQuartzPDFSurface.h \
gfxAtsuiFonts.h \
$(NULL)

View File

@ -81,7 +81,8 @@ public:
SurfaceTypeDirectFB,
SurfaceTypeSVG,
SurfaceTypeOS2,
SurfaceTypeWin32Printing
SurfaceTypeWin32Printing,
SurfaceTypeQuartzImage
} gfxSurfaceType;
typedef enum {

View File

@ -81,6 +81,9 @@ public:
*/
unsigned char* Data() { return mData; } // delete this data under us and die.
/* Fast copy from another image surface; returns TRUE if successful, FALSE otherwise */
PRBool CopyFrom (gfxImageSurface *other);
private:
long ComputeStride() const;

View File

@ -53,6 +53,9 @@ public:
already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxImageFormat imageFormat);
already_AddRefed<gfxASurface> gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
gfxASurface::gfxImageFormat format);
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
void *aClosure, PRBool& aAborted);

View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_QUARTZIMAGESURFACE_H
#define GFX_QUARTZIMAGESURFACE_H
#include "gfxASurface.h"
#include "gfxImageSurface.h"
class THEBES_API gfxQuartzImageSurface : public gfxASurface {
public:
gfxQuartzImageSurface(gfxImageSurface *imageSurface);
gfxQuartzImageSurface(cairo_surface_t *csurf);
virtual ~gfxQuartzImageSurface();
already_AddRefed<gfxImageSurface> GetImageSurface();
};
#endif /* GFX_QUARTZIMAGESURFACE_H */

View File

@ -58,8 +58,6 @@ public:
virtual PRInt32 GetDefaultContextFlags() const;
already_AddRefed<gfxImageSurface> GetImageSurface();
protected:
CGContextRef mCGContext;
gfxSize mSize;

View File

@ -101,7 +101,13 @@ endif
ifneq (,$(filter $(MOZ_WIDGET_TOOLKIT),mac cocoa))
CPPSRCS += gfxQuartzSurface.cpp gfxQuartzPDFSurface.cpp gfxPlatformMac.cpp gfxAtsuiFonts.cpp
CPPSRCS += \
gfxQuartzSurface.cpp \
gfxQuartzImageSurface.cpp \
gfxQuartzPDFSurface.cpp \
gfxPlatformMac.cpp \
gfxAtsuiFonts.cpp \
$(NULL)
#CPPSRCS += gfxPDFSurface.cpp
CPPSRCS += nsUnicodeRange.cpp

View File

@ -52,6 +52,7 @@
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
#endif
#include <stdio.h>
@ -158,6 +159,9 @@ gfxASurface::Wrap (cairo_surface_t *csurf)
else if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
result = new gfxQuartzSurface(csurf);
}
else if (stype == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
result = new gfxQuartzImageSurface(csurf);
}
#endif
else {
result = new gfxUnknownSurface(csurf);

View File

@ -114,3 +114,33 @@ gfxImageSurface::ComputeStride() const
return stride;
}
PRBool
gfxImageSurface::CopyFrom(gfxImageSurface *other)
{
if (other->mSize != mSize)
{
return PR_FALSE;
}
if (other->mFormat != mFormat &&
!(other->mFormat == ImageFormatARGB32 && mFormat == ImageFormatRGB24) &&
!(other->mFormat == ImageFormatRGB24 && mFormat == ImageFormatARGB32))
{
return PR_FALSE;
}
if (other->mStride == mStride) {
memcpy (mData, other->mData, mStride * mSize.height);
} else {
int lineSize = PR_MIN(other->mStride, mStride);
for (int i = 0; i < mSize.height; i++) {
unsigned char *src = other->mData + other->mStride * i;
unsigned char *dst = mData + mStride * i;
memcpy (dst, src, lineSize);
}
}
return PR_TRUE;
}

View File

@ -40,6 +40,7 @@
#include "gfxImageSurface.h"
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
#include "gfxQuartzFontCache.h"
#include "gfxAtsuiFonts.h"
@ -144,6 +145,26 @@ gfxPlatformMac::CreateOffscreenSurface(const gfxIntSize& size,
return newSurface;
}
already_AddRefed<gfxASurface>
gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
gfxASurface::gfxImageFormat format)
{
const gfxIntSize& surfaceSize = aSurface->GetSize();
nsRefPtr<gfxImageSurface> isurf = aSurface;
if (format != aSurface->Format()) {
isurf = new gfxImageSurface (surfaceSize, format);
if (!isurf->CopyFrom (aSurface)) {
// don't even bother doing anything more
NS_ADDREF(aSurface);
return aSurface;
}
}
nsRefPtr<gfxASurface> ret = new gfxQuartzImageSurface(isurf);
return ret.forget();
}
nsresult
gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxQuartzImageSurface.h"
#include "cairo-quartz.h"
gfxQuartzImageSurface::gfxQuartzImageSurface(gfxImageSurface *imageSurface)
{
if (imageSurface->CairoStatus() || imageSurface->CairoSurface() == NULL)
return;
cairo_surface_t *surf = cairo_quartz_image_surface_create (imageSurface->CairoSurface());
Init (surf);
}
gfxQuartzImageSurface::gfxQuartzImageSurface(cairo_surface_t *csurf)
{
Init (csurf, PR_TRUE);
}
gfxQuartzImageSurface::~gfxQuartzImageSurface()
{
}
already_AddRefed<gfxImageSurface>
gfxQuartzImageSurface::GetImageSurface()
{
if (!mSurfaceValid)
return nsnull;
cairo_surface_t *isurf = cairo_quartz_image_surface_get_image (CairoSurface());
if (!isurf) {
NS_WARNING ("Couldn't obtain an image surface from a QuartzImageSurface?!");
return nsnull;
}
nsRefPtr<gfxASurface> asurf = gfxASurface::Wrap(isurf);
gfxImageSurface *imgsurf = (gfxImageSurface*) asurf.get();
NS_ADDREF(imgsurf);
return imgsurf;
}

View File

@ -44,11 +44,14 @@ gfxQuartzSurface::gfxQuartzSurface(const gfxSize& size, gfxImageFormat format,
PRBool aForPrinting)
: mSize(size), mForPrinting(aForPrinting)
{
if (!CheckSurfaceSize(gfxIntSize((int)size.width, (int)size.height)))
unsigned int width = (unsigned int) floor(size.width);
unsigned int height = (unsigned int) floor(size.height);
if (!CheckSurfaceSize(gfxIntSize(width, height)))
return;
cairo_surface_t *surf = cairo_quartz_surface_create
((cairo_format_t) format, floor(size.width), floor(size.height));
((cairo_format_t) format, width, height);
mCGContext = cairo_quartz_surface_get_cg_context (surf);
@ -62,10 +65,12 @@ gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
PRBool aForPrinting)
: mCGContext(context), mSize(size), mForPrinting(aForPrinting)
{
unsigned int width = (unsigned int) floor(size.width);
unsigned int height = (unsigned int) floor(size.height);
cairo_surface_t *surf =
cairo_quartz_surface_create_for_cg_context(context,
floor(size.width),
floor(size.height));
width, height);
CGContextRetain(mCGContext);
@ -94,23 +99,3 @@ gfxQuartzSurface::~gfxQuartzSurface()
{
CGContextRelease(mCGContext);
}
already_AddRefed<gfxImageSurface>
gfxQuartzSurface::GetImageSurface()
{
if (!mSurfaceValid) {
NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
return nsnull;
}
NS_ASSERTION(CairoSurface() != nsnull, "CairoSurface() shouldn't be nsnull when mSurfaceValid is TRUE!");
cairo_surface_t *isurf = cairo_quartz_surface_get_image(CairoSurface());
if (!isurf)
return nsnull;
nsRefPtr<gfxASurface> asurf = gfxASurface::Wrap(isurf);
gfxImageSurface *imgsurf = (gfxImageSurface*) asurf.get();
NS_ADDREF(imgsurf);
return imgsurf;
}