mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=414685, optimize mac image decoding and rendering ; r=stuart
This commit is contained in:
parent
393e796228
commit
95e9d58680
@ -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
|
||||
|
||||
|
340
gfx/cairo/cairo/src/cairo-quartz-image-surface.c
Normal file
340
gfx/cairo/cairo/src/cairo-quartz-image-surface.c
Normal 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -78,6 +78,7 @@ endif
|
||||
ifneq (,$(filter $(MOZ_WIDGET_TOOLKIT),mac cocoa))
|
||||
EXPORTS += gfxPlatformMac.h \
|
||||
gfxQuartzSurface.h \
|
||||
gfxQuartzImageSurface.h \
|
||||
gfxQuartzPDFSurface.h \
|
||||
gfxAtsuiFonts.h \
|
||||
$(NULL)
|
||||
|
@ -81,7 +81,8 @@ public:
|
||||
SurfaceTypeDirectFB,
|
||||
SurfaceTypeSVG,
|
||||
SurfaceTypeOS2,
|
||||
SurfaceTypeWin32Printing
|
||||
SurfaceTypeWin32Printing,
|
||||
SurfaceTypeQuartzImage
|
||||
} gfxSurfaceType;
|
||||
|
||||
typedef enum {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
54
gfx/thebes/public/gfxQuartzImageSurface.h
Normal file
54
gfx/thebes/public/gfxQuartzImageSurface.h
Normal 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 */
|
@ -58,8 +58,6 @@ public:
|
||||
|
||||
virtual PRInt32 GetDefaultContextFlags() const;
|
||||
|
||||
already_AddRefed<gfxImageSurface> GetImageSurface();
|
||||
|
||||
protected:
|
||||
CGContextRef mCGContext;
|
||||
gfxSize mSize;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
76
gfx/thebes/src/gfxQuartzImageSurface.cpp
Normal file
76
gfx/thebes/src/gfxQuartzImageSurface.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user