b=340452, update cairo on trunk to 2006-06-03, r=stuart

git-svn-id: svn://10.0.0.236/trunk@199075 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
vladimir%pobox.com 2006-06-05 23:16:25 +00:00
parent d21958870c
commit b53474a3a1
65 changed files with 7756 additions and 4132 deletions

View File

@ -12,88 +12,10 @@ http://www.cairographics.org/.
VERSIONS:
cairo 1.1.1 (cvs - 2006-03-31)
cairo 1.1.1 (cvs - 2006-06-03)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****
VC6 cannot build pixman from cairo. Therefore, VC6 builds are not supported
if cairo is enabled. Please upgrade to VC7.1/8.
VC6 is not supported. Please upgrade to VC8.
==== Patches ====
[somewhat obsolete, see git repository history for patch info]
Last update: 23 Feb 2006
mozilla-misc.patch
- Misc compilation fixes for pixman (submitted upstream)
- temporary moz_cairo_set_target API (not for upstream)
- mac compilation fix for cairo-atsui-font.c for 10.2 SDK (maybe should
be upstream?)
- cairo-features.h.in - add cairo-platform.h include and hard-code the
cairo version (not for upstream)
- #if 0'ing out DllMain in win32-surface.c -- not needed, since
we don't use cairo multithreaded, and DllMain interferes
with libxul's DllMain. (not for usptream)
- #if 0'ing out bits to get rid of multithreaded stuff in cairoint.h
(not for upstream)
cairo-debug-helpers.patch
- some stuff for cairo-debug.[ch]
fbcompose-bandaid.patch (Updated 7 Feb 06)
- Workaround for https://bugs.freedesktop.org/show_bug.cgi?id=5777
cairo-win32-clip.patch
- Make mark_dirty() reset a surface's clip, so that we can call it
when we RestoreDC() after native win32 drawing (submitted upstream)
- Rework win32 surface clip and extents handling for correctness
(submitted upstream)
cairo-win32-expose-dc-and-dib.patch (Updated 10 Feb 06)
- Expose cairo_win32_surface_create_dib() and add
cairo_win32_surface_get_dc() to get at a surface's HDC
cairo-win32-alphablend.patch (Updated 10 Feb 06)
- Use AlphaBlend if the dst surface is either RGB24 or ARGB32, not
just RGB24
- Removed src->format == dst->format restriction for deciding when
to use BitBlt; it's valid for ARGB32->RGB24 and vice-versa with operator
SOURCE
- Remove RGB24 format check in fast win32-font.c path (we can still use
GDI with ARGB32)
- Add GdiFlush() calls before each image surface get
(Submitted upstream: https://bugs.freedesktop.org/show_bug.cgi?id=5845)
device-offset-scale.patch (Updated 7 Feb 06)
- Move device offset/scale handling into surface layer; large rework
of device offset/scale. (submitted upstream)
push-pop-group.patch (Updated 9 Feb 06)
- Implementation of push/pop group API; depends on device-offset-scale.
(submitted upstream)
- Add push_group_with_content() to select COLOR/COLOR_ALPHA/ALPHA
cairo-win32-composite-coord.patch
- Fix up coordinates before calling BitBlt/AlphaBlend, so that windows
doesn't get mad at us if we ask it to blit regions outside of the source
DC (NOT SUBMITTED UPSTREAM YET)
cairo-win32-expose-dc-and-dib.patch
- Expose cairo_win32_surface_get_dc() to return the HDC for a win32 surface
- Expose cairo_win32_surface_create_dib() for creating a DIB-backed surface
(NOT SUBMITTED UPSTREAM YET)
cairo-win32-creation-format.patch
- Have cairo_win32_surface_create inspect the DC and set up the appropriate
cairo_format_t
cairo-xlib-create-similar.patch (Updated 21 Feb 06)
- _cairo_xlib_surface_create_similar should not create a 24-bit
surface for a 16-bit target; fix it to emulate the target surface
as closely as possible (submitted upstream, not accepted yet)
cairo-xlib-getters.patch (Updated 23 Feb 06)
- Add cairo_xlib_get_(display,drawable,screen,visual,depth)
(submitted upstream, not accepted yet)

View File

@ -60,6 +60,7 @@ REQUIRES = $(PNG_REQUIRES) \
CSRCS = \
cairo.c \
cairo-analysis-surface.c \
cairo-arc.c \
cairo-array.c \
cairo-cache.c \
@ -68,16 +69,17 @@ CSRCS = \
cairo-debug.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
cairo-font-options.c \
cairo-gstate.c \
cairo-hash.c \
cairo-hash.c \
cairo-hull.c \
cairo-image-surface.c \
cairo-lzw.c \
cairo-lzw.c \
cairo-matrix.c \
cairo-meta-surface.c \
cairo-meta-surface.c \
cairo-operator.c \
cairo-output-stream.c \
cairo-paginated-surface.c \
cairo-paginated-surface.c \
cairo-path.c \
cairo-path-bounds.c \
cairo-path-data.c \
@ -86,13 +88,14 @@ CSRCS = \
cairo-pattern.c \
cairo-pen.c \
cairo-polygon.c \
cairo-region.c \
cairo-scaled-font.c \
cairo-region.c \
cairo-scaled-font.c \
cairo-scaled-font-subsets.c \
cairo-slope.c \
cairo-spline.c \
cairo-stroke-style.c \
cairo-stroke-style.c \
cairo-surface.c \
cairo-surface-fallback.c \
cairo-surface-fallback.c \
cairo-traps.c \
cairo-unicode.c \
cairo-wideint.c \
@ -129,6 +132,7 @@ endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
CSRCS += cairo-font-subset.c \
cairo-base85-stream.c \
cairo-pdf-surface.c \
cairo-ps-surface.c
EXPORTS += cairo-ps.h cairo-pdf.h

View File

@ -0,0 +1,55 @@
/* $Id: cairo-analysis-surface-private.h,v 1.1 2006-06-05 23:16:24 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
* 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 Keith Packard
*
* Contributor(s):
* Keith Packard <keithp@keithp.com>
*/
#ifndef CAIRO_ANALYSIS_SURFACE_H
#define CAIRO_ANALYSIS_SURFACE_H
#include "cairoint.h"
cairo_private cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height);
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_unsupported (cairo_surface_t *unsupported);
cairo_private cairo_bool_t
_cairo_analysis_surface_has_unsupported (cairo_surface_t *unsupported);
#endif /* CAIRO_ANALYSIS_SURFACE_H */

View File

@ -0,0 +1,259 @@
/*
* Copyright © 2006 Keith Packard
*
* 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 Keith Packard
*
* Contributor(s):
* Keith Packard <keithp@keithp.com>
*/
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-paginated-surface-private.h"
typedef struct {
cairo_surface_t base;
int width;
int height;
cairo_surface_t *target;
cairo_bool_t fallback;
} cairo_analysis_surface_t;
static cairo_int_status_t
_cairo_analysis_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_analysis_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->target, rectangle);
}
static cairo_int_status_t
_cairo_analysis_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status;
if (!surface->target->backend->paint)
status = CAIRO_INT_STATUS_UNSUPPORTED;
else
status = (*surface->target->backend->paint) (surface->target, op,
source);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
surface->fallback = TRUE;
status = CAIRO_STATUS_SUCCESS;
}
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status;
if (!surface->target->backend->mask)
status = CAIRO_INT_STATUS_UNSUPPORTED;
else
status = (*surface->target->backend->mask) (surface->target, op,
source, mask);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
surface->fallback = TRUE;
status = CAIRO_STATUS_SUCCESS;
}
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status;
if (!surface->target->backend->stroke)
status = CAIRO_INT_STATUS_UNSUPPORTED;
else
status = (*surface->target->backend->stroke) (surface->target, op,
source, path, style,
ctm, ctm_inverse,
tolerance, antialias);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
surface->fallback = TRUE;
status = CAIRO_STATUS_SUCCESS;
}
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status;
if (!surface->target->backend->fill)
status = CAIRO_INT_STATUS_UNSUPPORTED;
else
status = (*surface->target->backend->fill) (surface->target, op,
source, path, fill_rule,
tolerance, antialias);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
surface->fallback = TRUE;
status = CAIRO_STATUS_SUCCESS;
}
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status;
if (!surface->target->backend->show_glyphs)
status = CAIRO_INT_STATUS_UNSUPPORTED;
else
status = (*surface->target->backend->show_glyphs) (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
surface->fallback = TRUE;
status = CAIRO_STATUS_SUCCESS;
}
return status;
}
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
NULL, /* create_similar */
NULL, /* finish_surface */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* 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, /* clip_path */
_cairo_analysis_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 */
_cairo_analysis_surface_paint,
_cairo_analysis_surface_mask,
_cairo_analysis_surface_stroke,
_cairo_analysis_surface_fill,
_cairo_analysis_surface_show_glyphs,
NULL, /* snapshot */
};
cairo_private cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height)
{
cairo_analysis_surface_t *surface;
surface = malloc (sizeof (cairo_analysis_surface_t));
if (surface == NULL)
goto FAIL;
/* I believe the content type here is truly arbitrary. I'm quite
* sure nothing will ever use this value. */
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
surface->width = width;
surface->height = height;
surface->target = target;
surface->fallback = FALSE;
return &surface->base;
FAIL:
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
{
/* XXX */
return NULL;
}
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
{
/* XXX */
return NULL;
}
cairo_private cairo_bool_t
_cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
return surface->fallback;
}

View File

@ -200,10 +200,8 @@ _cairo_array_index (cairo_array_t *array, int index)
* which in the num_elements==0 case gets the NULL pointer here,
* but never dereferences it.
*/
if (array->elements == NULL) {
assert (index == 0);
if (index == 0 && array->num_elements == 0)
return NULL;
}
assert (0 <= index && index < array->num_elements);

View File

@ -218,6 +218,8 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
cairo_status_t status;
font = malloc(sizeof(cairo_atsui_font_t));
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
@ -594,105 +596,134 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
int num_glyphs)
{
cairo_atsui_font_t *font = abstract_font;
CGContextRef myBitmapContext;
CGColorSpaceRef colorSpace;
CGContextRef myBitmapContext = 0, drawingContext;
cairo_image_surface_t *destImageSurface;
int i, bits_per_comp, alpha;
int i;
void *extra = NULL;
cairo_bool_t can_draw_directly;
cairo_rectangle_fixed_t rect;
cairo_rectangle_t rect = {dest_x, dest_y, width, height};
_cairo_surface_acquire_dest_image(generic_surface,
&rect,
&destImageSurface,
&rect,
&extra);
/* Check if we can draw directly to the destination surface */
can_draw_directly = _cairo_surface_is_quartz (generic_surface) &&
_cairo_pattern_is_opaque_solid (pattern) &&
op == CAIRO_OPERATOR_OVER;
/* Create a CGBitmapContext for the dest surface for drawing into */
if (destImageSurface->depth == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 1;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 8) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 8;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 24) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
} else if (destImageSurface->depth == 32) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
if (!can_draw_directly) {
CGColorSpaceRef colorSpace = 0;
int bits_per_comp, alpha;
rect.x = dest_x;
rect.y = dest_y;
rect.width = width;
rect.height = height;
_cairo_surface_acquire_dest_image(generic_surface,
&rect,
&destImageSurface,
&rect,
&extra);
/* Create a CGBitmapContext for the dest surface for drawing into */
if (destImageSurface->depth == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 1;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 8) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 8;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 24) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
} else if (destImageSurface->depth == 32) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
} else {
// not reached
return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* Create a CGBitmapContext for the dest surface for drawing into */
colorSpace = CGColorSpaceCreateDeviceRGB();
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
destImageSurface->width,
destImageSurface->height,
bits_per_comp,
destImageSurface->stride,
colorSpace,
alpha);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
drawingContext = myBitmapContext;
} else {
// not reached
return CAIRO_INT_STATUS_UNSUPPORTED;
drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
CGContextSaveGState (drawingContext);
}
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
destImageSurface->width,
destImageSurface->height,
bits_per_comp,
destImageSurface->stride,
colorSpace,
alpha);
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
CGContextSetFont(myBitmapContext, cgFont);
CGContextSetFont(drawingContext, cgFont);
CGAffineTransform textTransform =
CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
CGContextSetFontSize(myBitmapContext, 1.0);
CGContextSetTextMatrix(myBitmapContext, textTransform);
CGContextSetFontSize(drawingContext, 1.0);
CGContextSetTextMatrix(drawingContext, textTransform);
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
_cairo_pattern_is_opaque_solid(pattern))
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
CGContextSetRGBFillColor(myBitmapContext,
CGContextSetRGBFillColor(drawingContext,
solid->color.red,
solid->color.green,
solid->color.blue, 1.0f);
} else {
CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
}
if (_cairo_surface_is_quartz (generic_surface)) {
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
if (surface->clip_region) {
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
int num_boxes = pixman_region_num_rects (surface->clip_region);
CGRect stack_rects[10];
CGRect *rects;
int i;
if (num_boxes > 10)
rects = malloc (sizeof (CGRect) * num_boxes);
else
rects = stack_rects;
for (i = 0; i < num_boxes; i++) {
rects[i].origin.x = boxes[i].x1;
rects[i].origin.y = boxes[i].y1;
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
}
CGContextClipToRects (myBitmapContext, rects, num_boxes);
if (rects != stack_rects)
free(rects);
}
} else {
/* XXX: Need to get the text clipped */
if (_cairo_surface_is_quartz (generic_surface)) {
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
if (surface->clip_region) {
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
int num_boxes = pixman_region_num_rects (surface->clip_region);
CGRect stack_rects[10];
CGRect *rects;
int i;
/* XXX: Return-value of malloc needs to be checked for
* NULL. Can someone fix this who is more familiar with
* the cleanup needed in this function?
*/
if (num_boxes > 10)
rects = malloc (sizeof (CGRect) * num_boxes);
else
rects = stack_rects;
for (i = 0; i < num_boxes; i++) {
rects[i].origin.x = boxes[i].x1;
rects[i].origin.y = boxes[i].y1;
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
}
CGContextClipToRects (drawingContext, rects, num_boxes);
if (rects != stack_rects)
free(rects);
}
} else {
/* XXX: Need to get the text clipped */
}
/* TODO - bold and italic text
*
@ -705,21 +736,24 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
for (i = 0; i < num_glyphs; i++) {
CGGlyph theGlyph = glyphs[i].index;
CGContextShowGlyphsAtPoint(myBitmapContext,
CGContextShowGlyphsAtPoint(drawingContext,
glyphs[i].x,
glyphs[i].y,
&theGlyph, 1);
}
CGColorSpaceRelease(colorSpace);
CGContextRelease(myBitmapContext);
_cairo_surface_release_dest_image(generic_surface,
&rect,
destImageSurface,
&rect,
extra);
if (!can_draw_directly) {
CGColorSpaceRelease(colorSpace);
CGContextRelease(myBitmapContext);
_cairo_surface_release_dest_image(generic_surface,
&rect,
destImageSurface,
&rect,
extra);
} else {
CGContextRestoreGState (drawingContext);
}
return CAIRO_STATUS_SUCCESS;
}

View File

@ -0,0 +1,130 @@
/* cairo_output_stream.c: Output stream abstraction
*
* Copyright © 2005 Red Hat, Inc
*
* 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 cairo_output_stream.c as distributed with the
* cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Author(s):
* Kristian Høgsberg <krh@redhat.com>
*/
#include "cairoint.h"
typedef struct _cairo_base85_stream {
cairo_output_stream_t *output;
unsigned char four_tuple[4];
int pending;
} cairo_base85_stream_t;
static void
_expand_four_tuple_to_five (unsigned char four_tuple[4],
unsigned char five_tuple[5],
cairo_bool_t *all_zero)
{
uint32_t value;
int digit, i;
value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
if (all_zero)
*all_zero = TRUE;
for (i = 0; i < 5; i++) {
digit = value % 85;
if (digit != 0 && all_zero)
*all_zero = FALSE;
five_tuple[4-i] = digit + 33;
value = value / 85;
}
}
static cairo_status_t
_cairo_base85_stream_write (void *closure,
const unsigned char *data,
unsigned int length)
{
cairo_base85_stream_t *stream = closure;
const unsigned char *ptr = data;
unsigned char five_tuple[5];
cairo_bool_t is_zero;
while (length) {
stream->four_tuple[stream->pending++] = *ptr++;
length--;
if (stream->pending == 4) {
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
if (is_zero)
_cairo_output_stream_write (stream->output, "z", 1);
else
_cairo_output_stream_write (stream->output, five_tuple, 5);
stream->pending = 0;
}
}
return _cairo_output_stream_get_status (stream->output);
}
static cairo_status_t
_cairo_base85_stream_close (void *closure)
{
cairo_status_t status;
cairo_base85_stream_t *stream = closure;
unsigned char five_tuple[5];
if (stream->pending) {
memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
}
/* Mark end of base85 data */
_cairo_output_stream_printf (stream->output, "~>");
status = _cairo_output_stream_get_status (stream->output);
free (stream);
return status;
}
cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output)
{
cairo_base85_stream_t *stream;
stream = malloc (sizeof (cairo_base85_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->output = output;
stream->pending = 0;
return _cairo_output_stream_create (_cairo_base85_stream_write,
_cairo_base85_stream_close,
stream);
}

View File

@ -70,6 +70,9 @@ struct cairo_beos_surface_t {
BBitmap* bitmap;
// If true, surface and view should be deleted when this surface is
// destroyed
bool owns_bitmap_view;
};
class AutoLockView {
@ -92,18 +95,23 @@ class AutoLockView {
bool mOK;
};
static cairo_surface_t *
_cairo_beos_surface_create_internal (BView* view,
BBitmap* bmp,
bool owns_bitmap_view = false);
static BRect
_cairo_rect_to_brect (const cairo_rectangle_t* rect)
_cairo_rect_to_brect (const cairo_rectangle_fixed_t* rect)
{
// A BRect is one pixel wider than you'd think
return BRect(rect->x, rect->y, rect->x + rect->width - 1,
rect->y + rect->height - 1);
}
static cairo_rectangle_t
static cairo_rectangle_fixed_t
_brect_to_cairo_rect (const BRect& rect)
{
cairo_rectangle_t retval;
cairo_rectangle_fixed_t retval;
retval.x = int(rect.left + 0.5);
retval.y = int(rect.top + 0.5);
retval.width = rect.IntegerWidth() + 1;
@ -359,6 +367,7 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
return data;
}
default:
assert(0);
return NULL;
}
}
@ -414,10 +423,76 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op,
};
}
static cairo_surface_t *
_cairo_beos_surface_create_similar (void *abstract_surface,
cairo_content_t content,
int width,
int height)
{
fprintf(stderr, "Creating similar\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
BRect rect(0.0, 0.0, width - 1, height - 1);
BBitmap* bmp;
switch (content) {
case CAIRO_CONTENT_ALPHA:
// Can't support this natively
return _cairo_image_surface_create_with_content(content, width,
height);
case CAIRO_CONTENT_COLOR_ALPHA:
bmp = new BBitmap(rect, B_RGBA32, true);
break;
case CAIRO_CONTENT_COLOR:
// Match the color depth
if (surface->bitmap) {
color_space space = surface->bitmap->ColorSpace();
// No alpha was requested -> make sure not to return
// a surface with alpha
if (space == B_RGBA32)
space = B_RGB32;
if (space == B_RGBA15)
space = B_RGB15;
bmp = new BBitmap(rect, space, true);
} else {
BScreen scr(surface->view->Window());
color_space space = B_RGB32;
if (scr.IsValid())
space = scr.ColorSpace();
bmp = new BBitmap(rect, space, true);
}
break;
default:
assert(0);
return NULL;
};
BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
bmp->AddChild(view);
return _cairo_beos_surface_create_internal(view, bmp, true);
}
static cairo_status_t
_cairo_beos_surface_finish (void *abstract_surface)
{
// Nothing to do
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
if (surface->owns_bitmap_view) {
if (surface->bitmap)
surface->bitmap->RemoveChild(surface->view);
delete surface->view;
delete surface->bitmap;
surface->view = NULL;
surface->bitmap = NULL;
}
return CAIRO_STATUS_SUCCESS;
}
@ -474,11 +549,11 @@ _cairo_beos_surface_release_source_image (void *abstract_surfac
static cairo_status_t
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect,
void **image_extra)
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect,
void **image_extra)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
@ -539,23 +614,22 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface
static void
_cairo_beos_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_beos_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
fprintf(stderr, "Fallback drawing\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
if (!locker)
return;
BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
surface->view->PushState();
surface->view->SetDrawingMode(B_OP_COPY);
@ -570,18 +644,18 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
}
static cairo_int_status_t
_cairo_beos_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
_cairo_beos_surface_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
dst);
@ -617,63 +691,95 @@ _cairo_beos_composite (cairo_operator_t op,
cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
surface;
if (_cairo_surface_is_image(src_surface)) {
fprintf(stderr, "Composite\n");
// Draw it on screen.
// Get a bitmap
BBitmap* bmp = NULL;
bool free_bmp = false;
if (_cairo_surface_is_image(src_surface)) {
cairo_image_surface_t* img_surface =
reinterpret_cast<cairo_image_surface_t*>(src_surface);
BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface);
surface->view->PushState();
// If our image rect is only a subrect of the desired size, and we
// aren't using B_OP_ALPHA, then we need to fill the rect first.
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
rgb_color black = { 0, 0, 0, 0 };
surface->view->SetDrawingMode(mode);
surface->view->SetHighColor(black);
surface->view->FillRect(dstRect);
}
if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) {
mode = B_OP_COPY;
}
surface->view->SetDrawingMode(mode);
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
else
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
surface->view->DrawBitmap(bmp, srcRect, dstRect);
surface->view->PopState();
delete bmp;
return CAIRO_INT_STATUS_SUCCESS;
bmp = _cairo_image_surface_to_bitmap(img_surface);
free_bmp = true;
} else if (src_surface->backend == surface->base.backend) {
cairo_beos_surface_t *beos_surface =
reinterpret_cast<cairo_beos_surface_t*>(src_surface);
if (beos_surface->bitmap) {
AutoLockView locker(beos_surface->view);
if (locker)
beos_surface->view->Sync();
bmp = beos_surface->bitmap;
} else {
_cairo_beos_view_to_bitmap(surface->view, &bmp);
free_bmp = true;
}
}
return CAIRO_INT_STATUS_UNSUPPORTED;
if (!bmp)
return CAIRO_INT_STATUS_UNSUPPORTED;
// So, BeOS seems to screw up painting an opaque bitmap onto a
// translucent one (it makes them partly transparent). Just return
// unsupported.
if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
surface->bitmap->ColorSpace() == B_RGBA32 &&
(mode == B_OP_COPY || mode == B_OP_ALPHA))
{
if (free_bmp)
delete bmp;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
fprintf(stderr, "Composite\n");
// Draw it on screen.
surface->view->PushState();
// If our image rect is only a subrect of the desired size, and we
// aren't using B_OP_ALPHA, then we need to fill the rect first.
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
rgb_color black = { 0, 0, 0, 0 };
surface->view->SetDrawingMode(mode);
surface->view->SetHighColor(black);
surface->view->FillRect(dstRect);
}
if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
mode = B_OP_COPY;
}
surface->view->SetDrawingMode(mode);
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
else
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
surface->view->DrawBitmap(bmp, srcRect, dstRect);
surface->view->PopState();
if (free_bmp)
delete bmp;
return CAIRO_INT_STATUS_SUCCESS;
}
static void
_cairo_beos_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_t *rect)
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_fixed_t *rect)
{
BRect brect(_cairo_rect_to_brect(rect));
surface->view->FillRect(brect);
}
static cairo_int_status_t
_cairo_beos_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
@ -716,7 +822,7 @@ _cairo_beos_fill_rectangles (void *abstract_surface,
surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
for (int i = 0; i < num_rects; ++i) {
_cairo_beos_fill_rectangle(surface, &rects[i]);
_cairo_beos_surface_fill_rectangle(surface, &rects[i]);
}
surface->view->PopState();
@ -756,8 +862,8 @@ _cairo_beos_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_beos_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_beos_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
@ -778,15 +884,15 @@ _cairo_beos_surface_get_extents (void *abstract_surface,
static const struct _cairo_surface_backend cairo_beos_surface_backend = {
CAIRO_SURFACE_TYPE_BEOS,
NULL, /* create_similar */
_cairo_beos_surface_create_similar,
_cairo_beos_surface_finish,
_cairo_beos_surface_acquire_source_image,
_cairo_beos_surface_release_source_image,
_cairo_beos_surface_acquire_dest_image,
_cairo_beos_surface_release_dest_image,
NULL, /* clone_similar */
_cairo_beos_composite, /* composite */
_cairo_beos_fill_rectangles,
_cairo_beos_surface_composite, /* composite */
_cairo_beos_surface_fill_rectangles,
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
@ -807,6 +913,31 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = {
NULL /* show_glyphs */
};
static cairo_surface_t *
_cairo_beos_surface_create_internal (BView* view,
BBitmap* bmp,
bool owns_bitmap_view)
{
// Must use malloc, because cairo code will use free() on the surface
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
malloc(sizeof(cairo_beos_surface_t)));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
}
cairo_content_t content = CAIRO_CONTENT_COLOR;
if (bmp && (bmp->ColorSpace() == B_RGBA32 || bmp->ColorSpace() == B_RGBA15))
content = CAIRO_CONTENT_COLOR_ALPHA;
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend, content);
surface->view = view;
surface->bitmap = bmp;
surface->owns_bitmap_view = owns_bitmap_view;
return (cairo_surface_t *) surface;
}
/**
* cairo_beos_surface_create:
* @view: The view to draw on
@ -843,20 +974,7 @@ cairo_surface_t *
cairo_beos_surface_create_for_bitmap (BView* view,
BBitmap* bmp)
{
// Must use malloc, because cairo code will use free() on the surface
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
malloc(sizeof(cairo_beos_surface_t)));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
}
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
surface->view = view;
surface->bitmap = bmp;
return (cairo_surface_t *) surface;
return _cairo_beos_surface_create_internal(view, bmp);
}
// ---------------------------------------------------------------------------

View File

@ -88,7 +88,7 @@ typedef struct _cairo_cache_entry {
} cairo_cache_entry_t;
typedef cairo_bool_t
(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b);
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef void
(*cairo_cache_callback_func_t) (void *entry,

View File

@ -61,7 +61,7 @@ struct _cairo_clip {
* clip paths
*/
cairo_surface_t *surface;
cairo_rectangle_t surface_rect;
cairo_rectangle_fixed_t surface_rect;
/*
* Surface clip serial number to store
* in the surface when this clip is set
@ -104,20 +104,25 @@ _cairo_clip_clip (cairo_clip_t *clip,
cairo_surface_t *target);
cairo_private cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_t *rectangle);
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_fixed_t *rectangle);
cairo_private cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region16_t *region);
cairo_private cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents);
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents);
cairo_private void
_cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty);
cairo_private cairo_bool_t
_cairo_clip_has_clip (cairo_clip_t *clip);

View File

@ -119,8 +119,8 @@ _cairo_clip_reset (cairo_clip_t *clip)
}
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_t *rectangle)
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_fixed_t *rectangle)
{
if (!clip)
return CAIRO_STATUS_SUCCESS;
@ -201,12 +201,12 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
* which has its origin at dst_x, dst_y in backend coordinates
*/
cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents)
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents)
{
cairo_pattern_union_t pattern;
cairo_status_t status;
@ -336,7 +336,7 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
{
cairo_pattern_union_t pattern;
cairo_box_t extents;
cairo_rectangle_t surface_rect, target_rect;
cairo_rectangle_fixed_t surface_rect, target_rect;
cairo_surface_t *surface;
cairo_status_t status;

View File

@ -72,6 +72,7 @@ cairo_debug_reset_static_data (void)
#endif
}
#if 0
/*
* clip dumper
*/
@ -261,3 +262,4 @@ cairo_debug_dump_trapezoid_array (cairo_trapezoid_t *traps,
}
}
#endif

View File

@ -235,10 +235,10 @@ static IDirectFBSurface *cairo_directfb_buffer_surface_create(IDirectFB *dfb,voi
static cairo_status_t
_cairo_directfb_surface_get_image (cairo_directfb_surface_t *surface,
cairo_rectangle_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_t *rect_out,
DFBSurfaceLockFlags flags)
cairo_rectangle_fixed_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *rect_out,
DFBSurfaceLockFlags flags)
{
int pitch;
void *data;
@ -395,11 +395,11 @@ _cairo_directfb_surface_release_source_image (void *abstract_surface,
}
static cairo_status_t
_cairo_directfb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
void **image_extra)
_cairo_directfb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
*image_extra = interest_rect;
@ -408,11 +408,11 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_surfac
}
static void
_cairo_directfb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_directfb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer=surface->buffer;
@ -519,11 +519,11 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
#endif
static cairo_int_status_t
_cairo_directfb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int n_rects)
_cairo_directfb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int n_rects)
{
int i,k;
cairo_directfb_surface_t *surface = abstract_surface;
@ -590,8 +590,8 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
if( rectangle ) {
cairo_directfb_surface_t *surface = abstract_surface;
@ -790,7 +790,9 @@ cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *dfbsurface)
cairo_directfb_surface_t *surface = calloc(1,sizeof(cairo_directfb_surface_t));
if( surface == NULL )
return NULL;
_cairo_surface_init (&surface->base, &cairo_directfb_surface_backend);
/* XXX: The content value here might be totally wrong. */
_cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
/*Reference the surface */
dfb->AddRef(dfb);
dfbsurface->AddRef(dfbsurface);

View File

@ -210,8 +210,8 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
static int
_cairo_toy_font_face_keys_equal (void *key_a,
void *key_b);
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b);
/* We maintain a hash table from family/weight/slant =>
* cairo_font_face_t for cairo_toy_font_t. The primary purpose of
@ -312,11 +312,11 @@ _cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
}
static int
_cairo_toy_font_face_keys_equal (void *key_a,
void *key_b)
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b)
{
cairo_toy_font_face_t *face_a = key_a;
cairo_toy_font_face_t *face_b = key_b;
const cairo_toy_font_face_t *face_a = key_a;
const cairo_toy_font_face_t *face_b = key_b;
return (strcmp (face_a->family, face_b->family) == 0 &&
face_a->slant == face_b->slant &&

View File

@ -103,8 +103,8 @@ struct _cairo_ft_unscaled_font {
};
static int
_cairo_ft_unscaled_font_keys_equal (void *key_a,
void *key_b);
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
const void *key_b);
static void
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
@ -365,11 +365,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
}
static int
_cairo_ft_unscaled_font_keys_equal (void *key_a,
void *key_b)
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
const void *key_b)
{
cairo_ft_unscaled_font_t *unscaled_a = key_a;
cairo_ft_unscaled_font_t *unscaled_b = key_b;
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
unscaled_a->id == unscaled_b->id);
@ -1227,7 +1227,9 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
static cairo_ft_options_t
_get_pattern_ft_options (FcPattern *pattern)
{
FcBool antialias, vertical_layout, hinting, autohint;
FcBool antialias, vertical_layout, hinting, autohint, bitmap;
FcBool transform;
FcMatrix *font_matrix;
cairo_ft_options_t ft_options;
int rgba;
#ifdef FC_HINT_STYLE
@ -1237,15 +1239,31 @@ _get_pattern_ft_options (FcPattern *pattern)
ft_options.load_flags = 0;
ft_options.extra_flags = 0;
#ifndef FC_EMBEDDED_BITMAP
#define FC_EMBEDDED_BITMAP "embeddedbitmap"
#endif
if (FcPatternGetMatrix (pattern,
FC_MATRIX, 0, &font_matrix) != FcResultMatch)
font_matrix = NULL;
transform = (font_matrix && (font_matrix->xx != 1 || font_matrix->xy != 0 ||
font_matrix->yx != 0 || font_matrix->yy != 1));
/* Check whether to force use of embedded bitmaps */
if (FcPatternGetBool (pattern,
FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
bitmap = FcFalse;
/* disable antialiasing if requested */
if (FcPatternGetBool (pattern,
FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
antialias = FcTrue;
if (antialias)
if ((!bitmap && antialias) || transform)
ft_options.load_flags |= FT_LOAD_NO_BITMAP;
else
else if (!antialias)
ft_options.load_flags |= FT_LOAD_MONOCHROME;
/* disable hinting if requested */
@ -2145,9 +2163,10 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
*
* Creates a new font face for the FreeType font backend based on a
* fontconfig pattern. This font can then be used with
* cairo_set_font_face() or cairo_font_create(). The #cairo_scaled_font_t
* returned from cairo_font_create() is also for the FreeType backend
* and can be used with functions such as cairo_ft_font_lock_face().
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_font_lock_face().
*
* Font rendering options are representated both here and when you
* call cairo_scaled_font_create(). Font options that have a representation
@ -2198,11 +2217,12 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
* are useful. You should not pass any of the flags affecting
* the load target, such as %FT_LOAD_TARGET_LIGHT.
*
* Creates a new font face for the FreeType font backend from a pre-opened
* FreeType face. This font can then be used with
* cairo_set_font_face() or cairo_font_create(). The #cairo_scaled_font_t
* returned from cairo_font_create() is also for the FreeType backend
* and can be used with functions such as cairo_ft_font_lock_face().
* Creates a new font face for the FreeType font backend from a
* pre-opened FreeType face. This font can then be used with
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_font_lock_face().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.

View File

@ -110,10 +110,10 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
}
static cairo_status_t
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_rectangle_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_t *rect_out)
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_rectangle_fixed_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *rect_out)
{
cairo_image_surface_t *image;
int x1, y1, x2, y2;
@ -317,11 +317,11 @@ _cairo_glitz_surface_release_source_image (void *abstract_surface,
}
static cairo_status_t
_cairo_glitz_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
void **image_extra)
_cairo_glitz_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
@ -339,11 +339,11 @@ _cairo_glitz_surface_acquire_dest_image (void *abstract_surface,
}
static void
_cairo_glitz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_glitz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -918,11 +918,11 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_glitz_surface_fill_rectangles (void *abstract_dst,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int n_rects)
_cairo_glitz_surface_fill_rectangles (void *abstract_dst,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int n_rects)
{
cairo_glitz_surface_t *dst = abstract_dst;
@ -1140,7 +1140,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
int stride;
stride = (width + 3) & -4;
data = malloc (stride * height);
data = calloc (stride * height, 1);
if (!data)
{
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
@ -1149,8 +1149,6 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_STATUS_NO_MEMORY;
}
memset (data, 0, stride * height);
/* using negative stride */
ptr = (unsigned char *) data + stride * (height - 1);
@ -1258,8 +1256,8 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_glitz_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_glitz_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -2165,7 +2163,9 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend);
/* XXX: The content value here might be totally wrong. */
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
glitz_surface_reference (surface);

View File

@ -371,51 +371,6 @@ _cairo_gstate_get_original_target (cairo_gstate_t *gstate)
return gstate->original_target;
}
/**
* _cairo_gstate_get_target_offsets_from_original
* @gstate: a #cairo_gstate_t
* @dx: device offset from gstate original target
* @dy: device offset from gstate original target
*
* Return the device offsets in dx, dy for the current group target
* from the original target at the top of the gstate chain.
**/
void
_cairo_gstate_get_target_offsets_from_original (cairo_gstate_t *gstate,
double *dx,
double *dy)
{
/* Because the device offsets for the current group target are
* always relative to its parent, we have to walk up the gstate
* stack to figure out the actual device offsets. */
double x = 0.0, y = 0.0;
double prevx = 0.0, prevy = 0.0;
while (gstate) {
if (gstate->parent_target) {
/* The device offset on a group surface is relative to its
* parent; we need to recover the offset to the actual
* top-level surface origin. So we increase the offsets
* by the difference between the previous (child) and the
* current (parent). We only check for
* gstate->parent_target to catch the actual redirection
* levels; we then use the target field in the gstate,
* which is the actual group target at that point.*/
x += (prevx - gstate->target->device_x_offset);
y += (prevy - gstate->target->device_y_offset);
prevx = gstate->target->device_x_offset;
prevy = gstate->target->device_y_offset;
}
gstate = gstate->next;
}
if (dx)
*dx = x;
if (dy)
*dy = y;
}
/**
* _cairo_gstate_get_clip:
* @gstate: a #cairo_gstate_t
@ -1007,19 +962,19 @@ BAIL:
/* XXX We currently have a confusing mix of boxes and rectangles as
* exemplified by this function. A cairo_box_t is a rectangular area
* represented by the coordinates of the upper left and lower right
* corners, expressed in fixed point numbers. A cairo_rectangle_t is
* corners, expressed in fixed point numbers. A cairo_rectangle_fixed_t is
* also a rectangular area, but represented by the upper left corner
* and the width and the height, as integer numbers.
*
* This function converts a cairo_box_t to a cairo_rectangle_t by
* This function converts a cairo_box_t to a cairo_rectangle_fixed_t by
* increasing the area to the nearest integer coordinates. We should
* standardize on cairo_rectangle_t and cairo_rectangle_fixed_t, and
* standardize on cairo_rectangle_fixed_t and cairo_rectangle_fixed_t, and
* this function could be renamed to the more reasonable
* _cairo_rectangle_fixed_round.
*/
void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle)
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_fixed_t *rectangle)
{
rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
rectangle->y = _cairo_fixed_integer_floor (box->p1.y);
@ -1028,7 +983,7 @@ _cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle)
}
void
_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src)
_cairo_rectangle_intersect (cairo_rectangle_fixed_t *dest, cairo_rectangle_fixed_t *src)
{
int x1, y1, x2, y2;

View File

@ -85,7 +85,7 @@ typedef struct _cairo_hash_entry {
} cairo_hash_entry_t;
typedef cairo_bool_t
(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b);
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef cairo_bool_t
(*cairo_hash_predicate_func_t) (void *entry);

View File

@ -124,6 +124,7 @@ struct _cairo_hash_table {
cairo_hash_entry_t **entries;
unsigned long live_entries;
unsigned long iterating; /* Iterating, no insert, no resize */
};
/**
@ -163,6 +164,7 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
}
hash_table->live_entries = 0;
hash_table->iterating = 0;
return hash_table;
}
@ -179,6 +181,10 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
* and this function will halt. The rationale for this behavior is to
* avoid memory leaks and to avoid needless complication of the API
* with destroy notifiy callbacks.
*
* WARNING: The hash_table must have no running iterators in it when
* _cairo_hash_table_destroy is called. It is a fatal error otherwise,
* and this function will halt.
**/
void
_cairo_hash_table_destroy (cairo_hash_table_t *hash_table)
@ -188,6 +194,8 @@ _cairo_hash_table_destroy (cairo_hash_table_t *hash_table)
/* The hash table must be empty. Otherwise, halt. */
assert (hash_table->live_entries == 0);
/* No iterators can be running. Otherwise, halt. */
assert (hash_table->iterating == 0);
free (hash_table->entries);
hash_table->entries = NULL;
@ -440,6 +448,9 @@ _cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
* WARNING: It is a fatal error if an entry exists in the hash table
* with a matching key, (this function will halt).
*
* WARNING: It is a fatal error to insert an element while
* an iterator is running
*
* Instead of using insert to replace an entry, consider just editing
* the entry obtained with _cairo_hash_table_lookup. Or if absolutely
* necessary, use _cairo_hash_table_remove first.
@ -454,6 +465,9 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
cairo_status_t status;
cairo_hash_entry_t **entry;
/* Insert is illegal while an iterator is running. */
assert (hash_table->iterating == 0);
entry = _cairo_hash_table_lookup_internal (hash_table,
key_and_value, FALSE);
@ -498,11 +512,16 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table,
*entry = DEAD_ENTRY;
hash_table->live_entries--;
/* This call _can_ fail, but only in failing to allocate new
* memory to shrink the hash table. It does leave the table in a
* consistent state, and we've already succeeded in removing the
* entry, so we don't examine the failure status of this call. */
_cairo_hash_table_resize (hash_table);
/* Check for table resize. Don't do this when iterating as this will
* reorder elements of the table and cause the iteration to potentially
* skip some elements. */
if (hash_table->iterating == 0) {
/* This call _can_ fail, but only in failing to allocate new
* memory to shrink the hash table. It does leave the table in a
* consistent state, and we've already succeeded in removing the
* entry, so we don't examine the failure status of this call. */
_cairo_hash_table_resize (hash_table);
}
}
/**
@ -513,6 +532,12 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table,
*
* Call @hash_callback for each live entry in the hash table, in a
* non-specified order.
*
* Entries in @hash_table may be removed by code executed from @hash_callback.
*
* Entries may not be inserted to @hash_table, nor may @hash_table
* be destroyed by code executed from @hash_callback. The relevant
* functions will halt in these cases.
**/
void
_cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
@ -525,9 +550,17 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
if (hash_table == NULL)
return;
/* Mark the table for iteration */
++hash_table->iterating;
for (i = 0; i < hash_table->arrangement->size; i++) {
entry = hash_table->entries[i];
if (ENTRY_IS_LIVE(entry))
hash_callback (entry, closure);
}
/* If some elements were deleted during the iteration,
* the table may need resizing. Just do this every time
* as the check is inexpensive.
*/
if (--hash_table->iterating == 0)
_cairo_hash_table_resize (hash_table);
}

View File

@ -63,7 +63,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &cairo_image_surface_backend);
_cairo_surface_init (&surface->base, &cairo_image_surface_backend,
_cairo_content_from_format (format));
surface->pixman_image = pixman_image;
@ -188,9 +189,10 @@ _create_pixman_format (cairo_format_t format)
* @height: height of the surface, in pixels
*
* Creates an image surface of the specified format and
* dimensions. The initial contents of the surface is undefined; you
* must explicitly initialize the surface contents, using, for
* example, cairo_paint().
* dimensions. Initially the surface contents are all
* 0. (Specifically, within each pixel, each color or alpha channel
* belonging to format will be 0. The contents of bits within a pixel,
* but not belonging to the given format are undefined).
*
* Return value: a pointer to the newly created surface. The caller
* owns the surface and should call cairo_surface_destroy when done
@ -270,6 +272,9 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" surface if an error such as out of memory
* occurs. You can use cairo_surface_status() to check for this.
*
* See cairo_surface_set_user_data() for a means of attaching a
* destroy-notification fallback to the surface if necessary.
**/
cairo_surface_t *
cairo_image_surface_create_for_data (unsigned char *data,
@ -454,9 +459,9 @@ _cairo_image_surface_release_source_image (void *abstract_surf
static cairo_status_t
_cairo_image_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
cairo_image_surface_t *surface = abstract_surface;
@ -473,11 +478,11 @@ _cairo_image_surface_acquire_dest_image (void *abstract_surfa
}
static void
_cairo_image_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_image_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
}
@ -700,11 +705,11 @@ _cairo_image_surface_composite (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
cairo_image_surface_t *surface = abstract_surface;
@ -861,7 +866,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
return status;
}
static cairo_int_status_t
cairo_int_status_t
_cairo_image_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
@ -875,8 +880,8 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_image_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_image_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;

View File

@ -1,6 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -27,472 +27,374 @@
*
* The Original Code is the cairo graphics library.
*
* Contributor(s):
* Alexander Larsson <alexl@redhat.com>
* The Initial Developer of the Original Code is University of Southern
* California.
*
* This code is derived from tif_lzw.c in libtiff 3.8.0.
* The original copyright notice appears below in its entirety.
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
typedef struct _lzw_buf {
cairo_status_t status;
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
unsigned char *data;
int data_size;
int num_data;
uint32_t pending;
int pending_bits;
} lzw_buf_t;
/* An lzw_buf_t is a simple, growable chunk of memory for holding
* variable-size objects of up to 16 bits each.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Sam Leffler and Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
/*
* TIFF Library.
* Rev 5.0 Lempel-Ziv & Welch Compression Support
* Initialize an lzw_buf_t to the given size in bytes.
*
* This code is derived from the compress program whose code is
* derived from software contributed to Berkeley by James A. Woods,
* derived from original work by Spencer Thomas and Joseph Orost.
* To store objects into the lzw_buf_t, call _lzw_buf_store_bits and
* when finished, call _lzw_buf_store_pending, (which flushes out the
* last few bits that hadn't yet made a complete byte yet).
*
* The original Berkeley copyright notice appears below in its entirety.
*/
#define MAXCODE(n) ((1L<<(n))-1)
/*
* The TIFF spec specifies that encoded bit
* strings range from 9 to 12 bits.
*/
#define BITS_MIN 9 /* start with 9 bits */
#define BITS_MAX 12 /* max of 12 bit strings */
/* predefined codes */
#define CODE_CLEAR 256 /* code to clear string table */
#define CODE_EOI 257 /* end-of-information code */
#define CODE_FIRST 258 /* first free code entry */
#define CODE_MAX MAXCODE(BITS_MAX)
#define HSIZE 9001L /* 91% occupancy */
#define HSHIFT (13-8)
#ifdef LZW_COMPAT
/* NB: +1024 is for compatibility with old files */
#define CSIZE (MAXCODE(BITS_MAX)+1024L)
#else
#define CSIZE (MAXCODE(BITS_MAX)+1L)
#endif
typedef uint16_t hcode_t; /* codes fit in 16 bits */
typedef struct {
long hash;
hcode_t code;
} hash_t;
typedef struct {
/* Out buffer */
unsigned char *out_buffer; /* compressed out buffer */
size_t out_buffer_size; /* # of allocated bytes in out buffer */
unsigned char *out_buffer_pos; /* current spot in out buffer */
size_t out_buffer_bytes; /* # of data bytes in out buffer */
unsigned char *out_buffer_end; /* bound on out_buffer */
unsigned short nbits; /* # of bits/code */
unsigned short maxcode; /* maximum code for lzw_nbits */
unsigned short free_ent; /* next free entry in hash table */
long nextdata; /* next bits of i/o */
long nextbits; /* # of valid bits in lzw_nextdata */
int enc_oldcode; /* last code encountered */
long enc_checkpoint; /* point at which to clear table */
#define CHECK_GAP 10000 /* enc_ratio check interval */
long enc_ratio; /* current compression ratio */
long enc_incount; /* (input) data bytes encoded */
long enc_outcount; /* encoded (output) bytes */
hash_t* enc_hashtab; /* kept separate for small machines */
} LZWCodecState;
static void cl_hash(LZWCodecState*);
/*
* LZW Encoding.
*/
static unsigned char *
grow_out_buffer (LZWCodecState *sp, unsigned char *op)
{
size_t cc;
cc = (size_t)(op - sp->out_buffer);
sp->out_buffer_size = sp->out_buffer_size * 2;
sp->out_buffer = realloc (sp->out_buffer, sp->out_buffer_size);
/*
* The 4 here insures there is space for 2 max-sized
* codes in LZWEncode and LZWPostDecode.
*/
sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
return sp->out_buffer + cc;
}
static int
LZWSetupEncode (LZWCodecState* sp)
{
memset (sp, 0, sizeof (LZWCodecState));
sp->enc_hashtab = (hash_t*) malloc (HSIZE * sizeof (hash_t));
if (sp->enc_hashtab == NULL)
return 0;
return 1;
}
static void
LZWFreeEncode (LZWCodecState* sp)
{
if (sp->enc_hashtab)
free (sp->enc_hashtab);
}
/*
* Reset encoding state at the start of a strip.
* Instead of returning failure from any functions, lzw_buf_t provides
* a status value that the caller can query, (and should query at
* least once when done with the object). The status value will be
* either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY;
*/
static void
LZWPreEncode (LZWCodecState *sp)
_lzw_buf_init (lzw_buf_t *buf, int size)
{
sp->nbits = BITS_MIN;
sp->maxcode = MAXCODE(BITS_MIN);
sp->free_ent = CODE_FIRST;
sp->nextbits = 0;
sp->nextdata = 0;
sp->enc_checkpoint = CHECK_GAP;
sp->enc_ratio = 0;
sp->enc_incount = 0;
sp->enc_outcount = 0;
/*
* The 4 here insures there is space for 2 max-sized
* codes in LZWEncode and LZWPostDecode.
*/
sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
cl_hash(sp); /* clear hash table */
sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */
}
if (size == 0)
size = 16;
#define CALCRATIO(sp, rat) { \
if (incount > 0x007fffff) { /* NB: shift will overflow */ \
rat = outcount >> 8; \
rat = (rat == 0 ? 0x7fffffff : incount/rat); \
} else \
rat = (incount << 8) / outcount; \
}
#define PutNextCode(op, c) { \
nextdata = (nextdata << nbits) | c; \
nextbits += nbits; \
*op++ = (unsigned char)(nextdata >> (nextbits-8)); \
nextbits -= 8; \
if (nextbits >= 8) { \
*op++ = (unsigned char)(nextdata >> (nextbits-8)); \
nextbits -= 8; \
} \
outcount += nbits; \
}
buf->status = CAIRO_STATUS_SUCCESS;
/*
* Encode a chunk of pixels.
*
* Uses an open addressing double hashing (no chaining) on the
* prefix code/next character combination. We do a variant of
* Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
* relatively-prime secondary probe. Here, the modular division
* first probe is gives way to a faster exclusive-or manipulation.
* Also do block compression with an adaptive reset, whereby the
* code table is cleared when the compression ratio decreases,
* but after the table fills. The variable-length output codes
* are re-sized at this point, and a CODE_CLEAR is generated
* for the decoder.
*/
static int
LZWEncode (LZWCodecState *sp,
unsigned char *bp,
size_t cc)
{
register long fcode;
register hash_t *hp;
register int h, c;
hcode_t ent;
long disp;
long incount, outcount, checkpoint;
long nextdata, nextbits;
int free_ent, maxcode, nbits;
unsigned char *op;
/*
* Load local state.
*/
incount = sp->enc_incount;
outcount = sp->enc_outcount;
checkpoint = sp->enc_checkpoint;
nextdata = sp->nextdata;
nextbits = sp->nextbits;
free_ent = sp->free_ent;
maxcode = sp->maxcode;
nbits = sp->nbits;
op = sp->out_buffer_pos;
ent = sp->enc_oldcode;
if (ent == (hcode_t) -1 && cc > 0) {
/*
* NB: This is safe because it can only happen
* at the start of a strip where we know there
* is space in the data buffer.
*/
PutNextCode(op, CODE_CLEAR);
ent = *bp++; cc--; incount++;
buf->data = malloc (size);
if (buf->data == NULL) {
buf->data_size = 0;
buf->status = CAIRO_STATUS_NO_MEMORY;
return;
}
while (cc > 0) {
c = *bp++; cc--; incount++;
fcode = ((long)c << BITS_MAX) + ent;
h = (c << HSHIFT) ^ ent; /* xor hashing */
#ifdef _WINDOWS
/*
* Check hash index for an overflow.
*/
if (h >= HSIZE)
h -= HSIZE;
#endif
hp = &sp->enc_hashtab[h];
if (hp->hash == fcode) {
ent = hp->code;
continue;
buf->data_size = size;
buf->num_data = 0;
buf->pending = 0;
buf->pending_bits = 0;
}
/* Increase the buffer size by doubling.
*
* Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
*/
static cairo_status_t
_lzw_buf_grow (lzw_buf_t *buf)
{
int new_size = buf->data_size * 2;
unsigned char *new_data;
if (buf->status)
return buf->status;
new_data = realloc (buf->data, new_size);
if (new_data == NULL) {
free (buf->data);
buf->data_size = 0;
buf->status = CAIRO_STATUS_NO_MEMORY;
return buf->status;
}
buf->data = new_data;
buf->data_size = new_size;
return CAIRO_STATUS_SUCCESS;
}
/* Store the lowest num_bits bits of values into buf.
*
* NOTE: The bits of value above size_in_bits must be 0, (so don't lie
* about the size).
*
* See also _lzw_buf_store_pending which must be called after the last
* call to _lzw_buf_store_bits.
*
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
*/
static void
_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits)
{
cairo_status_t status;
assert (value <= (1 << num_bits) - 1);
if (buf->status)
return;
buf->pending = (buf->pending << num_bits) | value;
buf->pending_bits += num_bits;
while (buf->pending_bits >= 8) {
if (buf->num_data >= buf->data_size) {
status = _lzw_buf_grow (buf);
if (status)
return;
}
if (hp->hash >= 0) {
/*
* Primary hash failed, check secondary hash.
*/
disp = HSIZE - h;
if (h == 0)
disp = 1;
do {
/*
* Avoid pointer arithmetic 'cuz of
* wraparound problems with segments.
*/
if ((h -= disp) < 0)
h += HSIZE;
hp = &sp->enc_hashtab[h];
if (hp->hash == fcode) {
ent = hp->code;
goto hit;
}
} while (hp->hash >= 0);
buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8);
buf->pending_bits -= 8;
}
}
/* Store the last remaining pending bits into the buffer.
*
* NOTE: This function must be called after the last call to
* _lzw_buf_store_bits.
*
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
*/
static void
_lzw_buf_store_pending (lzw_buf_t *buf)
{
cairo_status_t status;
if (buf->status)
return;
if (buf->pending_bits == 0)
return;
assert (buf->pending_bits < 8);
if (buf->num_data >= buf->data_size) {
status = _lzw_buf_grow (buf);
if (status)
return;
}
buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits);
buf->pending_bits = 0;
}
/* LZW defines a few magic code values */
#define LZW_CODE_CLEAR_TABLE 256
#define LZW_CODE_EOD 257
#define LZW_CODE_FIRST 258
/* We pack three separate values into a symbol as follows:
*
* 12 bits (31 down to 20): CODE: code value used to represent this symbol
* 12 bits (19 down to 8): PREV: previous code value in chain
* 8 bits ( 7 down to 0): NEXT: next byte value in chain
*/
typedef uint32_t lzw_symbol_t;
#define LZW_SYMBOL_SET(sym, prev, next) ((sym) = ((prev) << 8)|(next))
#define LZW_SYMBOL_SET_CODE(sym, code, prev, next) ((sym) = ((code << 20)|(prev) << 8)|(next))
#define LZW_SYMBOL_GET_CODE(sym) (((sym) >> 20))
#define LZW_SYMBOL_GET_PREV(sym) (((sym) >> 8) & 0x7ff)
#define LZW_SYMBOL_GET_BYTE(sym) (((sym) >> 0) & 0x0ff)
/* The PREV+NEXT fields can be seen as the key used to fetch values
* from the hash table, while the code is the value fetched.
*/
#define LZW_SYMBOL_KEY_MASK 0x000fffff
/* Since code values are only stored starting with 258 we can safely
* use a zero value to represent free slots in the hash table. */
#define LZW_SYMBOL_FREE 0x00000000
/* These really aren't very free for modifying. First, the PostScript
* specification sets the 9-12 bit range. Second, the encoding of
* lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte
* fitting within 32 bits.
*
* But other than that, the LZW compression scheme could function with
* more bits per code.
*/
#define LZW_BITS_MIN 9
#define LZW_BITS_MAX 12
#define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1)
#define LZW_MAX_SYMBOLS (1<<LZW_BITS_MAX)
#define LZW_SYMBOL_TABLE_SIZE 9013
#define LZW_SYMBOL_MOD1 LZW_SYMBOL_TABLE_SIZE
#define LZW_SYMBOL_MOD2 9011
typedef struct _lzw_symbol_table {
lzw_symbol_t table[LZW_SYMBOL_TABLE_SIZE];
} lzw_symbol_table_t;
/* Initialize the hash table to entirely empty */
static void
_lzw_symbol_table_init (lzw_symbol_table_t *table)
{
memset (table->table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t));
}
/* Lookup a symbol in the symbol table. The PREV and NEXT fields of
* symbol form the key for the lookup.
*
* If succesful, then this function returns TRUE and slot_ret will be
* left pointing at the result that will have the CODE field of
* interest.
*
* If the lookup fails, then this function returns FALSE and slot_ret
* will be pointing at the location in the table to which a new CODE
* value should be stored along with PREV and NEXT.
*/
static cairo_bool_t
_lzw_symbol_table_lookup (lzw_symbol_table_t *table,
lzw_symbol_t symbol,
lzw_symbol_t **slot_ret)
{
/* The algorithm here is identical to that in cairo-hash.c. We
* copy it here to allow for a rather more efficient
* implementation due to several circumstances that do not apply
* to the more general case:
*
* 1) We have a known bound on the total number of symbols, so we
* have a fixed-size table without any copying when growing
*
* 2) We never delete any entries, so we don't need to
* support/check for DEAD entries during lookup.
*
* 3) The object fits in 32 bits so we store each object in its
* entirety within the table rather than storing objects
* externally and putting pointers in the table, (which here
* would just double the storage requirements and have negative
* impacts on memory locality).
*/
int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK;
lzw_symbol_t candidate;
idx = hash % LZW_SYMBOL_MOD1;
step = 0;
*slot_ret = NULL;
for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++)
{
candidate = table->table[idx];
if (candidate == LZW_SYMBOL_FREE)
{
*slot_ret = &table->table[idx];
return FALSE;
}
/*
* New entry, emit code and add to table.
*/
/*
* Verify there is space in the buffer for the code
* and any potential Clear code that might be emitted
* below. The value of limit is setup so that there
* are at least 4 bytes free--room for 2 codes.
*/
if (op > sp->out_buffer_end) {
op = grow_out_buffer (sp, op);
if (sp->out_buffer == NULL) {
return 0;
else /* candidate is LIVE */
{
if ((candidate & LZW_SYMBOL_KEY_MASK) ==
(symbol & LZW_SYMBOL_KEY_MASK))
{
*slot_ret = &table->table[idx];
return TRUE;
}
}
PutNextCode(op, ent);
ent = c;
hp->code = free_ent++;
hp->hash = fcode;
if (free_ent == CODE_MAX-1) {
/* table is full, emit clear code and reset */
cl_hash(sp);
sp->enc_ratio = 0;
incount = 0;
outcount = 0;
free_ent = CODE_FIRST;
PutNextCode(op, CODE_CLEAR);
nbits = BITS_MIN;
maxcode = MAXCODE(BITS_MIN);
} else {
/*
* If the next entry is going to be too big for
* the code size, then increase it, if possible.
*/
if (free_ent > maxcode) {
nbits++;
assert(nbits <= BITS_MAX);
maxcode = (int) MAXCODE(nbits);
} else if (incount >= checkpoint) {
long rat;
/*
* Check compression ratio and, if things seem
* to be slipping, clear the hash table and
* reset state. The compression ratio is a
* 24+8-bit fractional number.
*/
checkpoint = incount+CHECK_GAP;
CALCRATIO(sp, rat);
if (rat <= sp->enc_ratio) {
cl_hash(sp);
sp->enc_ratio = 0;
incount = 0;
outcount = 0;
free_ent = CODE_FIRST;
PutNextCode(op, CODE_CLEAR);
nbits = BITS_MIN;
maxcode = MAXCODE(BITS_MIN);
} else
sp->enc_ratio = rat;
if (step == 0) {
step = hash % LZW_SYMBOL_MOD2;
if (step == 0)
step = 1;
}
idx += step;
if (idx >= LZW_SYMBOL_TABLE_SIZE)
idx -= LZW_SYMBOL_TABLE_SIZE;
}
return FALSE;
}
/* Compress a bytestream using the LZW algorithm.
*
* This is an original implementation based on reading the
* specification of the LZWDecode filter in the PostScript Language
* Reference. The free parameters in the LZW algorithm are set to the
* values mandated by PostScript, (symbols encoded with widths from 9
* to 12 bits).
*
* This function returns a pointer to a newly allocated buffer holding
* the compressed data, or NULL if an out-of-memory situation
* occurs.
*
* Notice that any one of the _lzw_buf functions called here could
* trigger an out-of-memory condition. But lzw_buf_t uses cairo's
* shutdown-on-error idiom, so it's safe to continue to call into
* lzw_buf without having to check for errors, (until a final check at
* the end).
*/
unsigned char *
_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out)
{
int bytes_remaining = *size_in_out;
lzw_buf_t buf;
lzw_symbol_table_t table;
lzw_symbol_t symbol, *slot = NULL; /* just to squelch a warning */
int code_next = LZW_CODE_FIRST;
int code_bits = LZW_BITS_MIN;
int prev, next = 0; /* just to squelch a warning */
if (*size_in_out == 0)
return NULL;
_lzw_buf_init (&buf, *size_in_out);
_lzw_symbol_table_init (&table);
/* The LZW header is a clear table code. */
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
while (1) {
/* Find the longest existing code in the symbol table that
* matches the current input, if any. */
prev = *data++;
bytes_remaining--;
if (bytes_remaining) {
do
{
next = *data++;
bytes_remaining--;
LZW_SYMBOL_SET (symbol, prev, next);
if (_lzw_symbol_table_lookup (&table, symbol, &slot))
prev = LZW_SYMBOL_GET_CODE (*slot);
} while (bytes_remaining && *slot != LZW_SYMBOL_FREE);
if (*slot == LZW_SYMBOL_FREE) {
data--;
bytes_remaining++;
}
}
hit:
;
}
/*
* Restore global state.
*/
sp->enc_incount = incount;
sp->enc_outcount = outcount;
sp->enc_checkpoint = checkpoint;
sp->enc_oldcode = ent;
sp->nextdata = nextdata;
sp->nextbits = nextbits;
sp->free_ent = free_ent;
sp->maxcode = maxcode;
sp->nbits = nbits;
sp->out_buffer_pos = op;
return 1;
}
/*
* Finish off an encoded strip by flushing the last
* string and tacking on an End Of Information code.
*/
static int
LZWPostEncode (LZWCodecState *sp)
{
unsigned char *op = sp->out_buffer_pos;
long nextbits = sp->nextbits;
long nextdata = sp->nextdata;
long outcount = sp->enc_outcount;
int nbits = sp->nbits;
if (op > sp->out_buffer_end) {
op = grow_out_buffer (sp, op);
if (sp->out_buffer == NULL) {
return 0;
/* Write the code into the output. This is either a byte read
* directly from the input, or a code from the last successful
* lookup. */
_lzw_buf_store_bits (&buf, prev, code_bits);
if (bytes_remaining == 0)
break;
LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next);
if (code_next > LZW_BITS_BOUNDARY(code_bits))
{
code_bits++;
if (code_bits > LZW_BITS_MAX) {
_lzw_symbol_table_init (&table);
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1);
code_bits = LZW_BITS_MIN;
code_next = LZW_CODE_FIRST;
}
}
}
if (sp->enc_oldcode != (hcode_t) -1) {
PutNextCode(op, sp->enc_oldcode);
sp->enc_oldcode = (hcode_t) -1;
/* The LZW footer is an end-of-data code. */
_lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits);
_lzw_buf_store_pending (&buf);
/* See if we ever ran out of memory while writing to buf. */
if (buf.status == CAIRO_STATUS_NO_MEMORY) {
*size_in_out = 0;
return NULL;
}
PutNextCode(op, CODE_EOI);
if (nextbits > 0)
*op++ = (unsigned char)(nextdata << (8-nextbits));
sp->out_buffer_bytes = (size_t)(op - sp->out_buffer);
return 1;
}
/*
* Reset encoding hash table.
*/
static void
cl_hash (LZWCodecState* sp)
{
register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
register long i = HSIZE-8;
do {
i -= 8;
hp[-7].hash = -1;
hp[-6].hash = -1;
hp[-5].hash = -1;
hp[-4].hash = -1;
hp[-3].hash = -1;
hp[-2].hash = -1;
hp[-1].hash = -1;
hp[ 0].hash = -1;
hp -= 8;
} while (i >= 0);
for (i += 8; i > 0; i--, hp--)
hp->hash = -1;
}
/*
* Copyright (c) 1985, 1986 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* James A. Woods, derived from original work by Spencer Thomas
* and Joseph Orost.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
void *
_cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compressed_size)
{
LZWCodecState state;
if (!LZWSetupEncode (&state))
goto bail0;
state.out_buffer_size = data_size/4;
/* We need *some* space at least */
if (state.out_buffer_size < 256)
state.out_buffer_size = 256;
state.out_buffer = malloc (state.out_buffer_size);
if (state.out_buffer == NULL)
goto bail1;
state.out_buffer_pos = state.out_buffer;
state.out_buffer_bytes = 0;
LZWPreEncode (&state);
if (!LZWEncode (&state, data, data_size))
goto bail2;
if (!LZWPostEncode(&state))
goto bail2;
LZWFreeEncode(&state);
*compressed_size = state.out_buffer_bytes;
return state.out_buffer;
bail2:
if (state.out_buffer)
free (state.out_buffer);
bail1:
LZWFreeEncode(&state);
bail0:
return NULL;
assert (buf.status == CAIRO_STATUS_SUCCESS);
*size_in_out = buf.num_data;
return buf.data;
}

View File

@ -556,6 +556,38 @@ _cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
return TRUE;
}
cairo_bool_t
_cairo_matrix_is_integer_translation_and_scale(const cairo_matrix_t *m,
int *itx, int *ity, int *sx, int *sy)
{
cairo_fixed_t x0_fixed, y0_fixed, xx_fixed, yy_fixed;
if ((m->yx != 0.0) || (m->yy != 0.0))
return FALSE;
x0_fixed = _cairo_fixed_from_double (m->x0);
y0_fixed = _cairo_fixed_from_double (m->y0);
xx_fixed = _cairo_fixed_from_double (m->xx);
yy_fixed = _cairo_fixed_from_double (m->yy);
if (!_cairo_fixed_is_integer(x0_fixed) ||
!_cairo_fixed_is_integer(y0_fixed) ||
!_cairo_fixed_is_integer(xx_fixed) ||
!_cairo_fixed_is_integer(yy_fixed))
return FALSE;
if (itx)
*itx = _cairo_fixed_integer_part(x0_fixed);
if (ity)
*ity = _cairo_fixed_integer_part(y0_fixed);
if (sx)
*sx = _cairo_fixed_integer_part(xx_fixed);
if (sy)
*sy = _cairo_fixed_integer_part(yy_fixed);
return TRUE;
}
/*
A circle in user space is transformed into an ellipse in device space.

View File

@ -137,6 +137,9 @@ typedef struct _cairo_meta_surface {
cairo_array_t commands;
cairo_surface_t *commands_owner;
cairo_bool_t is_clipped;
int replay_start_idx;
} cairo_meta_surface_t;
cairo_private cairo_surface_t *

View File

@ -72,7 +72,8 @@ _cairo_meta_surface_create (cairo_content_t content,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
content);
meta->content = content;
meta->width_pixels = width_pixels;
@ -81,6 +82,9 @@ _cairo_meta_surface_create (cairo_content_t content,
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
meta->commands_owner = NULL;
meta->is_clipped = FALSE;
meta->replay_start_idx = 0;
return &meta->base;
}
@ -226,6 +230,12 @@ _cairo_meta_surface_paint (void *abstract_surface,
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_paint_t *command;
/* An optimisation that takes care to not replay what was done
* before surface is cleared. We don't erase recorded commands
* since we may have earlier snapshots of this surface. */
if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
meta->replay_start_idx = meta->commands.num_elements;
command = malloc (sizeof (cairo_command_paint_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -468,11 +478,14 @@ _cairo_meta_surface_snapshot (void *abstract_other)
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
other->base.content);
meta->base.is_snapshot = TRUE;
meta->width_pixels = other->width_pixels;
meta->height_pixels = other->height_pixels;
meta->replay_start_idx = other->replay_start_idx;
meta->content = other->content;
_cairo_array_init_snapshot (&meta->commands, &other->commands);
meta->commands_owner = cairo_surface_reference (&other->base);
@ -504,8 +517,10 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
return status;
}
command->path_pointer = &command->path;
meta->is_clipped = TRUE;
} else {
command->path_pointer = NULL;
meta->is_clipped = FALSE;
}
command->fill_rule = fill_rule;
command->tolerance = tolerance;
@ -531,8 +546,8 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
* added to it.
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
rectangle->x = 0;
rectangle->y = 0;
@ -610,7 +625,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
num_elements = meta->commands.num_elements;
elements = _cairo_array_index (&meta->commands, 0);
for (i = 0; i < num_elements; i++) {
for (i = meta->replay_start_idx; i < num_elements; i++) {
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_PAINT:

View File

@ -0,0 +1,119 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Keith Packard
* Copyright © 2006 Red Hat, Inc
*
* 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 University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Keith Packard <keithp@keithp.com>
*/
#include "cairoint.h"
/* The analysis here assumes destination alpha semantics (that is
* CAIRO_CONTENT_COLOR_ALPHA). More things can be considered opaque
* otherwise (CAIRO_CONTENT_COLOR) so we'll probably want to add a
* cairo_content_t parameter to this function
*
* We also need a definition of what "opaque" means. Is it, "does not
* requiring 'knowing' the original contents of destination, nor does
* it set the destination alpha to anything but 1.0" ?
*/
cairo_bool_t
_cairo_operator_always_opaque (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return FALSE;
case CAIRO_OPERATOR_SOURCE:
return FALSE;
case CAIRO_OPERATOR_OVER:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
return FALSE;
case CAIRO_OPERATOR_DEST:
return TRUE;
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
return FALSE;
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_ADD:
case CAIRO_OPERATOR_SATURATE:
return FALSE;
}
return FALSE;
}
/* As above, we'll probably want to add a cairo_content_t parameter to
* this function
*
* We also need a definition of what "translucent" means.
*/
cairo_bool_t
_cairo_operator_always_translucent (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return TRUE;
case CAIRO_OPERATOR_SOURCE:
return FALSE;
case CAIRO_OPERATOR_OVER:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
return FALSE;
case CAIRO_OPERATOR_DEST:
return FALSE;
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
return FALSE;
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_ADD:
case CAIRO_OPERATOR_SATURATE:
return TRUE;
}
return TRUE;
}

View File

@ -44,54 +44,98 @@
#endif /* _MSC_VER */
struct _cairo_output_stream {
cairo_write_func_t write_data;
cairo_write_func_t write_func;
cairo_close_func_t close_func;
void *closure;
cairo_bool_t owns_closure_is_file;
unsigned long position;
cairo_status_t status;
cairo_bool_t closed;
};
const cairo_output_stream_t cairo_output_stream_nil = {
NULL, /* write_func */
NULL, /* close_func */
NULL, /* closure */
0, /* position */
CAIRO_STATUS_NO_MEMORY,
FALSE /* closed */
};
static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
NULL, /* write_func */
NULL, /* close_func */
NULL, /* closure */
0, /* position */
CAIRO_STATUS_WRITE_ERROR,
FALSE /* closed */
};
cairo_output_stream_t *
_cairo_output_stream_create (cairo_write_func_t write_data,
_cairo_output_stream_create (cairo_write_func_t write_func,
cairo_close_func_t close_func,
void *closure)
{
cairo_output_stream_t *stream;
stream = malloc (sizeof (cairo_output_stream_t));
if (stream == NULL)
return NULL;
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->write_data = write_data;
stream->write_func = write_func;
stream->close_func = close_func;
stream->closure = closure;
stream->owns_closure_is_file = FALSE;
stream->position = 0;
stream->status = CAIRO_STATUS_SUCCESS;
stream->closed = FALSE;
return stream;
}
void
_cairo_output_stream_close (cairo_output_stream_t *stream)
{
cairo_status_t status;
if (stream->closed)
return;
if (stream == &cairo_output_stream_nil ||
stream == &cairo_output_stream_nil_write_error)
{
return;
}
if (stream->close_func) {
status = stream->close_func (stream->closure);
if (status)
stream->status = status;
}
stream->closed = TRUE;
}
void
_cairo_output_stream_destroy (cairo_output_stream_t *stream)
{
if (stream->owns_closure_is_file) {
FILE *file = stream->closure;
fflush (file);
fclose (file);
}
if (stream == NULL)
return;
_cairo_output_stream_close (stream);
free (stream);
}
cairo_status_t
void
_cairo_output_stream_write (cairo_output_stream_t *stream,
const void *data, size_t length)
{
if (length == 0)
return CAIRO_STATUS_SUCCESS;
return;
stream->status = stream->write_data (stream->closure, data, length);
if (stream->status)
return;
stream->status = stream->write_func (stream->closure, data, length);
stream->position += length;
return stream->status;
}
void
@ -103,6 +147,9 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
char buffer[2];
int i, column;
if (stream->status)
return;
for (i = 0, column = 0; i < length; i++, column++) {
if (column == 38) {
_cairo_output_stream_write (stream, "\n", 1);
@ -114,72 +161,13 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
}
}
static cairo_bool_t
convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
{
cairo_bool_t all_zero;
uint32_t value;
int digit, i;
value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
all_zero = TRUE;
for (i = 0; i < 5; i++) {
digit = value % 85;
if (digit != 0)
all_zero = FALSE;
five_tuple[4-i] = digit + 33;
value = value / 85;
}
return all_zero;
}
void
_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
const char *data,
size_t length)
{
unsigned char *ptr;
unsigned char four_tuple[4];
char five_tuple[5];
int column;
ptr = (unsigned char *)data;
column = 0;
while (length > 0) {
if (length >= 4) {
if (convert_four_tuple (ptr, five_tuple)) {
column += 1;
_cairo_output_stream_write (stream, "z", 1);
} else {
column += 5;
_cairo_output_stream_write (stream, five_tuple, 5);
}
length -= 4;
ptr += 4;
} else { /* length < 4 */
memset (four_tuple, 0, 4);
memcpy (four_tuple, ptr, length);
convert_four_tuple (four_tuple, five_tuple);
column += length + 1;
_cairo_output_stream_write (stream, five_tuple, length + 1);
length = 0;
}
if (column >= 72) {
_cairo_output_stream_write (stream, "\n", 1);
column = 0;
}
}
if (column > 0) {
_cairo_output_stream_write (stream, "\n", 1);
}
}
/* Format a double in a locale independent way and trim trailing
* zeros. Based on code from Alex Larson <alexl@redhat.com>.
* http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
*
* The code in the patch is copyright Red Hat, Inc under the LGPL, but
* has been relicensed under the LGPL/MPL dual license for inclusion
* into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
*/
int
@ -238,8 +226,7 @@ enum {
* formatting. This functionality is only for internal use and we
* only implement the formats we actually use.
*/
cairo_status_t
void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap)
{
@ -248,6 +235,9 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *f;
int length_modifier;
if (stream->status)
return;
f = fmt;
p = buffer;
while (*f != '\0') {
@ -310,24 +300,19 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
}
_cairo_output_stream_write (stream, buffer, p - buffer);
return stream->status;
}
cairo_status_t
void
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...)
{
va_list ap;
cairo_status_t status;
va_start (ap, fmt);
status = _cairo_output_stream_vprintf (stream, fmt, ap);
_cairo_output_stream_vprintf (stream, fmt, ap);
va_end (ap);
return status;
}
long
@ -349,30 +334,57 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream)
static cairo_status_t
stdio_write (void *closure, const unsigned char *data, unsigned int length)
{
FILE *fp = closure;
FILE *file = closure;
if (fwrite (data, 1, length, fp) == length)
if (fwrite (data, 1, length, file) != length)
return CAIRO_STATUS_WRITE_ERROR;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
stdio_flush (void *closure)
{
FILE *file = closure;
fflush (file);
if (ferror (file))
return CAIRO_STATUS_WRITE_ERROR;
else
return CAIRO_STATUS_SUCCESS;
}
return CAIRO_STATUS_WRITE_ERROR;
static cairo_status_t
stdio_close (void *closure)
{
cairo_status_t status;
FILE *file = closure;
status = stdio_flush (closure);
fclose (file);
return status;
}
cairo_output_stream_t *
_cairo_output_stream_create_for_file (const char *filename)
_cairo_output_stream_create_for_file (FILE *file)
{
FILE *fp;
cairo_output_stream_t *stream;
if (file == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
fp = fopen (filename, "wb");
if (fp == NULL)
return NULL;
stream = _cairo_output_stream_create (stdio_write, fp);
if (stream)
stream->owns_closure_is_file = TRUE;
else
fclose (fp);
return stream;
return _cairo_output_stream_create (stdio_write, stdio_flush, file);
}
cairo_output_stream_t *
_cairo_output_stream_create_for_filename (const char *filename)
{
FILE *file;
file = fopen (filename, "wb");
if (file == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
return _cairo_output_stream_create (stdio_write, stdio_close, file);
}

View File

@ -38,11 +38,99 @@
#include "cairoint.h"
typedef enum {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
} cairo_paginated_mode_t;
typedef struct _cairo_paginated_surface_backend {
/* Optional. Will be called once for each page.
*
* NOTE: With respect to the order of drawing operations as seen
* by the target, this call will occur before any drawing
* operations for the relevant page. However, with respect to the
* function calls as made by the user, this call will be *after*
* any drawing operations for the page, (that is, it will occur
* during the user's call to cairo_show_page or cairo_copy_page).
*/
cairo_int_status_t
(*start_page) (void *surface);
/* Required. Will be called twice for each page, once with an
* argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
* CAIRO_PAGINATED_MODE_RENDER. See more details in the
* documentation for _cairo_paginated_surface_create below.
*/
void
(*set_paginated_mode) (void *surface,
cairo_paginated_mode_t mode);
} cairo_paginated_surface_backend_t;
/* A cairo_paginated_surface provides a very convenient wrapper that
* is well-suited for doing the analysis common to most surfaces that
* have paginated output, (that is, things directed at printers, or
* for saving content in files such as PostScript or PDF files).
*
* To use the paginated surface, you'll first need to create your
* 'real' surface using _cairo_surface_init and the standard
* cairo_surface_backend_t. Then you also call
* _cairo_paginated_surface_create which takes its own, much simpler,
* cairo_paginated_surface_backend. You are free to return the result
* of _cairo_paginated_surface_create from your public
* cairo_<foo>_surface_create. The paginated backend will be careful
* to not let the user see that they really got a "wrapped"
* surface. See test-paginated-surface.c for a fairly minimal example
* of a paginated-using surface. That should be a reasonable example
* to follow.
*
* What the paginated surface does is first save all drawing
* operations for a page into a meta-surface. Then when the user calls
* cairo_show_page, the paginated surface performs the following
* sequence of operations (using the backend functions passed to
* cairo_paginated_surface_create):
*
* 1. Calls start_page (if non NULL). At this point, it is appropriate
* for the target to emit any page-specific header information into
* its output.
*
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
*
* 3. Replays the meta-surface to the target surface, (with an
* analysis surface inserted between which watches the return value
* from each operation). This analysis stage is used to decide which
* operations will require fallbacks.
*
* 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
*
* 5. Replays a subset of the meta-surface operations to the target surface
*
* 6. Replays the remaining operations to an image surface, sets an
* appropriate clip on the target, then paints the resulting image
* surface to the target.
*
* So, the target will see drawing operations during two separate
* stages, (ANALYZE and RENDER). During the ANALYZE phase the target
* should not actually perform any rendering, (for example, if
* performing output to a file, no output should be generated during
* this stage). Instead the drawing functions simply need to return
* CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
* whether rendering would be supported. And it should do this as
* quickly as possible.
*
* NOTE: The paginated surface layer assumes that the target surface
* is "blank" by default at the beginning of each page, without any
* need for an explicit erasea operation, (as opposed to an image
* surface, for example, which might have uninitialized content
* originally). As such, it optimizes away CLEAR operations that
* happen at the beginning of each page---the target surface will not
* even see these operations.
*/
cairo_private cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
int height);
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
int height,
const cairo_paginated_surface_backend_t *backend);
cairo_private cairo_surface_t *
_cairo_paginated_surface_get_target (cairo_surface_t *surface);

View File

@ -31,47 +31,27 @@
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
* Keith Packard <keithp@keithp.com>
*/
/* The paginated surface layer exists to provide as much code sharing
* as possible for the various paginated surface backends in cairo
* (PostScript, PDF, etc.).
*
* The concept is that a surface which uses a paginated surface merely
* needs to implement backend operations which it can accurately
* provide, (and return CAIRO_INT_STATUS_UNSUPPORTED or leave backend
* function pointers NULL otherwise). The paginated surface is the
* responsible for collecting operations that aren't supported,
* replaying them against the image surface, and then supplying the
* resulting images to the target surface.
*
* When created, a paginated surface accepts the target surface to
* which the final drawing will eventually be performed. The paginated
* surface then uses cairo_meta_surface_t to record all drawing
* operations up until each show_page operation.
*
* At the time of show_page, the paginated surface replays the meta
* surface against the target surface and maintains regions of the
* result that will come from the nativ surface and regions that will
* need to come from image fallbacks. It then replays the necessary
* portions against image surface and provides those results to the
* target surface through existing interfaces.
*
* This way the target surface is never even aware of any distinction
* between native drawing operations vs. results that are supplied by
* image fallbacks. Instead the surface need only implement as much of
* the surface backend interface as it can do correctly, and let the
* paginated surface take care of all the messy details.
* (PostScript, PDF, etc.). See cairo-paginated-surface-private.h for
* more details on how it works and how to use it.
*/
#include "cairoint.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-analysis-surface-private.h"
typedef struct _cairo_paginated_surface {
cairo_surface_t base;
/* The target surface to hold the final result. */
cairo_surface_t *target;
cairo_content_t content;
/* XXX: These shouldn't actually exist. We inherit this ugliness
@ -82,14 +62,16 @@ typedef struct _cairo_paginated_surface {
int width;
int height;
/* The target surface to hold the final result. */
cairo_surface_t *target;
/* Paginated-surface specific functions for the target */
const cairo_paginated_surface_backend_t *backend;
/* A cairo_meta_surface to record all operations. To be replayed
* against target, and also against image surface as necessary for
* fallbacks. */
cairo_surface_t *meta;
cairo_bool_t page_is_blank;
} cairo_paginated_surface_t;
const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
@ -97,12 +79,6 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface);
/* XXX: This would seem the natural thing to do here. But currently,
* PDF and PS surfaces do not yet work as source surfaces. So instead,
* we don't implement create_similar for the paginate_surface which
* means that any create_similar() call on a paginated_surfacae will
* result in a new image surface. */
#if 0
static cairo_surface_t *
_cairo_paginated_surface_create_similar (void *abstract_surface,
cairo_content_t content,
@ -113,13 +89,13 @@ _cairo_paginated_surface_create_similar (void *abstract_surface,
return cairo_surface_create_similar (surface->target, content,
width, height);
}
#endif
cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
int height)
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
int height,
const cairo_paginated_surface_backend_t *backend)
{
cairo_paginated_surface_t *surface;
@ -127,22 +103,27 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
if (surface == NULL)
goto FAIL;
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend);
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend,
content);
/* Override surface->base.type with target's type so we don't leak
* evidence of the paginated wrapper out to the user. */
surface->base.type = cairo_surface_get_type (target);
surface->target = target;
surface->content = content;
surface->width = width;
surface->height = height;
surface->target = target;
surface->backend = backend;
surface->meta = _cairo_meta_surface_create (content, width, height);
if (cairo_surface_status (surface->meta))
goto FAIL_CLEANUP_SURFACE;
surface->page_is_blank = TRUE;
return &surface->base;
FAIL_CLEANUP_SURFACE:
@ -189,7 +170,7 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_t *image;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
_cairo_surface_get_extents (surface->target, &extents);
@ -213,32 +194,72 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface,
cairo_surface_destroy (&image->base);
}
static void
static cairo_int_status_t
_paint_page (cairo_paginated_surface_t *surface)
{
cairo_surface_t *analysis;
cairo_surface_t *image;
cairo_pattern_t *pattern;
cairo_status_t status;
image = _cairo_image_surface_create_with_content (surface->content,
surface->width,
surface->height);
analysis = _cairo_analysis_surface_create (surface->target,
surface->width, surface->height);
_cairo_meta_surface_replay (surface->meta, image);
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
_cairo_meta_surface_replay (surface->meta, analysis);
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
pattern = cairo_pattern_create_for_surface (image);
if (analysis->status) {
status = analysis->status;
cairo_surface_destroy (analysis);
return status;
}
if (_cairo_analysis_surface_has_unsupported (analysis))
{
image = _cairo_image_surface_create_with_content (surface->content,
surface->width,
surface->height);
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
_cairo_meta_surface_replay (surface->meta, image);
cairo_pattern_destroy (pattern);
pattern = cairo_pattern_create_for_surface (image);
cairo_surface_destroy (image);
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (image);
}
else
{
_cairo_meta_surface_replay (surface->meta, surface->target);
}
cairo_surface_destroy (analysis);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_start_page (cairo_paginated_surface_t *surface)
{
if (! surface->backend->start_page)
return CAIRO_STATUS_SUCCESS;
return (surface->backend->start_page) (surface->target);
}
static cairo_int_status_t
_cairo_paginated_surface_copy_page (void *abstract_surface)
{
cairo_status_t status;
cairo_paginated_surface_t *surface = abstract_surface;
status = _start_page (surface);
if (status)
return status;
_paint_page (surface);
/* XXX: It might make sense to add some suport here for calling
@ -257,8 +278,13 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface)
{
cairo_status_t status;
cairo_paginated_surface_t *surface = abstract_surface;
status = _start_page (surface);
if (status)
return status;
_paint_page (surface);
_cairo_surface_show_page (surface->target);
@ -270,6 +296,8 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
if (cairo_surface_status (surface->meta))
return cairo_surface_status (surface->meta);
surface->page_is_blank = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@ -288,14 +316,23 @@ _cairo_paginated_surface_intersect_clip_path (void *abstract_surface,
}
static cairo_int_status_t
_cairo_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->target, rectangle);
}
static void
_cairo_paginated_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_get_font_options (surface->target, options);
}
static cairo_int_status_t
_cairo_paginated_surface_paint (void *abstract_surface,
cairo_operator_t op,
@ -303,6 +340,12 @@ _cairo_paginated_surface_paint (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
/* Optimize away erasing of nothing. */
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
return CAIRO_STATUS_SUCCESS;
surface->page_is_blank = FALSE;
return _cairo_surface_paint (surface->meta, op, source);
}
@ -330,6 +373,12 @@ _cairo_paginated_surface_stroke (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
/* Optimize away erasing of nothing. */
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
return CAIRO_STATUS_SUCCESS;
surface->page_is_blank = FALSE;
return _cairo_surface_stroke (surface->meta, op, source,
path, style,
ctm, ctm_inverse,
@ -347,6 +396,12 @@ _cairo_paginated_surface_fill (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
/* Optimize away erasing of nothing. */
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
return CAIRO_STATUS_SUCCESS;
surface->page_is_blank = FALSE;
return _cairo_surface_fill (surface->meta, op, source,
path, fill_rule,
tolerance, antialias);
@ -362,6 +417,12 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
/* Optimize away erasing of nothing. */
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
return CAIRO_STATUS_SUCCESS;
surface->page_is_blank = FALSE;
return _cairo_surface_show_glyphs (surface->meta, op, source,
glyphs, num_glyphs,
scaled_font);
@ -387,7 +448,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->target, &extents);
@ -404,7 +465,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
const cairo_surface_backend_t cairo_paginated_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
NULL, /* create_similar --- see note for _cairo_paginated_surface_create_similar */
_cairo_paginated_surface_create_similar,
_cairo_paginated_surface_finish,
_cairo_paginated_surface_acquire_source_image,
_cairo_paginated_surface_release_source_image,
@ -420,7 +481,7 @@ const cairo_surface_backend_t cairo_paginated_surface_backend = {
_cairo_paginated_surface_intersect_clip_path,
_cairo_paginated_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
_cairo_paginated_surface_get_font_options,
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */

View File

@ -47,7 +47,6 @@ typedef struct cairo_stroker {
cairo_pen_t pen;
cairo_bool_t has_current_point;
cairo_point_t current_point;
cairo_point_t first_point;
@ -116,7 +115,11 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
int i = 0;
offset = stroker->style->dash_offset;
while (offset >= stroker->style->dash[i]) {
/* We stop searching for a starting point as soon as the
offset reaches zero. Otherwise when an initial dash
segment shrinks to zero it will be skipped over. */
while (offset > 0.0 && offset >= stroker->style->dash[i]) {
offset -= stroker->style->dash[i];
on = 1-on;
if (++i == stroker->style->num_dashes)
@ -159,7 +162,6 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
stroke_style->line_width / 2.0,
tolerance, ctm);
stroker->has_current_point = FALSE;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
@ -548,11 +550,18 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stro
static cairo_status_t
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2,
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
cairo_slope_t *slope, cairo_stroke_face_t *start,
cairo_stroke_face_t *end)
{
cairo_status_t status;
cairo_polygon_t polygon;
cairo_slope_t slope;
_compute_face (p1, slope, stroker, start);
/* XXX: This could be optimized slightly by not calling
_compute_face again but rather translating the relevant
fields from start. */
_compute_face (p2, slope, stroker, end);
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
@ -561,14 +570,6 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
return CAIRO_STATUS_SUCCESS;
}
_cairo_slope_init (&slope, p1, p2);
_compute_face (p1, &slope, stroker, start);
/* XXX: This could be optimized slightly by not calling
_compute_face again but rather translating the relevant
fields from start. */
_compute_face (p2, &slope, stroker, end);
/* XXX: I should really check the return value of the
move_to/line_to functions here to catch out of memory
conditions. But since that would be ugly, I'd prefer to add a
@ -607,7 +608,6 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
stroker->first_point = *point;
stroker->current_point = *point;
stroker->has_current_point = 1;
stroker->has_first_face = 0;
stroker->has_current_face = 0;
@ -615,6 +615,16 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_stroker_move_to_dashed (void *closure, cairo_point_t *point)
{
/* reset the dash pattern for new sub paths */
cairo_stroker_t *stroker = closure;
_cairo_stroker_start_dash (stroker);
return _cairo_stroker_move_to (closure, point);
}
static cairo_status_t
_cairo_stroker_line_to (void *closure, cairo_point_t *point)
{
@ -623,9 +633,7 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
cairo_stroke_face_t start, end;
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
if (!stroker->has_current_point)
return _cairo_stroker_move_to (stroker, point);
cairo_slope_t slope;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
@ -634,8 +642,10 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
as possible. */
return CAIRO_STATUS_SUCCESS;
}
_cairo_slope_init (&slope, p1, p2);
status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &start, &end);
status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &slope, &start, &end);
if (status)
return status;
@ -673,10 +683,18 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
cairo_stroke_face_t sub_start, sub_end;
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
cairo_slope_t slope;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in cairo_stroker_add_sub_edge and in _compute_face). The
key behavior is that degenerate paths should draw as much
as possible. */
return CAIRO_STATUS_SUCCESS;
}
_cairo_slope_init (&slope, p1, p2);
if (!stroker->has_current_point)
return _cairo_stroker_move_to (stroker, point);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
@ -701,7 +719,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
* XXX simplify this case analysis
*/
if (stroker->dash_on) {
status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &sub_start, &sub_end);
status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
if (status)
return status;
if (!first) {
@ -914,14 +932,12 @@ _cairo_stroker_close_path (void *closure)
cairo_status_t status;
cairo_stroker_t *stroker = closure;
if (stroker->has_current_point) {
if (stroker->dashed)
status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
else
status = _cairo_stroker_line_to (stroker, &stroker->first_point);
if (status)
return status;
}
if (stroker->dashed)
status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
else
status = _cairo_stroker_line_to (stroker, &stroker->first_point);
if (status)
return status;
if (stroker->has_first_face && stroker->has_current_face) {
status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
@ -931,7 +947,6 @@ _cairo_stroker_close_path (void *closure)
stroker->has_first_face = 0;
stroker->has_current_face = 0;
stroker->has_current_point = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -954,7 +969,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
if (stroker.style->dash)
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_stroker_move_to,
_cairo_stroker_move_to_dashed,
_cairo_stroker_line_to_dashed,
_cairo_stroker_curve_to_dashed,
_cairo_stroker_close_path,

View File

@ -87,7 +87,7 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->current_point.x = 0;
path->current_point.y = 0;
path->has_current_point = 0;
path->has_current_point = FALSE;
path->last_move_point = path->current_point;
}
@ -163,7 +163,7 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
}
path->arg_buf_tail = NULL;
path->has_current_point = 0;
path->has_current_point = FALSE;
}
void
@ -189,12 +189,18 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
return status;
path->current_point = point;
path->has_current_point = 1;
path->has_current_point = TRUE;
path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
{
path->has_current_point = FALSE;
}
cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
@ -202,7 +208,7 @@ _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
{
cairo_fixed_t x, y;
if (!path->has_current_point)
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@ -222,12 +228,16 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
point.x = x;
point.y = y;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (! path->has_current_point)
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
else
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (status)
return status;
path->current_point = point;
path->has_current_point = 1;
path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@ -239,7 +249,7 @@ _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
{
cairo_fixed_t x, y;
if (!path->has_current_point)
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@ -261,12 +271,19 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
if (! path->has_current_point) {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
&point[0], 1);
if (status)
return status;
}
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
path->current_point = point[2];
path->has_current_point = 1;
path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@ -281,7 +298,7 @@ _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
if (!path->has_current_point)
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x0 = path->current_point.x + dx0;
@ -304,13 +321,16 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
{
cairo_status_t status;
if (! path->has_current_point)
return CAIRO_STATUS_SUCCESS;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
if (status)
return status;
path->current_point.x = path->last_move_point.x;
path->current_point.y = path->last_move_point.y;
path->has_current_point = 1;
path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}

View File

@ -1050,7 +1050,6 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_pattern_is_opaque_solid
*
@ -1063,7 +1062,7 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
* Return value: %TRUE if the pattern is an opaque, solid color.
**/
cairo_bool_t
_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern)
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
{
cairo_solid_pattern_t *solid;
@ -1075,6 +1074,47 @@ _cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern)
return CAIRO_ALPHA_IS_OPAQUE (solid->color.alpha);
}
static cairo_bool_t
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
{
int i;
for (i = 0; i < gradient->n_stops; i++)
if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha))
return FALSE;
return TRUE;
}
/**
* _cairo_pattern_is_opaque
*
* Convenience function to determine whether a pattern is an opaque
* pattern (of any type). The same caveats that apply to
* _cairo_pattern_is_opaque_solid apply here as well.
*
* Return value: %TRUE if the pattern is a opaque.
**/
cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
{
const cairo_pattern_union_t *pattern;
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_TYPE_SOLID:
return _cairo_pattern_is_opaque_solid (abstract_pattern);
case CAIRO_PATTERN_TYPE_SURFACE:
return _cairo_surface_is_opaque (pattern->surface.surface);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
return _gradient_is_opaque (&pattern->gradient.base);
}
ASSERT_NOT_REACHED;
return FALSE;
}
static cairo_int_status_t
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
cairo_surface_t *dst,
@ -1354,14 +1394,14 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
* with a little more work.
**/
cairo_status_t
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_t *extents)
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_fixed_t *extents)
{
if (pattern->extend == CAIRO_EXTEND_NONE &&
pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
{
cairo_status_t status;
cairo_rectangle_t surface_extents;
cairo_rectangle_fixed_t surface_extents;
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* 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 University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_PDF_TEST_H
#define CAIRO_PDF_TEST_H
#include <cairo.h>
#if CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
CAIRO_BEGIN_DECLS
struct _cairo_path_fixed;
struct _cairo_traps;
struct _cairo_trapezoid;
struct _cairo_clip;
void
cairo_pdf_test_force_fallbacks (void);
void
cairo_debug_dump_clip (struct _cairo_clip *clip,
FILE *fp);
void
cairo_debug_dump_path (struct _cairo_path_fixed *path,
FILE *fp);
void
cairo_debug_dump_traps (struct _cairo_traps *traps,
FILE *fp);
void
cairo_debug_dump_trapezoid_array (struct _cairo_trapezoid *traps,
int num_traps,
FILE *fp);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PDF_SURFACE */
#endif /* CAIRO_PDF_TEST_H */

View File

@ -59,6 +59,11 @@ cairo_pdf_surface_set_dpi (cairo_surface_t *surface,
double x_dpi,
double y_dpi);
void
cairo_pdf_surface_set_size (cairo_surface_t *surface,
double width_in_points,
double height_in_points);
CAIRO_END_DECLS
#else /* CAIRO_HAS_PDF_SURFACE */

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,21 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
double width_in_points,
double height_in_points);
cairo_public void
cairo_ps_surface_set_size (cairo_surface_t *surface,
double width_in_points,
double height_in_points);
cairo_public void
cairo_ps_surface_dsc_comment (cairo_surface_t *surface,
const char *comment);
cairo_public void
cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface);
cairo_public void
cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface);
cairo_public void
cairo_ps_surface_set_dpi (cairo_surface_t *surface,
double x_dpi,

View File

@ -44,15 +44,11 @@ typedef struct cairo_quartz_surface {
CGContextRef context;
cairo_bool_t flipped;
cairo_bool_t y_grows_down;
int width;
int height;
cairo_rectangle_fixed_t extents;
cairo_image_surface_t *image;
pixman_region16_t *clip_region;
CGImageRef cgImage;
pixman_region16_t *clip_region;
} cairo_quartz_surface_t;
cairo_bool_t

View File

@ -37,27 +37,13 @@
#include "cairo-private.h"
#include "cairo-quartz-private.h"
static void
ImageDataReleaseFunc(void *info, const void *data, size_t size)
{
if (data != NULL) {
free((void *) data);
}
}
static cairo_status_t
_cairo_quartz_surface_finish(void *abstract_surface)
{
cairo_quartz_surface_t *surface = abstract_surface;
if (surface->image)
cairo_surface_destroy(&surface->image->base);
if (surface->cgImage)
CGImageRelease(surface->cgImage);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
return CAIRO_STATUS_SUCCESS;
}
@ -67,117 +53,127 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
CGColorSpaceRef colorSpace;
void *imageData;
UInt32 imageDataSize, rowBytes;
CGDataProviderRef dataProvider;
cairo_quartz_surface_t *surface = abstract_surface;
/* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
* struct. If the window is ever drawn to without going through Cairo, then
* we would need to refetch the pixel data from the window into the cached
* image surface.
*/
if (surface->image) {
cairo_surface_reference(&surface->image->base);
if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
/* XXX: We can create an image out of the bitmap here */
}
*image_out = surface->image;
return CAIRO_STATUS_SUCCESS;
}
colorSpace = CGColorSpaceCreateDeviceRGB();
rowBytes = surface->width * 4;
imageDataSize = rowBytes * surface->height;
imageData = malloc(imageDataSize);
dataProvider =
CGDataProviderCreateWithData(NULL, imageData, imageDataSize,
ImageDataReleaseFunc);
surface->cgImage = CGImageCreate(surface->width,
surface->height,
8,
32,
rowBytes,
colorSpace,
kCGImageAlphaPremultipliedFirst,
dataProvider,
NULL,
false, kCGRenderingIntentDefault);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(dataProvider);
surface->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data(imageData,
CAIRO_FORMAT_ARGB32,
surface->width,
surface->height, rowBytes);
if (surface->image->base.status) {
if (surface->cgImage)
CGImageRelease(surface->cgImage);
return CAIRO_STATUS_NO_MEMORY;
}
*image_out = surface->image;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_status_t
_cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
cairo_rectangle_t * interest_rect,
cairo_image_surface_t **
image_out,
cairo_rectangle_t * image_rect,
void **image_extra)
_cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect,
void **image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
cairo_surface_t *image_surface;
unsigned char *data;
int x1, y1, x2, y2;
image_rect->x = 0;
image_rect->y = 0;
image_rect->width = surface->image->width;
image_rect->height = surface->image->height;
x1 = surface->extents.x;
x2 = surface->extents.x + surface->extents.width;
y1 = surface->extents.y;
y2 = surface->extents.y + surface->extents.height;
*image_out = surface->image;
if (image_extra)
if (interest_rect->x > x1)
x1 = interest_rect->x;
if (interest_rect->y > y1)
y1 = interest_rect->y;
if (interest_rect->x + interest_rect->width < x2)
x2 = interest_rect->x + interest_rect->width;
if (interest_rect->y + interest_rect->height < y2)
y2 = interest_rect->y + interest_rect->height;
if (x1 >= x2 || y1 >= y2) {
*image_out = NULL;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
image_rect->x = x1;
image_rect->y = y1;
image_rect->width = x2 - x1;
image_rect->height = y2 - y1;
data = calloc (image_rect->width * image_rect->height * 4, 1);
image_surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
image_rect->width,
image_rect->height,
image_rect->width * 4);
*image_out = (cairo_image_surface_t *)image_surface;
*image_extra = data;
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static CGImageRef
create_image_from_surface (cairo_image_surface_t *image_surface, void *data)
{
CGImageRef image;
CGColorSpaceRef color_space;
CGDataProviderRef data_provider;
int width, height;
width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface);
height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface);
color_space = CGColorSpaceCreateDeviceRGB();
data_provider = CGDataProviderCreateWithData (NULL, data,
width * height * 4, NULL);
image = CGImageCreate (width, height,
8, 32,
width * 4,
color_space,
kCGImageAlphaPremultipliedFirst,
data_provider,
NULL,
FALSE, kCGRenderingIntentDefault);
CGColorSpaceRelease (color_space);
CGDataProviderRelease (data_provider);
return image;
}
static void
_cairo_quartz_surface_release_dest_image(void *abstract_surface,
cairo_rectangle_t *
intersect_rect,
cairo_image_surface_t * image,
cairo_rectangle_t * image_rect,
void *image_extra)
_cairo_quartz_surface_release_dest_image(void *abstract_surface,
cairo_rectangle_fixed_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
CGImageRef image_ref;
CGRect rect;
image_ref = create_image_from_surface (image, image_extra);
if (surface->image == image) {
CGRect rect;
rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height);
rect = CGRectMake(0, 0, surface->width, surface->height);
if (surface->flipped) {
CGContextSaveGState (surface->context);
CGContextTranslateCTM (surface->context, 0, surface->height);
CGContextScaleCTM (surface->context, 1, -1);
}
CGContextDrawImage(surface->context, rect, surface->cgImage);
if (surface->flipped)
CGContextRestoreGState (surface->context);
memset(surface->image->data, 0, surface->width * surface->height * 4);
if (surface->y_grows_down) {
CGContextSaveGState (surface->context);
CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y);
CGContextScaleCTM (surface->context, 1, -1);
}
CGContextDrawImage(surface->context, rect, image_ref);
CFRelease (image_ref);
if (surface->y_grows_down) {
CGContextRestoreGState (surface->context);
}
cairo_surface_destroy ((cairo_surface_t *)image);
free (image_extra);
}
static cairo_int_status_t
@ -185,33 +181,26 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface,
pixman_region16_t * region)
{
cairo_quartz_surface_t *surface = abstract_surface;
unsigned int serial;
serial = _cairo_surface_allocate_clip_serial (&surface->image->base);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (region) {
surface->clip_region = pixman_region_create ();
pixman_region_copy (surface->clip_region, region);
} else
surface->clip_region = NULL;
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (region) {
surface->clip_region = pixman_region_create ();
pixman_region_copy (surface->clip_region, region);
} else
surface->clip_region = NULL;
return _cairo_surface_set_clip_region(&surface->image->base,
region, serial);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_t * rectangle)
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_quartz_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
*rectangle = surface->extents;
return CAIRO_STATUS_SUCCESS;
}
@ -238,10 +227,12 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
cairo_bool_t flipped,
int width, int height)
int width,
int height,
cairo_bool_t y_grows_down)
{
cairo_quartz_surface_t *surface;
CGRect clip_box;
surface = malloc(sizeof(cairo_quartz_surface_t));
if (surface == NULL) {
@ -249,19 +240,19 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend);
/* XXX: The content value here might be totally wrong. */
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
surface->context = context;
surface->width = width;
surface->height = height;
surface->image = NULL;
surface->cgImage = NULL;
surface->clip_region = NULL;
surface->flipped = flipped;
surface->clip_region = NULL;
surface->y_grows_down = y_grows_down;
/* Set up the image surface which Cairo draws into and we blit to & from. */
void *foo;
_cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo);
clip_box = CGContextGetClipBoundingBox (context);
surface->extents.x = clip_box.origin.x;
surface->extents.y = clip_box.origin.y;
surface->extents.width = clip_box.size.width;
surface->extents.height = clip_box.size.height;
return (cairo_surface_t *) surface;
}

View File

@ -47,9 +47,9 @@ CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_quartz_surface_create (CGContextRef context,
cairo_bool_t flipped,
int width,
int height);
int height,
cairo_bool_t y_grows_down);
CAIRO_END_DECLS

View File

@ -37,7 +37,7 @@
/**
* _cairo_region_create_from_rectangle:
* @rect: a #cairo_rectangle_t
* @rect: a #cairo_rectangle_fixed_t
*
* Creates a region with extents initialized from the given
* rectangle.
@ -46,7 +46,7 @@
* memory couldn't a allocated.
**/
pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_t *rect)
_cairo_region_create_from_rectangle (cairo_rectangle_fixed_t *rect)
{
/* We can't use pixman_region_create_simple(), because it doesn't
* have an error return
@ -67,11 +67,11 @@ _cairo_region_create_from_rectangle (cairo_rectangle_t *rect)
* @region: a #pixman_region16_t
* @rect: rectangle into which to store the extents
*
* Gets the bounding box of a region as a cairo_rectangle_t
* Gets the bounding box of a region as a cairo_rectangle_fixed_t
**/
void
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_t *rect)
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_fixed_t *rect)
{
pixman_box16_t *region_extents = pixman_region_extents (region);

View File

@ -1,228 +1,246 @@
#define cairo_append_path _moz_cairo_append_path
#define cairo_arc _moz_cairo_arc
#define cairo_arc_negative _moz_cairo_arc_negative
#define cairo_arc_to _moz_cairo_arc_to
#define cairo_atsui_font_face_create_for_atsu_font_id _moz_cairo_atsui_font_face_create_for_atsu_font_id
#define cairo_beos_surface_create _moz_cairo_beos_surface_create
#define cairo_beos_surface_create_for_bitmap _moz_cairo_beos_surface_create_for_bitmap
#define cairo_debug_reset_static_data _moz_cairo_debug_reset_static_data
#define cairo_clip _moz_cairo_clip
#define cairo_clip_preserve _moz_cairo_clip_preserve
#define cairo_close_path _moz_cairo_close_path
#define cairo_copy_page _moz_cairo_copy_page
#define cairo_copy_path _moz_cairo_copy_path
#define cairo_copy_path_flat _moz_cairo_copy_path_flat
#define cairo_create _moz_cairo_create
#define cairo_curve_to _moz_cairo_curve_to
#define cairo_debug_dump_clip _moz_cairo_debug_dump_clip
#define cairo_debug_dump_path _moz_cairo_debug_dump_path
#define cairo_debug_dump_traps _moz_cairo_debug_dump_traps
#define cairo_debug_dump_trapezoid_array _moz_cairo_debug_dump_trapezoid_array
#define cairo_debug_dump_traps _moz_cairo_debug_dump_traps
#define cairo_debug_reset_static_data _moz_cairo_debug_reset_static_data
#define cairo_debug_reset_static_data _moz_cairo_debug_reset_static_data
#define cairo_destroy _moz_cairo_destroy
#define cairo_device_to_user _moz_cairo_device_to_user
#define cairo_device_to_user_distance _moz_cairo_device_to_user_distance
#define cairo_extract_clip_rectangles _moz_cairo_extract_clip_rectangles
#define cairo_fill _moz_cairo_fill
#define cairo_fill_extents _moz_cairo_fill_extents
#define cairo_fill_preserve _moz_cairo_fill_preserve
#define cairo_font_extents _moz_cairo_font_extents
#define cairo_font_face_destroy _moz_cairo_font_face_destroy
#define cairo_font_face_get_type _moz_cairo_font_face_get_type
#define cairo_font_face_get_user_data _moz_cairo_font_face_get_user_data
#define cairo_font_face_reference _moz_cairo_font_face_reference
#define cairo_font_face_set_user_data _moz_cairo_font_face_set_user_data
#define cairo_font_face_status _moz_cairo_font_face_status
#define cairo_font_options_copy _moz_cairo_font_options_copy
#define cairo_font_options_create _moz_cairo_font_options_create
#define cairo_font_options_destroy _moz_cairo_font_options_destroy
#define cairo_font_options_equal _moz_cairo_font_options_equal
#define cairo_font_options_get_antialias _moz_cairo_font_options_get_antialias
#define cairo_font_options_get_hint_metrics _moz_cairo_font_options_get_hint_metrics
#define cairo_font_options_get_hint_style _moz_cairo_font_options_get_hint_style
#define cairo_font_options_get_subpixel_order _moz_cairo_font_options_get_subpixel_order
#define cairo_font_options_hash _moz_cairo_font_options_hash
#define cairo_font_options_merge _moz_cairo_font_options_merge
#define cairo_font_options_set_antialias _moz_cairo_font_options_set_antialias
#define cairo_font_options_set_hint_metrics _moz_cairo_font_options_set_hint_metrics
#define cairo_font_options_set_hint_style _moz_cairo_font_options_set_hint_style
#define cairo_font_options_set_subpixel_order _moz_cairo_font_options_set_subpixel_order
#define cairo_font_options_status _moz_cairo_font_options_status
#define cairo_ft_font_face_create_for_ft_face _moz_cairo_ft_font_face_create_for_ft_face
#define cairo_ft_font_face_create_for_pattern _moz_cairo_ft_font_face_create_for_pattern
#define cairo_ft_font_options_substitute _moz_cairo_ft_font_options_substitute
#define cairo_ft_font_face_create_for_ft_face _moz_cairo_ft_font_face_create_for_ft_face
#define cairo_ft_scaled_font_lock_face _moz_cairo_ft_scaled_font_lock_face
#define cairo_ft_scaled_font_unlock_face _moz_cairo_ft_scaled_font_unlock_face
#define cairo_get_antialias _moz_cairo_get_antialias
#define cairo_get_current_point _moz_cairo_get_current_point
#define cairo_get_fill_rule _moz_cairo_get_fill_rule
#define cairo_get_font_face _moz_cairo_get_font_face
#define cairo_get_font_matrix _moz_cairo_get_font_matrix
#define cairo_get_font_options _moz_cairo_get_font_options
#define cairo_get_group_target _moz_cairo_get_group_target
#define cairo_get_line_cap _moz_cairo_get_line_cap
#define cairo_get_line_join _moz_cairo_get_line_join
#define cairo_get_line_width _moz_cairo_get_line_width
#define cairo_get_matrix _moz_cairo_get_matrix
#define cairo_get_miter_limit _moz_cairo_get_miter_limit
#define cairo_get_operator _moz_cairo_get_operator
#define cairo_get_source _moz_cairo_get_source
#define cairo_get_target _moz_cairo_get_target
#define cairo_get_tolerance _moz_cairo_get_tolerance
#define cairo_glitz_surface_create _moz_cairo_glitz_surface_create
#define cairo_glyph_extents _moz_cairo_glyph_extents
#define cairo_glyph_path _moz_cairo_glyph_path
#define cairo_has_clip _moz_cairo_has_clip
#define cairo_identity_matrix _moz_cairo_identity_matrix
#define cairo_image_surface_create _moz_cairo_image_surface_create
#define cairo_image_surface_create_for_data _moz_cairo_image_surface_create_for_data
#define cairo_image_surface_create_from_png _moz_cairo_image_surface_create_from_png
#define cairo_image_surface_create_from_png_stream _moz_cairo_image_surface_create_from_png_stream
#define cairo_image_surface_get_height _moz_cairo_image_surface_get_height
#define cairo_image_surface_get_width _moz_cairo_image_surface_get_width
#define cairo_in_fill _moz_cairo_in_fill
#define cairo_in_stroke _moz_cairo_in_stroke
#define cairo_line_to _moz_cairo_line_to
#define cairo_mask _moz_cairo_mask
#define cairo_mask_surface _moz_cairo_mask_surface
#define cairo_matrix_init _moz_cairo_matrix_init
#define cairo_matrix_init_identity _moz_cairo_matrix_init_identity
#define cairo_matrix_init_rotate _moz_cairo_matrix_init_rotate
#define cairo_matrix_init_scale _moz_cairo_matrix_init_scale
#define cairo_matrix_init_translate _moz_cairo_matrix_init_translate
#define cairo_matrix_invert _moz_cairo_matrix_invert
#define cairo_matrix_multiply _moz_cairo_matrix_multiply
#define cairo_matrix_rotate _moz_cairo_matrix_rotate
#define cairo_matrix_scale _moz_cairo_matrix_scale
#define cairo_matrix_transform_distance _moz_cairo_matrix_transform_distance
#define cairo_matrix_transform_point _moz_cairo_matrix_transform_point
#define cairo_matrix_translate _moz_cairo_matrix_translate
#define cairo_move_to _moz_cairo_move_to
#define cairo_new_path _moz_cairo_new_path
#define cairo_new_sub_path _moz_cairo_new_sub_path
#define cairo_paint _moz_cairo_paint
#define cairo_paint_with_alpha _moz_cairo_paint_with_alpha
#define cairo_path_destroy _moz_cairo_path_destroy
#define cairo_pattern_add_color_stop_rgb _moz_cairo_pattern_add_color_stop_rgb
#define cairo_pattern_add_color_stop_rgba _moz_cairo_pattern_add_color_stop_rgba
#define cairo_pattern_create_for_surface _moz_cairo_pattern_create_for_surface
#define cairo_pattern_create_linear _moz_cairo_pattern_create_linear
#define cairo_pattern_create_radial _moz_cairo_pattern_create_radial
#define cairo_pattern_create_rgb _moz_cairo_pattern_create_rgb
#define cairo_pattern_create_rgba _moz_cairo_pattern_create_rgba
#define cairo_pattern_destroy _moz_cairo_pattern_destroy
#define cairo_pattern_get_extend _moz_cairo_pattern_get_extend
#define cairo_pattern_get_filter _moz_cairo_pattern_get_filter
#define cairo_pattern_get_matrix _moz_cairo_pattern_get_matrix
#define cairo_pattern_get_type _moz_cairo_pattern_get_type
#define cairo_pattern_reference _moz_cairo_pattern_reference
#define cairo_pattern_set_extend _moz_cairo_pattern_set_extend
#define cairo_pattern_set_filter _moz_cairo_pattern_set_filter
#define cairo_pattern_set_matrix _moz_cairo_pattern_set_matrix
#define cairo_pattern_status _moz_cairo_pattern_status
#define cairo_pdf_surface_create _moz_cairo_pdf_surface_create
#define cairo_pdf_surface_create_for_stream _moz_cairo_pdf_surface_create_for_stream
#define cairo_pdf_surface_set_dpi _moz_cairo_pdf_surface_set_dpi
#define cairo_ps_surface_create _moz_cairo_ps_surface_create
#define cairo_ps_surface_create_for_stream _moz_cairo_ps_surface_create_for_stream
#define cairo_ps_surface_set_dpi _moz_cairo_ps_surface_set_dpi
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
#define cairo_win32_surface_create _moz_cairo_win32_surface_create
#define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib
#define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc
#define cairo_win32_font_face_create_for_logfontw _moz_cairo_win32_font_face_create_for_logfontw
#define cairo_win32_font_face_create_for_hfont _moz_cairo_win32_font_face_create_for_hfont
#define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font
#define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font
#define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor
#define cairo_xcb_surface_create_with_xrender_format _moz_cairo_xcb_surface_create_with_xrender_format
#define cairo_xcb_surface_create _moz_cairo_xcb_surface_create
#define cairo_xcb_surface_create_for_bitmap _moz_cairo_xcb_surface_create_for_bitmap
#define cairo_xcb_surface_set_size _moz_cairo_xcb_surface_set_size
#define cairo_test_xlib_disable_render _moz_cairo_test_xlib_disable_render
#define cairo_xlib_surface_create_with_xrender_format _moz_cairo_xlib_surface_create_with_xrender_format
#define cairo_xlib_surface_create _moz_cairo_xlib_surface_create
#define cairo_xlib_surface_create_for_bitmap _moz_cairo_xlib_surface_create_for_bitmap
#define cairo_xlib_surface_set_size _moz_cairo_xlib_surface_set_size
#define cairo_xlib_surface_set_drawable _moz_cairo_xlib_surface_set_drawable
#define cairo_xlib_surface_get_drawable _moz_cairo_xlib_surface_get_drawable
#define cairo_xlib_surface_get_display _moz_cairo_xlib_surface_get_display
#define cairo_xlib_surface_get_screen _moz_cairo_xlib_surface_get_screen
#define cairo_xlib_surface_get_visual _moz_cairo_xlib_surface_get_visual
#define cairo_xlib_surface_get_depth _moz_cairo_xlib_surface_get_depth
#define cairo_version _moz_cairo_version
#define cairo_version_string _moz_cairo_version_string
#define cairo_create _moz_cairo_create
#define cairo_reference _moz_cairo_reference
#define cairo_destroy _moz_cairo_destroy
#define cairo_save _moz_cairo_save
#define cairo_restore _moz_cairo_restore
#define cairo_push_group _moz_cairo_push_group
#define cairo_push_group_with_content _moz_cairo_push_group_with_content
#define cairo_pop_group _moz_cairo_pop_group
#define cairo_pop_group_to_source _moz_cairo_pop_group_to_source
#define cairo_profile_surface_create _moz_cairo_profile_surface_create
#define cairo_profile_surface_get_profile_data _moz_cairo_profile_surface_get_profile_data
#define cairo_ps_surface_create _moz_cairo_ps_surface_create
#define cairo_ps_surface_create_for_stream _moz_cairo_ps_surface_create_for_stream
#define cairo_ps_surface_dsc_begin_page_setup _moz_cairo_ps_surface_dsc_begin_page_setup
#define cairo_ps_surface_dsc_begin_setup _moz_cairo_ps_surface_dsc_begin_setup
#define cairo_ps_surface_dsc_comment _moz_cairo_ps_surface_dsc_comment
#define cairo_ps_surface_set_dpi _moz_cairo_ps_surface_set_dpi
#define cairo_ps_surface_set_size _moz_cairo_ps_surface_set_size
#define cairo_push_group _moz_cairo_push_group
#define cairo_push_group_with_content _moz_cairo_push_group_with_content
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
#define cairo_rectangle _moz_cairo_rectangle
#define cairo_reference _moz_cairo_reference
#define cairo_rel_curve_to _moz_cairo_rel_curve_to
#define cairo_rel_line_to _moz_cairo_rel_line_to
#define cairo_rel_move_to _moz_cairo_rel_move_to
#define cairo_reset_clip _moz_cairo_reset_clip
#define cairo_restore _moz_cairo_restore
#define cairo_rotate _moz_cairo_rotate
#define cairo_save _moz_cairo_save
#define cairo_scale _moz_cairo_scale
#define cairo_scaled_font_create _moz_cairo_scaled_font_create
#define cairo_scaled_font_destroy _moz_cairo_scaled_font_destroy
#define cairo_scaled_font_extents _moz_cairo_scaled_font_extents
#define cairo_scaled_font_get_ctm _moz_cairo_scaled_font_get_ctm
#define cairo_scaled_font_get_font_face _moz_cairo_scaled_font_get_font_face
#define cairo_scaled_font_get_font_matrix _moz_cairo_scaled_font_get_font_matrix
#define cairo_scaled_font_get_font_options _moz_cairo_scaled_font_get_font_options
#define cairo_scaled_font_get_type _moz_cairo_scaled_font_get_type
#define cairo_scaled_font_glyph_extents _moz_cairo_scaled_font_glyph_extents
#define cairo_scaled_font_reference _moz_cairo_scaled_font_reference
#define cairo_scaled_font_status _moz_cairo_scaled_font_status
#define cairo_scaled_font_text_extents _moz_cairo_scaled_font_text_extents
#define cairo_select_font_face _moz_cairo_select_font_face
#define cairo_set_antialias _moz_cairo_set_antialias
#define cairo_set_dash _moz_cairo_set_dash
#define cairo_set_fill_rule _moz_cairo_set_fill_rule
#define cairo_set_font_face _moz_cairo_set_font_face
#define cairo_set_font_matrix _moz_cairo_set_font_matrix
#define cairo_set_font_options _moz_cairo_set_font_options
#define cairo_set_font_size _moz_cairo_set_font_size
#define cairo_set_line_cap _moz_cairo_set_line_cap
#define cairo_set_line_join _moz_cairo_set_line_join
#define cairo_set_line_width _moz_cairo_set_line_width
#define cairo_set_matrix _moz_cairo_set_matrix
#define cairo_set_miter_limit _moz_cairo_set_miter_limit
#define cairo_set_operator _moz_cairo_set_operator
#define cairo_set_scaled_font _moz_cairo_set_scaled_font
#define cairo_set_source _moz_cairo_set_source
#define cairo_set_source_rgb _moz_cairo_set_source_rgb
#define cairo_set_source_rgba _moz_cairo_set_source_rgba
#define cairo_set_source_surface _moz_cairo_set_source_surface
#define cairo_set_tolerance _moz_cairo_set_tolerance
#define cairo_set_antialias _moz_cairo_set_antialias
#define cairo_set_fill_rule _moz_cairo_set_fill_rule
#define cairo_set_line_width _moz_cairo_set_line_width
#define cairo_set_line_cap _moz_cairo_set_line_cap
#define cairo_set_line_join _moz_cairo_set_line_join
#define cairo_set_dash _moz_cairo_set_dash
#define cairo_set_miter_limit _moz_cairo_set_miter_limit
#define cairo_translate _moz_cairo_translate
#define cairo_scale _moz_cairo_scale
#define cairo_rotate _moz_cairo_rotate
#define cairo_transform _moz_cairo_transform
#define cairo_set_matrix _moz_cairo_set_matrix
#define cairo_identity_matrix _moz_cairo_identity_matrix
#define cairo_user_to_device _moz_cairo_user_to_device
#define cairo_user_to_device_distance _moz_cairo_user_to_device_distance
#define cairo_device_to_user _moz_cairo_device_to_user
#define cairo_device_to_user_distance _moz_cairo_device_to_user_distance
#define cairo_new_path _moz_cairo_new_path
#define cairo_move_to _moz_cairo_move_to
#define cairo_line_to _moz_cairo_line_to
#define cairo_curve_to _moz_cairo_curve_to
#define cairo_arc _moz_cairo_arc
#define cairo_arc_negative _moz_cairo_arc_negative
#define cairo_arc_to _moz_cairo_arc_to
#define cairo_rel_move_to _moz_cairo_rel_move_to
#define cairo_rel_line_to _moz_cairo_rel_line_to
#define cairo_rel_curve_to _moz_cairo_rel_curve_to
#define cairo_rectangle _moz_cairo_rectangle
#define cairo_stroke_to_path _moz_cairo_stroke_to_path
#define cairo_close_path _moz_cairo_close_path
#define cairo_paint _moz_cairo_paint
#define cairo_paint_with_alpha _moz_cairo_paint_with_alpha
#define cairo_mask _moz_cairo_mask
#define cairo_mask_surface _moz_cairo_mask_surface
#define cairo_stroke _moz_cairo_stroke
#define cairo_stroke_preserve _moz_cairo_stroke_preserve
#define cairo_fill _moz_cairo_fill
#define cairo_fill_preserve _moz_cairo_fill_preserve
#define cairo_copy_page _moz_cairo_copy_page
#define cairo_show_page _moz_cairo_show_page
#define cairo_in_stroke _moz_cairo_in_stroke
#define cairo_in_fill _moz_cairo_in_fill
#define cairo_stroke_extents _moz_cairo_stroke_extents
#define cairo_fill_extents _moz_cairo_fill_extents
#define cairo_reset_clip _moz_cairo_reset_clip
#define cairo_clip _moz_cairo_clip
#define cairo_clip_preserve _moz_cairo_clip_preserve
#define cairo_font_options_create _moz_cairo_font_options_create
#define cairo_font_options_copy _moz_cairo_font_options_copy
#define cairo_font_options_destroy _moz_cairo_font_options_destroy
#define cairo_font_options_status _moz_cairo_font_options_status
#define cairo_font_options_merge _moz_cairo_font_options_merge
#define cairo_font_options_equal _moz_cairo_font_options_equal
#define cairo_font_options_hash _moz_cairo_font_options_hash
#define cairo_font_options_set_antialias _moz_cairo_font_options_set_antialias
#define cairo_font_options_get_antialias _moz_cairo_font_options_get_antialias
#define cairo_font_options_set_subpixel_order _moz_cairo_font_options_set_subpixel_order
#define cairo_font_options_get_subpixel_order _moz_cairo_font_options_get_subpixel_order
#define cairo_font_options_set_hint_style _moz_cairo_font_options_set_hint_style
#define cairo_font_options_get_hint_style _moz_cairo_font_options_get_hint_style
#define cairo_font_options_set_hint_metrics _moz_cairo_font_options_set_hint_metrics
#define cairo_font_options_get_hint_metrics _moz_cairo_font_options_get_hint_metrics
#define cairo_select_font_face _moz_cairo_select_font_face
#define cairo_set_font_size _moz_cairo_set_font_size
#define cairo_set_font_matrix _moz_cairo_set_font_matrix
#define cairo_get_font_matrix _moz_cairo_get_font_matrix
#define cairo_set_font_options _moz_cairo_set_font_options
#define cairo_get_font_options _moz_cairo_get_font_options
#define cairo_show_text _moz_cairo_show_text
#define cairo_show_glyphs _moz_cairo_show_glyphs
#define cairo_get_font_face _moz_cairo_get_font_face
#define cairo_font_extents _moz_cairo_font_extents
#define cairo_set_font_face _moz_cairo_set_font_face
#define cairo_text_extents _moz_cairo_text_extents
#define cairo_glyph_extents _moz_cairo_glyph_extents
#define cairo_text_path _moz_cairo_text_path
#define cairo_glyph_path _moz_cairo_glyph_path
#define cairo_font_face_reference _moz_cairo_font_face_reference
#define cairo_font_face_destroy _moz_cairo_font_face_destroy
#define cairo_font_face_status _moz_cairo_font_face_status
#define cairo_font_face_get_type _moz_cairo_font_face_get_type
#define cairo_font_face_get_user_data _moz_cairo_font_face_get_user_data
#define cairo_font_face_set_user_data _moz_cairo_font_face_set_user_data
#define cairo_scaled_font_create _moz_cairo_scaled_font_create
#define cairo_scaled_font_reference _moz_cairo_scaled_font_reference
#define cairo_scaled_font_destroy _moz_cairo_scaled_font_destroy
#define cairo_scaled_font_status _moz_cairo_scaled_font_status
#define cairo_scaled_font_get_type _moz_cairo_scaled_font_get_type
#define cairo_scaled_font_extents _moz_cairo_scaled_font_extents
#define cairo_scaled_font_text_extents _moz_cairo_scaled_font_text_extents
#define cairo_scaled_font_glyph_extents _moz_cairo_scaled_font_glyph_extents
#define cairo_scaled_font_get_font_face _moz_cairo_scaled_font_get_font_face
#define cairo_scaled_font_get_font_matrix _moz_cairo_scaled_font_get_font_matrix
#define cairo_scaled_font_get_ctm _moz_cairo_scaled_font_get_ctm
#define cairo_scaled_font_get_font_options _moz_cairo_scaled_font_get_font_options
#define cairo_get_operator _moz_cairo_get_operator
#define cairo_get_source _moz_cairo_get_source
#define cairo_get_tolerance _moz_cairo_get_tolerance
#define cairo_get_antialias _moz_cairo_get_antialias
#define cairo_get_current_point _moz_cairo_get_current_point
#define cairo_get_fill_rule _moz_cairo_get_fill_rule
#define cairo_get_line_width _moz_cairo_get_line_width
#define cairo_get_line_cap _moz_cairo_get_line_cap
#define cairo_get_line_join _moz_cairo_get_line_join
#define cairo_get_miter_limit _moz_cairo_get_miter_limit
#define cairo_get_matrix _moz_cairo_get_matrix
#define cairo_get_target _moz_cairo_get_target
#define cairo_get_group_target _moz_cairo_get_group_target
#define cairo_copy_path _moz_cairo_copy_path
#define cairo_copy_path_flat _moz_cairo_copy_path_flat
#define cairo_append_path _moz_cairo_append_path
#define cairo_path_destroy _moz_cairo_path_destroy
#define cairo_has_clip _moz_cairo_has_clip
#define cairo_extract_clip_rectangles _moz_cairo_extract_clip_rectangles
#define cairo_show_page _moz_cairo_show_page
#define cairo_show_text _moz_cairo_show_text
#define cairo_status _moz_cairo_status
#define cairo_status_to_string _moz_cairo_status_to_string
#define cairo_stroke _moz_cairo_stroke
#define cairo_stroke_extents _moz_cairo_stroke_extents
#define cairo_stroke_preserve _moz_cairo_stroke_preserve
#define cairo_stroke_to_path _moz_cairo_stroke_to_path
#define cairo_surface_create_similar _moz_cairo_surface_create_similar
#define cairo_surface_reference _moz_cairo_surface_reference
#define cairo_surface_finish _moz_cairo_surface_finish
#define cairo_surface_destroy _moz_cairo_surface_destroy
#define cairo_surface_status _moz_cairo_surface_status
#define cairo_surface_get_type _moz_cairo_surface_get_type
#define cairo_surface_write_to_png _moz_cairo_surface_write_to_png
#define cairo_surface_write_to_png_stream _moz_cairo_surface_write_to_png_stream
#define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
#define cairo_surface_set_user_data _moz_cairo_surface_set_user_data
#define cairo_surface_get_font_options _moz_cairo_surface_get_font_options
#define cairo_surface_finish _moz_cairo_surface_finish
#define cairo_surface_flush _moz_cairo_surface_flush
#define cairo_surface_get_content _moz_cairo_surface_get_content
#define cairo_surface_get_device_offset _moz_cairo_surface_get_device_offset
#define cairo_surface_get_font_options _moz_cairo_surface_get_font_options
#define cairo_surface_get_type _moz_cairo_surface_get_type
#define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
#define cairo_surface_is_profile _moz_cairo_surface_is_profile
#define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
#define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle
#define cairo_surface_reference _moz_cairo_surface_reference
#define cairo_surface_set_device_offset _moz_cairo_surface_set_device_offset
#define cairo_surface_get_device_offset _moz_cairo_surface_get_device_offset
#define cairo_image_surface_create _moz_cairo_image_surface_create
#define cairo_image_surface_create_for_data _moz_cairo_image_surface_create_for_data
#define cairo_image_surface_get_width _moz_cairo_image_surface_get_width
#define cairo_image_surface_get_height _moz_cairo_image_surface_get_height
#define cairo_image_surface_create_from_png _moz_cairo_image_surface_create_from_png
#define cairo_image_surface_create_from_png_stream _moz_cairo_image_surface_create_from_png_stream
#define cairo_pattern_create_rgb _moz_cairo_pattern_create_rgb
#define cairo_pattern_create_rgba _moz_cairo_pattern_create_rgba
#define cairo_pattern_create_for_surface _moz_cairo_pattern_create_for_surface
#define cairo_pattern_create_linear _moz_cairo_pattern_create_linear
#define cairo_pattern_create_radial _moz_cairo_pattern_create_radial
#define cairo_pattern_reference _moz_cairo_pattern_reference
#define cairo_pattern_destroy _moz_cairo_pattern_destroy
#define cairo_pattern_status _moz_cairo_pattern_status
#define cairo_pattern_get_type _moz_cairo_pattern_get_type
#define cairo_pattern_add_color_stop_rgb _moz_cairo_pattern_add_color_stop_rgb
#define cairo_pattern_add_color_stop_rgba _moz_cairo_pattern_add_color_stop_rgba
#define cairo_pattern_set_matrix _moz_cairo_pattern_set_matrix
#define cairo_pattern_get_matrix _moz_cairo_pattern_get_matrix
#define cairo_pattern_set_extend _moz_cairo_pattern_set_extend
#define cairo_pattern_get_extend _moz_cairo_pattern_get_extend
#define cairo_pattern_set_filter _moz_cairo_pattern_set_filter
#define cairo_pattern_get_filter _moz_cairo_pattern_get_filter
#define cairo_matrix_init _moz_cairo_matrix_init
#define cairo_matrix_init_identity _moz_cairo_matrix_init_identity
#define cairo_matrix_init_translate _moz_cairo_matrix_init_translate
#define cairo_matrix_init_scale _moz_cairo_matrix_init_scale
#define cairo_matrix_init_rotate _moz_cairo_matrix_init_rotate
#define cairo_matrix_translate _moz_cairo_matrix_translate
#define cairo_matrix_scale _moz_cairo_matrix_scale
#define cairo_matrix_rotate _moz_cairo_matrix_rotate
#define cairo_matrix_invert _moz_cairo_matrix_invert
#define cairo_matrix_multiply _moz_cairo_matrix_multiply
#define cairo_matrix_transform_distance _moz_cairo_matrix_transform_distance
#define cairo_matrix_transform_point _moz_cairo_matrix_transform_point
#define cairo_surface_set_user_data _moz_cairo_surface_set_user_data
#define cairo_surface_status _moz_cairo_surface_status
#define cairo_surface_write_to_png _moz_cairo_surface_write_to_png
#define cairo_surface_write_to_png_stream _moz_cairo_surface_write_to_png_stream
#define cairo_svg_get_versions _moz_cairo_svg_get_versions
#define cairo_svg_surface_create _moz_cairo_svg_surface_create
#define cairo_svg_surface_create_for_stream _moz_cairo_svg_surface_create_for_stream
#define cairo_svg_surface_restrict_to_version _moz_cairo_svg_surface_restrict_to_version
#define cairo_svg_surface_set_dpi _moz_cairo_svg_surface_set_dpi
#define cairo_svg_version_to_string _moz_cairo_svg_version_to_string
#define cairo_text_extents _moz_cairo_text_extents
#define cairo_text_path _moz_cairo_text_path
#define cairo_transform _moz_cairo_transform
#define cairo_translate _moz_cairo_translate
#define cairo_user_to_device _moz_cairo_user_to_device
#define cairo_user_to_device_distance _moz_cairo_user_to_device_distance
#define cairo_version _moz_cairo_version
#define cairo_version_string _moz_cairo_version_string
#define cairo_win32_font_face_create_for_hfont _moz_cairo_win32_font_face_create_for_hfont
#define cairo_win32_font_face_create_for_logfontw _moz_cairo_win32_font_face_create_for_logfontw
#define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font
#define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical
#define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device
#define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor
#define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font
#define cairo_win32_surface_create _moz_cairo_win32_surface_create
#define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib
#define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc
#define cairo_xcb_surface_create _moz_cairo_xcb_surface_create
#define cairo_xcb_surface_create_for_bitmap _moz_cairo_xcb_surface_create_for_bitmap
#define cairo_xcb_surface_create_with_xrender_format _moz_cairo_xcb_surface_create_with_xrender_format
#define cairo_xcb_surface_set_size _moz_cairo_xcb_surface_set_size
#define cairo_xlib_surface_create _moz_cairo_xlib_surface_create
#define cairo_xlib_surface_create_for_bitmap _moz_cairo_xlib_surface_create_for_bitmap
#define cairo_xlib_surface_create_with_xrender_format _moz_cairo_xlib_surface_create_with_xrender_format
#define cairo_xlib_surface_get_depth _moz_cairo_xlib_surface_get_depth
#define cairo_xlib_surface_get_display _moz_cairo_xlib_surface_get_display
#define cairo_xlib_surface_get_drawable _moz_cairo_xlib_surface_get_drawable
#define cairo_xlib_surface_get_screen _moz_cairo_xlib_surface_get_screen
#define cairo_xlib_surface_get_visual _moz_cairo_xlib_surface_get_visual
#define cairo_xlib_surface_set_drawable _moz_cairo_xlib_surface_set_drawable
#define cairo_xlib_surface_set_size _moz_cairo_xlib_surface_set_size

View File

@ -0,0 +1,182 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc
*
* 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 University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
#define CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
#include "cairoint.h"
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
typedef struct _cairo_scaled_font_subset {
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
unsigned int subset_id;
/* Index of glyphs array is subset_glyph_index.
* Value of glyphs array is scaled_font_glyph_index.
*/
unsigned long *glyphs;
int num_glyphs;
} cairo_scaled_font_subset_t;
/**
* _cairo_scaled_font_subsets_create:
* @max_glyphs_per_subset: the maximum number of glyphs that should
* appear in any subset. A value of 0 indicates that there is no limit
* to the number of glyphs per subset.
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create subsets of any number of cairo_scaled_font_t
* objects. This allows the (arbitrarily large and sparse) glyph
* indices of a cairo_scaled_font to be mapped to one or more font
* subsets with glyph indices packed into the range
* [0 .. max_glyphs_per_subset).
*
* Return value: a pointer to the newly creates font subsets. The
* caller owns this object and should call
* _cairo_scaled_font_subsets_destroy() when done with it.
**/
cairo_private cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create (int max_glyphs_per_subset);
/**
* _cairo_scaled_font_subsets_destroy:
* @font_subsets: a #cairo_scaled_font_subsets_t object to be destroyed
*
* Destroys @font_subsets and all resources associated with it.
**/
cairo_private void
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
/**
* _cairo_scaled_font_subsets_map_glyph:
* @font_subsets: a #cairo_scaled_font_subsets_t
* @scaled_font: the font of the glyph to be mapped
* @scaled_font_glyph_index: the index of the glyph to be mapped
* @font_id_ret: return value giving the font ID of the mapped glyph
* @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
* @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
*
* Map a glyph from a #cairo_scaled_font to a new index within a
* subset of that font. The mapping performed is from the tuple:
*
* (scaled_font, scaled_font_glyph_index)
*
* to the tuple:
*
* (font_id, subset_id, subset_glyph_index)
*
* This mapping is 1:1. If the input tuple has previously mapped, the
* the output tuple previously returned will be returned again.
*
* Otherwise, the return tuple will be constructed as follows:
*
* 1) There is a 1:1 correspondence between the input scaled_font
* value and the output font_id value. If no mapping has been
* previously performed with the scaled_font value then the
* smallest unused font_id value will be returned.
*
* 2) Within the set of output tuples of the same font_id value the
* smallest value of subset_id will be returned such that
* subset_glyph_index does not exceed max_glyphs_per_subset (as
* passed to _cairo_scaled_font_subsets_create()) and that the
* resulting tuple is unique.
*
* 3) The smallest value of subset_glyph_index is returned such that
* the resulting tuple is unique.
*
* The net result is that any #cairo_scaled_font_t will be represented
* by one or more font subsets. Each subset is effectively a tuple of
* (scaled_font, font_id, subset_id) and within each subset there
* exists a mapping of scaled_glyph_font_index to subset_glyph_index.
*
* This final description of a font subset is the same representation
* used by #cairo_scaled_font_subset_t as provided by
* _cairo_scaled_font_subsets_foreach.
*
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int *font_id_ret,
unsigned int *subset_id_ret,
unsigned int *subset_glyph_index_ret);
typedef void
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
void *closure);
/**
* _cairo_scaled_font_subsets_foreach:
* @font_subsets: a #cairo_scaled_font_subsets_t
* @font_subset_callback: a function to be called for each font subset
* @closure: closure data for the callback function
*
* Iterate over each unique font subset as created by calls to
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
* unique pairs of (font_id, subset_id) as returned by
* _cairo_scaled_font_subsets_map_glyph().
*
* For each subset, @font_subset_callback will be called and will be
* provided with both a #cairo_scaled_font_subset_t object containing
* all the glyphs in the subset as well as the value of @closure.
*
* The #cairo_scaled_font_subset_t object contains the scaled_font,
* the font_id, and the subset_id corresponding to all glyphs
* belonging to the subset. In addition, it contains an array providing
* a mapping between subset glyph indices and the original scaled font
* glyph indices.
*
* The index of the array corresponds to subset_glyph_index values
* returned by _cairo_scaled_font_subsets_map_glyph() while the
* values of the array correspond to the scaled_font_glyph_index
* values passed as input to the same function.
*
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure);
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */

View File

@ -0,0 +1,385 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2003 University of Southern California
* Copyright © 2005 Red Hat, Inc
* Copyright © 2006 Keith Packard
* Copyright © 2006 Red Hat, Inc
*
* 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 University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Kristian Høgsberg <krh@redhat.com>
* Keith Packard <keithp@keithp.com>
*/
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
struct _cairo_scaled_font_subsets {
int max_glyphs_per_subset_limit;
int max_glyphs_per_subset_used;
int num_sub_fonts;
cairo_hash_table_t *sub_fonts;
};
typedef struct _cairo_sub_font {
cairo_hash_entry_t base;
cairo_scaled_font_subsets_t *parent;
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
int current_subset;
int num_glyphs_in_current_subset;
int max_glyphs_per_subset;
cairo_hash_table_t *sub_font_glyphs;
} cairo_sub_font_t;
typedef struct _cairo_sub_font_glyph {
cairo_hash_entry_t base;
unsigned int subset_id;
unsigned int subset_glyph_index;
} cairo_sub_font_glyph_t;
typedef struct _cairo_sub_font_collection {
unsigned long *glyphs; /* scaled_font_glyph_index */
int glyphs_size;
int max_glyph;
int num_glyphs;
unsigned int subset_id;
cairo_scaled_font_subset_callback_func_t font_subset_callback;
void *font_subset_callback_closure;
} cairo_sub_font_collection_t;
static void
_cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t *sub_font_glyph,
unsigned long scaled_font_glyph_index)
{
sub_font_glyph->base.hash = scaled_font_glyph_index;
}
static cairo_bool_t
_cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
{
const cairo_sub_font_glyph_t *sub_font_glyph_a = key_a;
const cairo_sub_font_glyph_t *sub_font_glyph_b = key_b;
return sub_font_glyph_a->base.hash == sub_font_glyph_b->base.hash;
}
static cairo_sub_font_glyph_t *
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
unsigned int subset_id,
unsigned int subset_glyph_index)
{
cairo_sub_font_glyph_t *sub_font_glyph;
sub_font_glyph = malloc (sizeof (cairo_sub_font_glyph_t));
if (sub_font_glyph == NULL)
return NULL;
_cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
sub_font_glyph->subset_id = subset_id;
sub_font_glyph->subset_glyph_index = subset_glyph_index;
return sub_font_glyph;
}
static void
_cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph)
{
free (sub_font_glyph);
}
static void
_cairo_sub_font_glyph_pluck (void *entry, void *closure)
{
cairo_sub_font_glyph_t *sub_font_glyph = entry;
cairo_hash_table_t *sub_font_glyphs = closure;
_cairo_hash_table_remove (sub_font_glyphs, &sub_font_glyph->base);
_cairo_sub_font_glyph_destroy (sub_font_glyph);
}
static void
_cairo_sub_font_glyph_collect (void *entry, void *closure)
{
cairo_sub_font_glyph_t *sub_font_glyph = entry;
cairo_sub_font_collection_t *collection = closure;
unsigned long scaled_font_glyph_index;
unsigned int subset_glyph_index;
if (sub_font_glyph->subset_id != collection->subset_id)
return;
scaled_font_glyph_index = sub_font_glyph->base.hash;
subset_glyph_index = sub_font_glyph->subset_glyph_index;
/* Ensure we don't exceed the allocated bounds. */
assert (subset_glyph_index < collection->glyphs_size);
collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
if (subset_glyph_index > collection->max_glyph)
collection->max_glyph = subset_glyph_index;
collection->num_glyphs++;
}
static cairo_bool_t
_cairo_sub_fonts_equal (const void *key_a, const void *key_b)
{
const cairo_sub_font_t *sub_font_a = key_a;
const cairo_sub_font_t *sub_font_b = key_b;
return sub_font_a->scaled_font == sub_font_b->scaled_font;
}
static void
_cairo_sub_font_init_key (cairo_sub_font_t *sub_font,
cairo_scaled_font_t *scaled_font)
{
sub_font->base.hash = (unsigned long) scaled_font;
sub_font->scaled_font = scaled_font;
}
static cairo_sub_font_t *
_cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
cairo_scaled_font_t *scaled_font,
unsigned int font_id,
int max_glyphs_per_subset)
{
cairo_sub_font_t *sub_font;
sub_font = malloc (sizeof (cairo_sub_font_t));
if (sub_font == NULL)
return NULL;
_cairo_sub_font_init_key (sub_font, scaled_font);
sub_font->parent = parent;
sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
sub_font->font_id = font_id;
sub_font->current_subset = 0;
sub_font->num_glyphs_in_current_subset = 0;
sub_font->max_glyphs_per_subset = max_glyphs_per_subset;
sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal);
if (! sub_font->sub_font_glyphs) {
free (sub_font);
return NULL;
}
return sub_font;
}
static void
_cairo_sub_font_destroy (cairo_sub_font_t *sub_font)
{
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
_cairo_sub_font_glyph_pluck,
sub_font->sub_font_glyphs);
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
cairo_scaled_font_destroy (sub_font->scaled_font);
free (sub_font);
}
static void
_cairo_sub_font_pluck (void *entry, void *closure)
{
cairo_sub_font_t *sub_font = entry;
cairo_hash_table_t *sub_fonts = closure;
_cairo_hash_table_remove (sub_fonts, &sub_font->base);
_cairo_sub_font_destroy (sub_font);
}
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
(cairo_hash_entry_t **) &sub_font_glyph))
{
if (sub_font->max_glyphs_per_subset &&
sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
{
sub_font->current_subset++;
sub_font->num_glyphs_in_current_subset = 0;
}
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset++);
if (sub_font_glyph == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_subset_used)
sub_font->parent->max_glyphs_per_subset_used = sub_font->num_glyphs_in_current_subset;
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
if (status)
return status;
}
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_sub_font_collect (void *entry, void *closure)
{
cairo_sub_font_t *sub_font = entry;
cairo_sub_font_collection_t *collection = closure;
cairo_scaled_font_subset_t subset;
int i;
for (i = 0; i <= sub_font->current_subset; i++) {
collection->subset_id = i;
collection->num_glyphs = 0;
collection->max_glyph = 0;
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
_cairo_sub_font_glyph_collect, collection);
/* Ensure the resulting array has no uninitialized holes */
assert (collection->num_glyphs == collection->max_glyph + 1);
subset.scaled_font = sub_font->scaled_font;
subset.font_id = sub_font->font_id;
subset.subset_id = i;
subset.glyphs = collection->glyphs;
subset.num_glyphs = collection->num_glyphs;
(collection->font_subset_callback) (&subset,
collection->font_subset_callback_closure);
}
}
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
{
cairo_scaled_font_subsets_t *subsets;
subsets = malloc (sizeof (cairo_scaled_font_subsets_t));
if (subsets == NULL)
return NULL;
subsets->max_glyphs_per_subset_limit = max_glyphs_per_subset;
subsets->max_glyphs_per_subset_used = 0;
subsets->num_sub_fonts = 0;
subsets->sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
if (! subsets->sub_fonts) {
free (subsets);
return NULL;
}
return subsets;
}
void
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
{
_cairo_hash_table_foreach (subsets->sub_fonts, _cairo_sub_font_pluck, subsets->sub_fonts);
_cairo_hash_table_destroy (subsets->sub_fonts);
free (subsets);
}
cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int *font_id,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
{
cairo_sub_font_t key, *sub_font;
cairo_status_t status;
_cairo_sub_font_init_key (&key, scaled_font);
if (! _cairo_hash_table_lookup (subsets->sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
sub_font = _cairo_sub_font_create (subsets, scaled_font,
subsets->num_sub_fonts++,
subsets->max_glyphs_per_subset_limit);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_hash_table_insert (subsets->sub_fonts,
&sub_font->base);
if (status)
return status;
}
*font_id = sub_font->font_id;
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
}
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure)
{
cairo_sub_font_collection_t collection;
collection.glyphs_size = font_subsets->max_glyphs_per_subset_used;
collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
if (collection.glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
collection.font_subset_callback = font_subset_callback;
collection.font_subset_callback_closure = closure;
_cairo_hash_table_foreach (font_subsets->sub_fonts,
_cairo_sub_font_collect, &collection);
free (collection.glyphs);
return CAIRO_STATUS_SUCCESS;
}

View File

@ -1,4 +1,4 @@
/* $Id: cairo-scaled-font.c,v 1.8 2006-04-01 00:36:09 vladimir%pobox.com Exp $
/* $Id: cairo-scaled-font.c,v 1.9 2006-06-05 23:16:24 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
@ -39,10 +39,10 @@
#include "cairoint.h"
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b)
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
cairo_scaled_glyph_t *key_a = abstract_key_a;
cairo_scaled_glyph_t *key_b = abstract_key_b;
const cairo_scaled_glyph_t *key_a = abstract_key_a;
const cairo_scaled_glyph_t *key_b = abstract_key_b;
return (_cairo_scaled_glyph_index (key_a) ==
_cairo_scaled_glyph_index (key_b));
@ -180,7 +180,7 @@ static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
static int
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
static cairo_scaled_font_map_t *
_cairo_scaled_font_map_lock (void)
@ -298,10 +298,10 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
}
static cairo_bool_t
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
cairo_scaled_font_t *key_a = abstract_key_a;
cairo_scaled_font_t *key_b = abstract_key_b;
const cairo_scaled_font_t *key_a = abstract_key_a;
const cairo_scaled_font_t *key_b = abstract_key_b;
return (key_a->font_face == key_b->font_face &&
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
@ -782,10 +782,10 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
* Compute a device-space bounding box for the glyphs.
*/
cairo_status_t
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_rectangle_t *extents)
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_rectangle_fixed_t *extents)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
int i;
@ -920,11 +920,11 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
/* round glyph locations to the nearest pixel */
x = (int) floor (glyphs[i].x +
glyph_surface->base.device_x_offset +
0.5);
glyph_surface->base.device_x_offset +
0.5);
y = (int) floor (glyphs[i].y +
glyph_surface->base.device_y_offset +
0.5);
glyph_surface->base.device_y_offset +
0.5);
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
@ -1020,7 +1020,7 @@ _scaled_glyph_path_close_path (void *abstract_closure)
cairo_status_t
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path)
{
@ -1211,13 +1211,18 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
/* ask backend to initialize metrics and shape fields */
status = (*scaled_font->backend->
scaled_glyph_init) (scaled_font, scaled_glyph, info);
if (status)
if (status) {
_cairo_scaled_glyph_destroy (scaled_glyph);
goto CLEANUP;
}
/* on success, the cache takes ownership of the scaled_glyph */
status = _cairo_cache_insert (scaled_font->glyphs,
&scaled_glyph->cache_entry);
if (status)
if (status) {
_cairo_scaled_glyph_destroy (scaled_glyph);
goto CLEANUP;
}
}
/*
* Check and see if the glyph, as provided,
@ -1242,8 +1247,6 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
CLEANUP:
if (status) {
_cairo_scaled_font_set_error (scaled_font, status);
if (scaled_glyph)
_cairo_scaled_glyph_destroy (scaled_glyph);
*scaled_glyph_ret = NULL;
} else {
*scaled_glyph_ret = scaled_glyph;

View File

@ -96,10 +96,10 @@ _cairo_surface_fallback_composite (cairo_operator_t op,
unsigned int height);
cairo_private cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects);
cairo_private cairo_status_t

View File

@ -40,9 +40,9 @@
typedef struct {
cairo_surface_t *dst;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_image_surface_t *image;
cairo_rectangle_t image_rect;
cairo_rectangle_fixed_t image_rect;
void *image_extra;
} fallback_state_t;
@ -98,21 +98,21 @@ _fallback_fini (fallback_state_t *state)
state->image_extra);
}
typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents);
typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents);
static cairo_status_t
_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_t *extents)
_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_fixed_t *extents)
{
cairo_surface_t *mask;
cairo_status_t status;
@ -151,13 +151,13 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
* us to combine the clip with the mask
*/
static cairo_status_t
_clip_and_composite_with_mask (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_t *extents)
_clip_and_composite_with_mask (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_fixed_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -185,13 +185,13 @@ _clip_and_composite_with_mask (cairo_clip_t *clip,
* in two pieces and combine them together.
*/
static cairo_status_t
_clip_and_composite_combine (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_t *extents)
_clip_and_composite_combine (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_fixed_t *extents)
{
cairo_surface_t *intermediate;
cairo_surface_pattern_t dst_pattern;
@ -274,12 +274,12 @@ _clip_and_composite_combine (cairo_clip_t *clip,
* defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
*/
static cairo_status_t
_clip_and_composite_source (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_t *extents)
_clip_and_composite_source (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_fixed_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -320,7 +320,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
}
static int
_cairo_rectangle_empty (const cairo_rectangle_t *rect)
_cairo_rectangle_empty (const cairo_rectangle_fixed_t *rect)
{
return rect->width == 0 || rect->height == 0;
}
@ -347,13 +347,13 @@ _cairo_rectangle_empty (const cairo_rectangle_t *rect)
* Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
**/
static cairo_status_t
_clip_and_composite (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_t *extents)
_clip_and_composite (cairo_clip_t *clip,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_fixed_t *extents)
{
cairo_pattern_union_t solid_pattern;
cairo_status_t status;
@ -403,12 +403,12 @@ _clip_and_composite (cairo_clip_t *clip,
/* Composites a region representing a set of trapezoids.
*/
static cairo_status_t
_composite_trap_region (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_operator_t op,
cairo_surface_t *dst,
pixman_region16_t *trap_region,
cairo_rectangle_t *extents)
_composite_trap_region (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_operator_t op,
cairo_surface_t *dst,
pixman_region16_t *trap_region,
cairo_rectangle_fixed_t *extents)
{
cairo_status_t status;
cairo_pattern_union_t solid_pattern;
@ -451,6 +451,10 @@ _composite_trap_region (cairo_clip_t *clip,
extents->x, extents->y,
extents->width, extents->height);
/* Restore the original clip if we modified it temporarily. */
if (num_rects >1)
_cairo_surface_set_clip (dst, clip);
if (clip_surface)
_cairo_pattern_fini (&mask.base);
@ -466,13 +470,13 @@ typedef struct {
} cairo_composite_traps_info_t;
static cairo_status_t
_composite_traps_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents)
_composite_traps_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents)
{
cairo_composite_traps_info_t *info = closure;
cairo_pattern_union_t pattern;
@ -509,7 +513,7 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_status_t status;
pixman_region16_t *trap_region;
pixman_region16_t *clear_region = NULL;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
@ -652,7 +656,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_box_t box;
cairo_traps_t traps;
@ -661,7 +665,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_t source_extents;
cairo_rectangle_fixed_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
if (status)
return status;
@ -695,13 +699,13 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
}
static cairo_status_t
_cairo_surface_mask_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents)
_cairo_surface_mask_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents)
{
cairo_pattern_t *mask = closure;
@ -728,7 +732,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_rectangle_t extents, source_extents, mask_extents;
cairo_rectangle_fixed_t extents, source_extents, mask_extents;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
@ -844,13 +848,13 @@ typedef struct {
} cairo_show_glyphs_info_t;
static cairo_status_t
_cairo_surface_old_show_glyphs_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents)
_cairo_surface_old_show_glyphs_draw_func (void *closure,
cairo_operator_t op,
cairo_pattern_t *src,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_fixed_t *extents)
{
cairo_show_glyphs_info_t *glyph_info = closure;
cairo_pattern_union_t pattern;
@ -912,7 +916,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_rectangle_t extents, glyph_extents;
cairo_rectangle_fixed_t extents, glyph_extents;
cairo_show_glyphs_info_t glyph_info;
status = _cairo_surface_get_extents (surface, &extents);
@ -1035,14 +1039,14 @@ _cairo_surface_fallback_composite (cairo_operator_t op,
}
cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
fallback_state_t state;
cairo_rectangle_t *offset_rects = NULL;
cairo_rectangle_fixed_t *offset_rects = NULL;
cairo_status_t status;
int x1, y1, x2, y2;
int i;
@ -1082,7 +1086,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
/* If the fetched image isn't at 0,0, we need to offset the rectangles */
if (state.image_rect.x != 0 || state.image_rect.y != 0) {
offset_rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
offset_rects = malloc (sizeof (cairo_rectangle_fixed_t) * num_rects);
if (offset_rects == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto DONE;

View File

@ -43,6 +43,7 @@
const cairo_surface_t _cairo_surface_nil = {
&cairo_image_surface_backend, /* backend */
CAIRO_CONTENT_COLOR,
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
@ -60,6 +61,7 @@ const cairo_surface_t _cairo_surface_nil = {
const cairo_surface_t _cairo_surface_nil_file_not_found = {
&cairo_image_surface_backend, /* backend */
CAIRO_CONTENT_COLOR,
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
@ -77,6 +79,7 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = {
const cairo_surface_t _cairo_surface_nil_read_error = {
&cairo_image_surface_backend, /* backend */
CAIRO_CONTENT_COLOR,
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
@ -116,7 +119,7 @@ static void _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *
* breakpoint in _cairo_error() to generate a stack trace for when the
* user causes cairo to detect an error.
**/
static void
void
_cairo_surface_set_error (cairo_surface_t *surface,
cairo_status_t status)
{
@ -145,6 +148,20 @@ cairo_surface_get_type (cairo_surface_t *surface)
return surface->type;
}
/**
* cairo_surface_get_content:
* @surface: a #cairo_surface_t
*
* Return value: The content type of @surface which indicates whether
* the surface contains color and/or alpha information. See
* #cairo_content_t.
**/
cairo_content_t
cairo_surface_get_content (cairo_surface_t *surface)
{
return surface->content;
}
/**
* cairo_surface_status:
* @surface: a #cairo_surface_t
@ -165,9 +182,12 @@ cairo_surface_status (cairo_surface_t *surface)
void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend)
const cairo_surface_backend_t *backend,
cairo_content_t content)
{
surface->backend = backend;
surface->content = content;
surface->type = backend->type;
@ -268,7 +288,10 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
return (cairo_surface_t*) &_cairo_surface_nil;
}
status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE, source);
status = _cairo_surface_paint (surface,
color == CAIRO_COLOR_TRANSPARENT ?
CAIRO_OPERATOR_CLEAR :
CAIRO_OPERATOR_SOURCE, source);
cairo_pattern_destroy (source);
@ -587,8 +610,8 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
* sufficient to do this, since functions like
* cairo_device_to_user() will expose the hidden offset.
*
* Note that the offset only affects drawing to the surface, not using
* the surface in a surface pattern.
* Note that the offset affects drawing to the surface as well as
* using the surface in a source pattern.
**/
void
cairo_surface_set_device_offset (cairo_surface_t *surface,
@ -614,7 +637,7 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
* @surface: a #cairo_surface_t
* @x_offset: the offset in the X direction, in device units
* @y_offset: the offset in the Y direction, in device units
*
*
* Returns a previous device offset set by
* cairo_surface_set_device_offset().
*
@ -714,9 +737,9 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
**/
cairo_status_t
_cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void **image_extra)
{
assert (!surface->finished);
@ -739,11 +762,11 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
* resources that were allocated.
**/
void
_cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
assert (!surface->finished);
@ -915,7 +938,7 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height)
{
cairo_rectangle_t rect;
cairo_rectangle_fixed_t rect;
assert (! surface->is_snapshot);
@ -954,7 +977,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
{
int num_rects = pixman_region_num_rects (region);
pixman_box16_t *boxes = pixman_region_rects (region);
cairo_rectangle_t *rects;
cairo_rectangle_fixed_t *rects;
cairo_status_t status;
int i;
@ -1000,10 +1023,10 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
**/
cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
cairo_rectangle_fixed_t *rects,
int num_rects)
{
cairo_int_status_t status;
@ -1081,7 +1104,7 @@ _cairo_surface_mask (cairo_surface_t *surface,
FINISH:
_cairo_pattern_fini (&dev_source.base);
_cairo_pattern_fini (&dev_mask.base);
return status;
}
@ -1529,8 +1552,8 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
*/
cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle)
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_status_t status;
@ -1632,30 +1655,30 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (dst->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
if (dst->backend->old_show_glyphs)
if (dst->backend->old_show_glyphs) {
status = dst->backend->old_show_glyphs (scaled_font,
op, pattern, dst,
source_x, source_y,
dest_x, dest_y,
dest_x, dest_y,
width, height,
glyphs, num_glyphs);
else
} else
status = CAIRO_INT_STATUS_UNSUPPORTED;
return status;
}
static cairo_status_t
_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
cairo_rectangle_t *src_rectangle,
cairo_rectangle_t *mask_rectangle,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
cairo_rectangle_fixed_t *src_rectangle,
cairo_rectangle_fixed_t *mask_rectangle,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_rectangle_t dst_rectangle;
cairo_rectangle_t drawn_rectangle;
cairo_rectangle_fixed_t dst_rectangle;
cairo_rectangle_fixed_t drawn_rectangle;
pixman_region16_t *drawn_region;
pixman_region16_t *clear_region;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@ -1744,12 +1767,12 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_t src_tmp, mask_tmp;
cairo_rectangle_t *src_rectangle = NULL;
cairo_rectangle_t *mask_rectangle = NULL;
cairo_rectangle_fixed_t src_tmp, mask_tmp;
cairo_rectangle_fixed_t *src_rectangle = NULL;
cairo_rectangle_fixed_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
* non-repeating sources and masks. Other sources and masks can be ignored.
*/
@ -1819,12 +1842,12 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_t src_tmp, mask_tmp;
cairo_rectangle_t *src_rectangle = NULL;
cairo_rectangle_t *mask_rectangle = NULL;
cairo_rectangle_fixed_t src_tmp, mask_tmp;
cairo_rectangle_fixed_t *src_rectangle = NULL;
cairo_rectangle_fixed_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
* non-repeating sources and masks. Other sources and masks can be ignored.
*/
@ -1850,6 +1873,42 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
dst_x, dst_y, width, height);
}
static cairo_bool_t
_format_is_opaque (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32:
return FALSE;
case CAIRO_FORMAT_RGB24:
return TRUE;
case CAIRO_FORMAT_A8:
return FALSE;
case CAIRO_FORMAT_A1:
return TRUE;
}
return FALSE;
}
/* XXX: This function is funny in a couple of ways. First it seems to
* be computing something like "not translucent" rather than "opaque"
* since it returns TRUE for an A1 image surface. Second, it just
* gives up on anything other than an image surface.
*
* I imagine something that might be more useful here (or in addition)
* would be cairo_surface_get_content.
*/
cairo_bool_t
_cairo_surface_is_opaque (const cairo_surface_t *surface)
{
if (_cairo_surface_is_image (surface)) {
const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
return _format_is_opaque (image_surface->format);
}
return FALSE;
}
/**
* _cairo_surface_copy_pattern_for_destination
* @pattern: the pattern to copy

File diff suppressed because it is too large Load Diff

View File

@ -38,22 +38,39 @@
CAIRO_BEGIN_DECLS
cairo_surface_t *
typedef enum {
CAIRO_SVG_VERSION_1_1 = 0,
CAIRO_SVG_VERSION_1_2,
CAIRO_SVG_VERSION_LAST
} cairo_svg_version_t;
cairo_public cairo_surface_t *
cairo_svg_surface_create (const char *filename,
double width_in_points,
double height_in_points);
cairo_surface_t *
cairo_public cairo_surface_t *
cairo_svg_surface_create_for_stream (cairo_write_func_t write_func,
void *closure,
double width_in_points,
double height_in_points);
void
cairo_public void
cairo_svg_surface_set_dpi (cairo_surface_t *surface,
double x_dpi,
double y_dpi);
cairo_public void
cairo_svg_surface_restrict_to_version (cairo_surface_t *surface,
cairo_svg_version_t version);
cairo_public void
cairo_svg_get_versions (cairo_svg_version_t const **versions,
int *num_versions);
cairo_public const char *
cairo_svg_version_to_string (cairo_svg_version_t version);
CAIRO_END_DECLS
#else /* CAIRO_HAS_SVG_SURFACE */

View File

@ -39,6 +39,13 @@
#include <cairo-win32.h>
#include <cairoint.h>
#ifndef SHADEBLENDCAPS
#define SHADEBLENDCAPS 120
#endif
#ifndef SB_NONE
#define SB_NONE 0
#endif
#define WIN32_FONT_LOGICAL_SCALE 32
typedef struct _cairo_win32_surface {
@ -62,13 +69,31 @@ typedef struct _cairo_win32_surface {
cairo_surface_t *image;
cairo_rectangle_t clip_rect;
cairo_rectangle_fixed_t clip_rect;
HRGN saved_clip;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
/* Surface DC flags */
uint32_t flags;
} cairo_win32_surface_t;
/* Surface DC flag values */
enum {
/* Whether the DC is a display DC or not */
CAIRO_WIN32_SURFACE_FLAG_IS_DISPLAY = (1<<1),
/* Whether we can use BitBlt with this surface */
CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
/* Whether we can use AlphaBlend with this surface */
CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
/* Whether we can use StretchBlt with this surface */
CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4)
};
cairo_status_t
_cairo_win32_print_gdi_error (const char *context);

View File

@ -301,7 +301,8 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
surface->extents = surface->clip_rect;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
_cairo_content_from_format (format));
return (cairo_surface_t *)surface;
@ -448,9 +449,9 @@ _cairo_win32_surface_release_source_image (void *abstract_surf
static cairo_status_t
_cairo_win32_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void **image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -515,11 +516,11 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
}
static void
_cairo_win32_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_win32_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_win32_surface_t *local = image_extra;
@ -811,7 +812,7 @@ static cairo_int_status_t
_cairo_win32_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -963,8 +964,8 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -1184,7 +1185,8 @@ cairo_win32_surface_create (HDC hdc)
surface->extents = surface->clip_rect;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
_cairo_content_from_format (format));
return (cairo_surface_t *)surface;
}

View File

@ -66,6 +66,32 @@ format_from_visual(XCBConnection *c, XCBVISUALID visual)
return nil;
}
static cairo_content_t
_xcb_render_format_to_content (XCBRenderPICTFORMINFO *xrender_format)
{
cairo_bool_t xrender_format_has_alpha;
cairo_bool_t xrender_format_has_color;
/* This only happens when using a non-Render server. Let's punt
* and say there's no alpha here. */
if (xrender_format == NULL)
return CAIRO_CONTENT_COLOR;
xrender_format_has_alpha = (xrender_format->direct.alpha_mask != 0);
xrender_format_has_color = (xrender_format->direct.red_mask != 0 ||
xrender_format->direct.green_mask != 0 ||
xrender_format->direct.blue_mask != 0);
if (xrender_format_has_alpha)
if (xrender_format_has_color)
return CAIRO_CONTENT_COLOR_ALPHA;
else
return CAIRO_CONTENT_ALPHA;
else
return CAIRO_CONTENT_COLOR;
}
/* XXX: Why is this ridiculously complex compared to the equivalent
* function in cairo-xlib-surface.c */
static XCBRenderPICTFORMINFO
@ -287,8 +313,8 @@ _cairo_xcb_surface_finish (void *abstract_surface)
static int
_bits_per_pixel(XCBConnection *c, int depth)
{
XCBFORMAT *fmt = XCBConnSetupSuccessRepPixmapFormats(XCBGetSetup(c));
XCBFORMAT *fmtend = fmt + XCBConnSetupSuccessRepPixmapFormatsLength(XCBGetSetup(c));
XCBFORMAT *fmt = XCBSetupPixmapFormats(XCBGetSetup(c));
XCBFORMAT *fmtend = fmt + XCBSetupPixmapFormatsLength(XCBGetSetup(c));
for(; fmt != fmtend; ++fmt)
if(fmt->depth == depth)
@ -351,10 +377,10 @@ _CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
}
static cairo_status_t
_get_image_surface (cairo_xcb_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect)
_get_image_surface (cairo_xcb_surface_t *surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect)
{
cairo_image_surface_t *image;
XCBGetImageRep *imagerep;
@ -370,7 +396,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
y2 = surface->height;
if (interest_rect) {
cairo_rectangle_t rect;
cairo_rectangle_fixed_t rect;
rect.x = interest_rect->x;
rect.y = interest_rect->y;
@ -405,7 +431,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
{
XCBGenericError *error;
imagerep = XCBGetImageReply(surface->dpy,
XCBGetImage(surface->dpy, ZPixmap,
XCBGetImage(surface->dpy, XCBImageFormatZPixmap,
surface->drawable,
x1, y1,
x2 - x1, y2 - y1,
@ -444,7 +470,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
x1, y1, 0, 0, x2 - x1, y2 - y1);
imagerep = XCBGetImageReply(surface->dpy,
XCBGetImage(surface->dpy, ZPixmap,
XCBGetImage(surface->dpy, XCBImageFormatZPixmap,
drawable,
x1, y1,
x2 - x1, y2 - y1,
@ -558,7 +584,7 @@ _draw_image_surface (cairo_xcb_surface_t *surface,
_cairo_xcb_surface_ensure_gc (surface);
bpp = _bits_per_pixel(surface->dpy, image->depth);
data_len = _bytes_per_line(surface->dpy, image->width, bpp) * image->height;
XCBPutImage(surface->dpy, ZPixmap, surface->drawable, surface->gc,
XCBPutImage(surface->dpy, XCBImageFormatZPixmap, surface->drawable, surface->gc,
image->width,
image->height,
dst_x, dst_y,
@ -597,9 +623,9 @@ _cairo_xcb_surface_release_source_image (void *abstract_surfac
static cairo_status_t
_cairo_xcb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -618,9 +644,9 @@ _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
static void
_cairo_xcb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -914,11 +940,11 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_xcb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_xcb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t * color,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
cairo_xcb_surface_t *surface = abstract_surface;
XCBRenderCOLOR render_color;
@ -1010,8 +1036,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -1100,7 +1126,8 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &cairo_xcb_surface_backend);
_cairo_surface_init (&surface->base, &cairo_xcb_surface_backend,
_xcb_render_format_to_content (format));
surface->dpy = dpy;
@ -1130,7 +1157,7 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
/* This is ugly, but we have to walk over all visuals
* for the display to find the depth.
*/
roots = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(surface->dpy));
roots = XCBSetupRootsIter(XCBGetSetup(surface->dpy));
for(; roots.rem; XCBSCREENNext(&roots))
{
depths = XCBSCREENAllowedDepthsIter(roots.data);
@ -1291,9 +1318,10 @@ cairo_xcb_surface_set_size (cairo_surface_t *surface,
{
cairo_xcb_surface_t *xcb_surface = (cairo_xcb_surface_t *)surface;
/* XXX: How do we want to handle this error case? */
if (! _cairo_surface_is_xcb (surface))
if (! _cairo_surface_is_xcb (surface)) {
_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
xcb_surface->width = width;
xcb_surface->height = height;

View File

@ -125,7 +125,7 @@ struct _cairo_xlib_surface {
XRectangle *clip_rects;
int num_clip_rects;
XRenderPictFormat *format;
XRenderPictFormat *xrender_format;
};
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
@ -154,7 +154,7 @@ struct _cairo_xlib_surface {
static cairo_bool_t cairo_xlib_render_disabled = FALSE;
/**
* cairo_test_xlib_disable_render:
* cairo_xlib_test_disable_render:
*
* Disables the use of the RENDER extension.
*
@ -165,7 +165,7 @@ static cairo_bool_t cairo_xlib_render_disabled = FALSE;
* </note>
**/
void
cairo_test_xlib_disable_render (void)
cairo_xlib_test_disable_render (void)
{
cairo_xlib_render_disabled = TRUE;
}
@ -187,7 +187,7 @@ _CAIRO_FORMAT_DEPTH (cairo_format_t format)
}
static XRenderPictFormat *
_CAIRO_FORMAT_XRENDER_FORMAT(Display *dpy, cairo_format_t format)
_CAIRO_FORMAT_TO_XRENDER_FORMAT(Display *dpy, cairo_format_t format)
{
int pict_format;
switch (format) {
@ -215,11 +215,12 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
Pixmap pix;
cairo_xlib_surface_t *surface;
int depth = _CAIRO_FORMAT_DEPTH (format);
XRenderPictFormat *xrender_format = _CAIRO_FORMAT_XRENDER_FORMAT (dpy,
format);
XRenderPictFormat *xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy,
format);
/* As a good first approximation, if the display doesn't have COMPOSITE,
* we're better off using image surfaces for all temporary operations
/* As a good first approximation, if the display doesn't have even
* the most elementary RENDER operation, then we're better off
* using image surfaces for all temporary operations
*/
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) {
return cairo_image_surface_create (format, width, height);
@ -243,6 +244,31 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
return &surface->base;
}
static cairo_content_t
_xrender_format_to_content (XRenderPictFormat *xrender_format)
{
cairo_bool_t xrender_format_has_alpha;
cairo_bool_t xrender_format_has_color;
/* This only happens when using a non-Render server. Let's punt
* and say there's no alpha here. */
if (xrender_format == NULL)
return CAIRO_CONTENT_COLOR;
xrender_format_has_alpha = (xrender_format->direct.alpha != 0);
xrender_format_has_color = (xrender_format->direct.red != 0 ||
xrender_format->direct.green != 0 ||
xrender_format->direct.blue != 0);
if (xrender_format_has_alpha)
if (xrender_format_has_color)
return CAIRO_CONTENT_COLOR_ALPHA;
else
return CAIRO_CONTENT_ALPHA;
else
return CAIRO_CONTENT_COLOR;
}
static cairo_bool_t
_xrender_format_matches_content (XRenderPictFormat *format,
cairo_content_t content)
@ -486,10 +512,10 @@ _swap_ximage_to_native (XImage *ximage)
}
static cairo_status_t
_get_image_surface (cairo_xlib_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect)
_get_image_surface (cairo_xlib_surface_t *surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect)
{
cairo_image_surface_t *image;
XImage *ximage;
@ -503,7 +529,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
y2 = surface->height;
if (interest_rect) {
cairo_rectangle_t rect;
cairo_rectangle_fixed_t rect;
rect.x = interest_rect->x;
rect.y = interest_rect->y;
@ -604,12 +630,12 @@ _get_image_surface (cairo_xlib_surface_t *surface,
masks.red_mask = surface->visual->red_mask;
masks.green_mask = surface->visual->green_mask;
masks.blue_mask = surface->visual->blue_mask;
} else if (surface->format) {
} else if (surface->xrender_format) {
masks.bpp = ximage->bits_per_pixel;
masks.red_mask = (unsigned long)surface->format->direct.redMask << surface->format->direct.red;
masks.green_mask = (unsigned long)surface->format->direct.greenMask << surface->format->direct.green;
masks.blue_mask = (unsigned long)surface->format->direct.blueMask << surface->format->direct.blue;
masks.alpha_mask = (unsigned long)surface->format->direct.alphaMask << surface->format->direct.alpha;
masks.red_mask = (unsigned long)surface->xrender_format->direct.redMask << surface->xrender_format->direct.red;
masks.green_mask = (unsigned long)surface->xrender_format->direct.greenMask << surface->xrender_format->direct.green;
masks.blue_mask = (unsigned long)surface->xrender_format->direct.blueMask << surface->xrender_format->direct.blue;
masks.alpha_mask = (unsigned long)surface->xrender_format->direct.alphaMask << surface->xrender_format->direct.alpha;
} else {
masks.bpp = ximage->bits_per_pixel;
masks.red_mask = 0;
@ -673,7 +699,7 @@ _cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface)
if (!surface->src_picture)
surface->src_picture = XRenderCreatePicture (surface->dpy,
surface->drawable,
surface->format,
surface->xrender_format,
0, NULL);
}
@ -703,7 +729,7 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
if (!surface->dst_picture) {
surface->dst_picture = XRenderCreatePicture (surface->dpy,
surface->drawable,
surface->format,
surface->xrender_format,
0, NULL);
_cairo_xlib_surface_set_picture_clip_rects (surface);
}
@ -793,9 +819,9 @@ _cairo_xlib_surface_release_source_image (void *abstract_surfa
static cairo_status_t
_cairo_xlib_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
cairo_xlib_surface_t *surface = abstract_surface;
@ -813,11 +839,11 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
}
static void
_cairo_xlib_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
_cairo_xlib_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
cairo_xlib_surface_t *surface = abstract_surface;
@ -1023,7 +1049,7 @@ _surfaces_compatible (cairo_xlib_surface_t *dst,
return FALSE;
/* if Render is supported, match picture formats */
if (src->format != NULL && src->format == dst->format)
if (src->xrender_format != NULL && src->xrender_format == dst->xrender_format)
return TRUE;
/* Without Render, match visuals instead */
@ -1036,9 +1062,9 @@ _surfaces_compatible (cairo_xlib_surface_t *dst,
static cairo_bool_t
_surface_has_alpha (cairo_xlib_surface_t *surface)
{
if (surface->format) {
if (surface->format->type == PictTypeDirect &&
surface->format->direct.alphaMask != 0)
if (surface->xrender_format) {
if (surface->xrender_format->type == PictTypeDirect &&
surface->xrender_format->direct.alphaMask != 0)
return TRUE;
else
return FALSE;
@ -1381,11 +1407,11 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects)
{
cairo_xlib_surface_t *surface = abstract_surface;
XRenderColor render_color;
@ -1641,7 +1667,7 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
if (surface->gc)
XSetClipMask (surface->dpy, surface->gc, None);
if (surface->format && surface->dst_picture) {
if (surface->xrender_format && surface->dst_picture) {
XRenderPictureAttributes pa;
pa.clip_mask = None;
XRenderChangePicture (surface->dpy, surface->dst_picture,
@ -1685,8 +1711,8 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
}
static cairo_int_status_t
_cairo_xlib_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_xlib_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
cairo_xlib_surface_t *surface = abstract_surface;
@ -1708,6 +1734,14 @@ _cairo_xlib_surface_get_font_options (void *abstract_surface,
*options = surface->screen_info->font_options;
}
static cairo_status_t
_cairo_xlib_surface_flush (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
XSync (surface->dpy, False);
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
@ -1734,7 +1768,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_get_extents,
NULL, /* old_show_glyphs */
_cairo_xlib_surface_get_font_options,
NULL, /* flush */
_cairo_xlib_surface_flush,
NULL, /* mark_dirty_rectangle */
_cairo_xlib_surface_scaled_font_fini,
_cairo_xlib_surface_scaled_glyph_fini,
@ -1766,7 +1800,7 @@ _cairo_xlib_surface_create_internal (Display *dpy,
Drawable drawable,
Screen *screen,
Visual *visual,
XRenderPictFormat *format,
XRenderPictFormat *xrender_format,
int width,
int height,
int depth)
@ -1786,21 +1820,8 @@ _cairo_xlib_surface_create_internal (Display *dpy,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
surface->dpy = dpy;
surface->screen_info = screen_info;
surface->gc = NULL;
surface->drawable = drawable;
surface->screen = screen;
surface->owns_pixmap = FALSE;
surface->use_pixmap = 0;
surface->width = width;
surface->height = height;
if (format) {
depth = format->depth;
if (xrender_format) {
depth = xrender_format->depth;
} else if (visual) {
int j, k;
@ -1826,6 +1847,31 @@ _cairo_xlib_surface_create_internal (Display *dpy,
surface->render_minor = -1;
}
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
if (!xrender_format) {
if (visual)
xrender_format = XRenderFindVisualFormat (dpy, visual);
else if (depth == 1)
xrender_format = XRenderFindStandardFormat (dpy, PictStandardA1);
}
} else {
xrender_format = NULL;
}
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
_xrender_format_to_content (xrender_format));
surface->dpy = dpy;
surface->screen_info = screen_info;
surface->gc = NULL;
surface->drawable = drawable;
surface->screen = screen;
surface->owns_pixmap = FALSE;
surface->use_pixmap = 0;
surface->width = width;
surface->height = height;
surface->buggy_repeat = FALSE;
if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
if (VendorRelease (dpy) <= 60802000)
@ -1838,19 +1884,8 @@ _cairo_xlib_surface_create_internal (Display *dpy,
surface->dst_picture = None;
surface->src_picture = None;
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
if (!format) {
if (visual)
format = XRenderFindVisualFormat (dpy, visual);
else if (depth == 1)
format = XRenderFindStandardFormat (dpy, PictStandardA1);
}
} else {
format = NULL;
}
surface->visual = visual;
surface->format = format;
surface->xrender_format = xrender_format;
surface->depth = depth;
surface->have_clip_rects = FALSE;
@ -1994,18 +2029,20 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
* this function on a surface created for a Pixmap.
**/
void
cairo_xlib_surface_set_size (cairo_surface_t *surface,
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
int width,
int height)
{
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _cairo_surface_is_xlib (surface))
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
xlib_surface->width = width;
xlib_surface->height = height;
surface->width = width;
surface->height = height;
}
/**
* cairo_xlib_surface_set_drawable:
@ -2029,9 +2066,10 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _cairo_surface_is_xlib (abstract_surface))
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_surface_set_error (abstract_surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
/* XXX: and what about this case? */
if (surface->owns_pixmap)
@ -2053,44 +2091,41 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
surface->height = height;
}
static cairo_bool_t _is_valid_xlib_surface (cairo_surface_t *abstract_surface)
Display *
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
{
return _cairo_surface_is_xlib (abstract_surface) &&
abstract_surface->status == CAIRO_STATUS_SUCCESS;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
}
return surface->dpy;
}
Drawable
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _is_valid_xlib_surface (abstract_surface))
return 0;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return 0;
}
return surface->drawable;
}
Display *
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _is_valid_xlib_surface (abstract_surface))
return NULL;
return surface->dpy;
}
Screen *
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _is_valid_xlib_surface (abstract_surface))
return NULL;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
}
return surface->screen;
}
@ -2098,11 +2133,12 @@ cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
Visual *
cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _is_valid_xlib_surface (abstract_surface))
return NULL;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
}
return surface->visual;
}
@ -2110,11 +2146,12 @@ cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
int
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
/* XXX: How do we want to handle this error case? */
if (! _is_valid_xlib_surface (abstract_surface))
return -1;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return 0;
}
return surface->depth;
}
@ -2122,7 +2159,8 @@ cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
typedef struct _cairo_xlib_surface_font_private {
Display *dpy;
GlyphSet glyphset;
XRenderPictFormat *format;
cairo_format_t format;
XRenderPictFormat *xrender_format;
} cairo_xlib_surface_font_private_t;
static cairo_status_t
@ -2137,8 +2175,9 @@ _cairo_xlib_surface_font_init (Display *dpy,
return CAIRO_STATUS_NO_MEMORY;
font_private->dpy = dpy;
font_private->format = _CAIRO_FORMAT_XRENDER_FORMAT(dpy, format);
font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->format);
font_private->format = format;
font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format);
font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format);
scaled_font->surface_private = font_private;
scaled_font->surface_backend = &cairo_xlib_surface_backend;
return CAIRO_STATUS_SUCCESS;
@ -2185,7 +2224,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
XGlyphInfo glyph_info;
unsigned long glyph_index;
unsigned char *data;
cairo_status_t status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_xlib_surface_font_private_t *font_private;
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
@ -2197,6 +2236,32 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
}
font_private = scaled_font->surface_private;
/* If the glyph format does not match the font format, then we
* create a temporary surface for the glyph image with the font's
* format.
*/
if (glyph_surface->format != font_private->format) {
cairo_t *cr;
cairo_surface_t *tmp_surface;
tmp_surface = cairo_image_surface_create (font_private->format,
glyph_surface->width,
glyph_surface->height);
cr = cairo_create (tmp_surface);
cairo_set_source_surface (cr, &glyph_surface->base, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
status = cairo_status (cr);
cairo_destroy (cr);
glyph_surface = (cairo_image_surface_t *) tmp_surface;
if (status)
goto BAIL;
}
/*
* Most of the font rendering system thinks of glyph tiles as having
* an origin at (0,0) and an x and y bounding box "offset" which
@ -2252,8 +2317,10 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
unsigned char *new, *n;
new = malloc (c);
if (!new)
return CAIRO_STATUS_NO_MEMORY;
if (!new) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL;
}
n = new;
d = data;
while (c--)
@ -2276,8 +2343,10 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
unsigned char *new, *n;
new = malloc (c);
if (new == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (new == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL;
}
n = new;
d = data;
while ((c -= 4) >= 0)
@ -2309,7 +2378,11 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
if (data != glyph_surface->data)
free (data);
return CAIRO_STATUS_SUCCESS;
BAIL:
if (glyph_surface != scaled_glyph->surface)
cairo_surface_destroy (&glyph_surface->base);
return status;
}
#define N_STACK_BUF 1024
@ -2364,7 +2437,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_xlib_surface_t *dst,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->format,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
@ -2425,7 +2498,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo_xlib_surface_t *dst,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->format,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
@ -2486,7 +2559,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_xlib_surface_t *dst,
_render_operator (op),
src->src_picture,
dst->dst_picture,
font_private->format,
font_private->xrender_format,
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
elts[0].xOff, elts[0].yOff,
elts, num_glyphs);
@ -2528,7 +2601,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_pattern_union_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->format)
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Just let unbounded operators go through the fallback code
@ -2582,7 +2655,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
(cairo_surface_t **) &src,
&attributes);
} else {
cairo_rectangle_t glyph_extents;
cairo_rectangle_fixed_t glyph_extents;
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,

View File

@ -45,8 +45,8 @@
CAIRO_BEGIN_DECLS
cairo_public void
cairo_test_xlib_disable_render (void);
void
cairo_xlib_test_disable_render (void);
CAIRO_END_DECLS

View File

@ -70,12 +70,12 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *surface,
int width,
int height);
cairo_public Drawable
cairo_xlib_surface_get_drawable (cairo_surface_t *surface);
cairo_public Display *
cairo_xlib_surface_get_display (cairo_surface_t *surface);
cairo_public Drawable
cairo_xlib_surface_get_drawable (cairo_surface_t *surface);
cairo_public Screen *
cairo_xlib_surface_get_screen (cairo_surface_t *surface);
@ -83,7 +83,7 @@ cairo_public Visual *
cairo_xlib_surface_get_visual (cairo_surface_t *surface);
cairo_public int
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface);
cairo_xlib_surface_get_depth (cairo_surface_t *surface);
CAIRO_END_DECLS

View File

@ -62,7 +62,7 @@ static const cairo_t cairo_nil = {
* a bit of a pain, but it should be easy to always catch as long as
* one adds a new test case to test a trigger of the new status value.
*/
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DASH
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DSC_COMMENT
/**
* _cairo_error:
@ -82,6 +82,7 @@ static const cairo_t cairo_nil = {
void
_cairo_error (cairo_status_t status)
{
fprintf (stderr, "CAIRO ERROR: %d\n", status);
assert (status > CAIRO_STATUS_SUCCESS &&
status <= CAIRO_STATUS_LAST_STATUS);
}
@ -220,6 +221,9 @@ cairo_create (cairo_surface_t *target)
cairo_t *
cairo_reference (cairo_t *cr)
{
if (cr == NULL)
return NULL;
if (cr->ref_count == (unsigned int)-1)
return cr;
@ -241,6 +245,9 @@ cairo_reference (cairo_t *cr)
void
cairo_destroy (cairo_t *cr)
{
if (cr == NULL)
return;
if (cr->ref_count == (unsigned int)-1)
return;
@ -328,11 +335,44 @@ slim_hidden_def(cairo_restore);
* cairo_push_group:
* @cr: a cairo context
*
* Pushes a CAIRO_CONTENT_COLOR_ALPHA temporary surface onto
* the rendering stack, redirecting all rendering into it.
* See cairo_push_group_with_content().
* Temporarily redirects drawing to an intermediate surface known as a
* group. The redirection lasts until the group is completed by a call
* to cairo_pop_group() or cairo_pop_group_to_source(). These calls
* provide the result of any drawing to the group as a pattern,
* (either as an explicit object, or set as the source pattern).
*
* This group functionality can be convenient for performing
* intermediate compositing. One common use of a group is to render
* objects as opaque within the group, (so that they occlude each
* other), and then blend the result with translucence onto the
* destination.
*
* Groups can be nested arbitrarily deep by making balanced calls to
* cairo_push_group()/cairo_pop_group(). Each call pushes/pops the new
* target group onto/from a stack.
*
* The cairo_push_group() function calls cairo_save() so that any
* changes to the graphics state will not be visible outside the
* group, (the pop_group functions call cairo_restore()).
*
* By default the intermediate group will have a content type of
* CAIRO_CONTENT_COLOR_ALPHA. Other content types can be chosen for
* the group by using cairo_push_group_with_content() instead.
*
* As an example, here is how one might fill and stroke a path with
* translucence, but without any portion of the fill being visible
* under the stroke:
*
* <informalexample><programlisting>
* cairo_push_group (cr);
* cairo_set_source (cr, fill_pattern);
* cairo_fill_preserve (cr);
* cairo_set_source (cr, stroke_pattern);
* cairo_stroke (cr);
* cairo_pop_group_to_source (cr);
* cairo_paint_with_alpha (cr, alpha);
* </programlisting></informalexample>
*/
void
cairo_push_group (cairo_t *cr)
{
@ -346,22 +386,22 @@ slim_hidden_def(cairo_push_group);
* @content: a %cairo_content_t indicating the type of group that
* will be created
*
* Pushes a temporary surface onto the rendering stack, redirecting
* all rendering into it. The surface dimensions are the size of
* the current clipping bounding box. Initially, this surface
* is painted with CAIRO_OPERATOR_CLEAR.
* Temporarily redirects drawing to an intermediate surface known as a
* group. The redirection lasts until the group is completed by a call
* to cairo_pop_group() or cairo_pop_group_to_source(). These calls
* provide the result of any drawing to the group as a pattern,
* (either as an explicit object, or set as the source pattern).
*
* cairo_push_group() calls cairo_save() so that any changes to the
* graphics state will not be visible after cairo_pop_group() or
* cairo_pop_group_with_alpha(). See cairo_pop_group() and
* cairo_pop_group_with_alpha().
* The group will have a content type of @content. The ability to
* control this content type is the only distinction between this
* function and cairo_push_group() which you should see for a more
* detailed description of group rendering.
*/
void
cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
{
cairo_status_t status;
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_surface_t *group_surface = NULL;
/* Get the extents that we'll use in creating our new group surface */
@ -401,6 +441,26 @@ bail:
}
slim_hidden_def(cairo_push_group_with_content);
/**
* cairo_pop_group:
* @cr: a cairo context
*
* Terminates the redirection begun by a call to cairo_push_group() or
* cairo_push_group_with_content() and returns a new pattern
* containing the results of all drawing operations performed to the
* group.
*
* The cairo_pop_group() function calls cairo_restore(), (balancing a
* call to cairo_save() by the push_group function), so that any
* changes to the graphics state will not be visible outside the
* group.
*
* Return value: a newly created (surface) pattern containing the
* results of all drawing operations performed to the group. The
* caller owns the returned object and should call
* cairo_pattern_destroy() when finished with it.
**/
cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
@ -443,6 +503,31 @@ done:
}
slim_hidden_def(cairo_pop_group);
/**
* cairo_pop_group_t_source:
* @cr: a cairo context
*
* Terminates the redirection begun by a call to cairo_push_group() or
* cairo_push_group_with_content() and installs the resulting pattern
* as the source pattern in the given cairo context.
*
* The behavior of this function is equivalent to the sequence of
* operations:
*
* <informalexample><programlisting>
* cairo_pattern_t *group = cairo_pop_group (cr);
* cairo_set_source (cr, group);
* cairo_pattern_destroy (group);
* </programlisting></informalexample>
*
* but is more convenient as their is no need for a variable to store
* the short-lived pointer to the pattern.
*
* The cairo_pop_group() function calls cairo_restore(), (balancing a
* call to cairo_save() by the push_group function), so that any
* changes to the graphics state will not be visible outside the
* group.
**/
void
cairo_pop_group_to_source (cairo_t *cr)
{
@ -718,16 +803,28 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
/**
* cairo_set_line_width:
* @cr: a #cairo_t
* @width: a line width, as a user-space value
* @width: a line width
*
* Sets the current line width within the cairo context. The line
* width specifies the diameter of a pen that is circular in
* user-space.
* width value specifies the diameter of a pen that is circular in
* user space, (though device-space pen may be an ellipse in general
* due to scaling/shear/rotation of the CTM).
*
* As with the other stroke parameters, the current line cap style is
* Note: When the description above refers to user space and CTM it
* refers to the user space and CTM in effect at the time of the
* stroking operation, not the user space and CTM in effect at the
* time of the call to cairo_set_line_width(). The simplest usage
* makes both of these spaces identical. That is, if there is no
* change to the CTM between a call to cairo_set_line_with() and the
* stroking operation, then one can just pass user-space values to
* cairo_set_line_width() and ignore this note.
*
* As with the other stroke parameters, the current line width is
* examined by cairo_stroke(), cairo_stroke_extents(), and
* cairo_stroke_to_path(), but does not have any effect during path
* construction.
*
* The default line width value is 2.0.
**/
void
cairo_set_line_width (cairo_t *cr, double width)
@ -795,15 +892,19 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
/**
* cairo_set_dash:
* @cr: a cairo context
* @dashes: an array specifying alternate lengths of on and off po
* @dashes: an array specifying alternate lengths of on and off stroke portions
* @num_dashes: the length of the dashes array
* @offset: an offset into the dash pattern at which the stroke should start
*
* Sets the dash pattern to be used by cairo_stroke(). A dash pattern
* is specified by @dashes, an array of positive values. Each value
* provides the user-space length of altenate "on" and "off" portions
* of the stroke. The @offset specifies an offset into the pattern at
* which the stroke begins.
* provides the length of alternate "on" and "off" portions of the
* stroke. The @offset specifies an offset into the pattern at which
* the stroke begins.
*
* Note: The length values are in user-space units as evaluated at the
* time of stroking. This is not necessarily the same as the user
* space at the time of cairo_set_dash().
*
* If @num_dashes is 0 dashing is disabled.
*
@ -1062,8 +1163,8 @@ cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
* cairo_new_path:
* @cr: a cairo context
*
* Clears the current path. After this call there will be no current
* point.
* Clears the current path. After this call there will be no path and
* no current point.
**/
void
cairo_new_path (cairo_t *cr)
@ -1081,8 +1182,8 @@ slim_hidden_def(cairo_new_path);
* @x: the X coordinate of the new position
* @y: the Y coordinate of the new position
*
* If the current subpath is not empty, begin a new subpath. After
* this call the current point will be (@x, @y).
* Begin a new subpath. After this call the current point will be (@x,
* @y).
**/
void
cairo_move_to (cairo_t *cr, double x, double y)
@ -1102,6 +1203,31 @@ cairo_move_to (cairo_t *cr, double x, double y)
}
slim_hidden_def(cairo_move_to);
/**
* cairo_new_sub_path:
* @cr: a cairo context
*
* Begin a new subpath. Note that the existing path is not
* affected. After this call there will be no current point.
*
* In many cases, this call is not needed since new subpaths are
* frequently started with cairo_move_to().
*
* A call to cairo_new_sub_path() is particularly useful when
* beginning a new subpath with one of the cairo_arc() calls. This
* makes things easier as it is no longer necessary to manually
* compute the arc's initial coordinates for a call to
* cairo_move_to().
**/
void
cairo_new_sub_path (cairo_t *cr)
{
if (cr->status)
return;
_cairo_path_fixed_new_sub_path (&cr->path);
}
/**
* cairo_line_to:
* @cr: a cairo context
@ -1111,6 +1237,9 @@ slim_hidden_def(cairo_move_to);
* Adds a line to the path from the current point to position (@x, @y)
* in user-space coordinates. After this call the current point
* will be (@x, @y).
*
* If there is no current point before the call to cairo_line_to()
* this function will behave as cairo_move_to (@cr, @x, @y).
**/
void
cairo_line_to (cairo_t *cr, double x, double y)
@ -1143,6 +1272,10 @@ cairo_line_to (cairo_t *cr, double x, double y)
* position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and
* (@x2, @y2) as the control points. After this call the current point
* will be (@x3, @y3).
*
* If there is no current point before the call to cairo_curve_to()
* this function will behave as if preceded by a call to
* cairo_move_to (@cr, @x1, @y1).
**/
void
cairo_curve_to (cairo_t *cr,
@ -1198,9 +1331,9 @@ cairo_curve_to (cairo_t *cr,
* arc.
*
* Angles are measured in radians. An angle of 0.0 is in the direction
* of the positive X axis (in user-space). An angle of %M_PI/2.0 radians
* of the positive X axis (in user space). An angle of %M_PI/2.0 radians
* (90 degrees) is in the direction of the positive Y axis (in
* user-space). Angles increase in the direction from the positive X
* user space). Angles increase in the direction from the positive X
* axis toward the positive Y axis. So with the default transformation
* matrix, angles increase in a clockwise direction.
*
@ -1211,7 +1344,7 @@ cairo_curve_to (cairo_t *cr,
* see cairo_arc_negative() to get the arc in the direction of
* decreasing angles.
*
* The arc is circular in user-space. To achieve an elliptical arc,
* The arc is circular in user space. To achieve an elliptical arc,
* you can scale the current transformation matrix by different
* amounts in the X and Y directions. For example, to draw an ellipse
* in the box given by @x, @y, @width, @height:
@ -1313,11 +1446,15 @@ cairo_arc_to (cairo_t *cr,
* @dx: the X offset
* @dy: the Y offset
*
* If the current subpath is not empty, begin a new subpath. After
* this call the current point will offset by (@x, @y).
* Begin a new subpath. After this call the current point will offset
* by (@x, @y).
*
* Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy)
* is logically equivalent to cairo_move_to (@cr, x + @dx, y + @dy).
*
* It is an error to call this function with no current point. Doing
* so will cause @cr to shutdown with a status of
* CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_move_to (cairo_t *cr, double dx, double dy)
@ -1349,6 +1486,10 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
*
* Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy)
* is logically equivalent to cairo_line_to (@cr, x + @dx, y + @dy).
*
* It is an error to call this function with no current point. Doing
* so will cause @cr to shutdown with a status of
* CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
@ -1389,6 +1530,10 @@ slim_hidden_def(cairo_rel_line_to);
* @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to
* cairo_curve_to (@cr, x + @dx1, y + @dy1, x + @dx2, y + @dy2, x +
* @dx3, y + @dy3).
*
* It is an error to call this function with no current point. Doing
* so will cause @cr to shutdown with a status of
* CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_curve_to (cairo_t *cr,
@ -1478,13 +1623,17 @@ cairo_stroke_to_path (cairo_t *cr)
*
* Adds a line segment to the path from the current point to the
* beginning of the current subpath, (the most recent point passed to
* cairo_move_to()), and closes this subpath.
* cairo_move_to()), and closes this subpath. After this call the
* current point will be at the joined endpoint of the subpath.
*
* The behavior of cairo_close_path() is distinct from simply calling
* cairo_line_to() with the equivalent coordinate in the case of
* stroking. When a closed subpath is stroked, there are no caps on
* the ends of the subpath. Instead, their is a line join connecting
* the ends of the subpath. Instead, there is a line join connecting
* the final and initial segments of the subpath.
*
* If there is no current point before the call to cairo_close_path,
* this function will have no effect.
**/
void
cairo_close_path (cairo_t *cr)
@ -2083,6 +2232,46 @@ cairo_get_font_options (cairo_t *cr,
_cairo_gstate_get_font_options (cr->gstate, options);
}
/**
* cairo_set_scaled_font:
* @cr: a #cairo_t
* @scaled_font: a #cairo_scaled_font_t
*
* Replaces the current font face, font matrix, and font options in
* the #cairo_t with those of the #cairo_scaled_font_t. Except for
* some translation, the current CTM of the #cairo_t should be the
* same as that of the #cairo_scaled_font_t, which can be accessed
* using cairo_scaled_font_get_ctm().
**/
void
cairo_set_scaled_font (cairo_t *cr,
const cairo_scaled_font_t *scaled_font)
{
if (cr->status)
return;
cr->status = scaled_font->status;
if (cr->status)
goto BAIL;
cr->status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
if (cr->status)
goto BAIL;
cr->status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
if (cr->status)
goto BAIL;
cr->status = _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
if (cr->status)
goto BAIL;
return;
BAIL:
_cairo_set_error (cr, cr->status);
}
/**
* cairo_text_extents:
* @cr: a #cairo_t
@ -2419,9 +2608,10 @@ cairo_get_fill_rule (cairo_t *cr)
* cairo_get_line_width:
* @cr: a cairo context
*
* Gets the current line width, as set by cairo_set_line_width().
*
* Return value: the current line width, in user-space units.
* Return value: the current line width value exactly as set by
* cairo_set_line_width(). Note that the value is unchanged even if
* the CTM has changed between the calls to cairo_set_line_width() and
* cairo_get_line_width().
**/
double
cairo_get_line_width (cairo_t *cr)
@ -2512,14 +2702,10 @@ cairo_get_target (cairo_t *cr)
/**
* cairo_get_group_target:
* @cr: a cairo context
* @dx: device offset x value from cr's original target
* @dy: device offset y value from cr's original target
*
* Gets the target surface for the current transparency group
* started by the last cairo_push_group() call on the cairo
* context. The offset between this surface and the cairo
* context's original target surface is also returned if
* dx and/or dy are not NULL.
* context.
*
* This function may return NULL if there is no transparency
* group on the target.
@ -2529,21 +2715,14 @@ cairo_get_target (cairo_t *cr)
* cairo_surface_reference().
**/
cairo_surface_t *
cairo_get_group_target (cairo_t *cr, double *dx, double *dy)
cairo_get_group_target (cairo_t *cr)
{
cairo_surface_t *gsurf;
if (cr->status)
return (cairo_surface_t*) &_cairo_surface_nil;
gsurf = _cairo_gstate_get_target (cr->gstate);
if (!gsurf)
return NULL;
if (dx || dy)
_cairo_gstate_get_target_offsets_from_original (cr->gstate, dx, dy);
return gsurf;
return _cairo_gstate_get_target (cr->gstate);
}
/**
@ -2770,6 +2949,8 @@ cairo_status_to_string (cairo_status_t status)
return "file not found";
case CAIRO_STATUS_INVALID_DASH:
return "invalid value for a dash setting";
case CAIRO_STATUS_INVALID_DSC_COMMENT:
return "invalid value for a DSC comment";
}
return "<unknown error status>";

View File

@ -167,6 +167,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual*
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@ -193,7 +194,8 @@ typedef enum _cairo_status {
CAIRO_STATUS_INVALID_FORMAT,
CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND,
CAIRO_STATUS_INVALID_DASH
CAIRO_STATUS_INVALID_DASH,
CAIRO_STATUS_INVALID_DSC_COMMENT
} cairo_status_t;
/**
@ -459,6 +461,9 @@ cairo_new_path (cairo_t *cr);
cairo_public void
cairo_move_to (cairo_t *cr, double x, double y);
cairo_public void
cairo_new_sub_path (cairo_t *cr);
cairo_public void
cairo_line_to (cairo_t *cr, double x, double y);
@ -876,6 +881,10 @@ cairo_public void
cairo_get_font_options (cairo_t *cr,
cairo_font_options_t *options);
cairo_public void
cairo_set_scaled_font (cairo_t *cr,
const cairo_scaled_font_t *scaled_font);
cairo_public void
cairo_show_text (cairo_t *cr, const char *utf8);
@ -1062,7 +1071,7 @@ cairo_public cairo_surface_t *
cairo_get_target (cairo_t *cr);
cairo_public cairo_surface_t *
cairo_get_group_target (cairo_t *cr, double *dx, double *dy);
cairo_get_group_target (cairo_t *cr);
typedef enum _cairo_path_data_type {
CAIRO_PATH_MOVE_TO,
@ -1277,6 +1286,9 @@ typedef enum _cairo_surface_type {
cairo_public cairo_surface_type_t
cairo_surface_get_type (cairo_surface_t *surface);
cairo_public cairo_content_t
cairo_surface_get_content (cairo_surface_t *surface);
#if CAIRO_HAS_PNG_FUNCTIONS
cairo_public cairo_status_t
@ -1563,6 +1575,10 @@ cairo_public void
cairo_matrix_transform_point (const cairo_matrix_t *matrix,
double *x, double *y);
/* Functions to be used while debugging (not intended for use in production code) */
cairo_public void
cairo_debug_reset_static_data (void);
#ifndef _CAIROINT_H_
/* Obsolete functions. These definitions exist to coerce the compiler

View File

@ -63,7 +63,6 @@
#include <stdio.h>
#include "cairo.h"
#include "cairo-debug.h"
#include <pixman.h>
CAIRO_BEGIN_DECLS
@ -247,7 +246,7 @@ typedef struct _cairo_trapezoid {
typedef struct _cairo_rectangle {
short x, y;
unsigned short width, height;
} cairo_rectangle_t, cairo_glyph_size_t;
} cairo_rectangle_fixed_t, cairo_glyph_size_t;
/* Sure wish C had a real enum type so that this would be distinct
from cairo_status_t. Oh well, without that, I'll use this bogus 1000
@ -262,6 +261,7 @@ typedef enum cairo_int_status {
typedef enum cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
@ -332,10 +332,10 @@ typedef struct _cairo_image_surface cairo_image_surface_t;
typedef struct _cairo_surface_backend cairo_surface_backend_t;
cairo_private void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle);
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_fixed_t *rectangle);
cairo_private void
_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src);
_cairo_rectangle_intersect (cairo_rectangle_fixed_t *dest, cairo_rectangle_fixed_t *src);
/* cairo_array.c structures and functions */
@ -637,18 +637,18 @@ struct _cairo_surface_backend {
void *image_extra);
cairo_status_t
(*acquire_dest_image) (void *abstract_surface,
cairo_rectangle_t *interest_rect,
(*acquire_dest_image) (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void **image_extra);
void
(*release_dest_image) (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra);
(*release_dest_image) (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra);
cairo_status_t
(*clone_similar) (void *surface,
@ -671,11 +671,11 @@ struct _cairo_surface_backend {
unsigned int height);
cairo_int_status_t
(*fill_rectangles) (void *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
(*fill_rectangles) (void *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_fixed_t *rects,
int num_rects);
/* XXX: dst should be the first argument for consistency */
cairo_int_status_t
@ -747,8 +747,8 @@ struct _cairo_surface_backend {
* clip.
*/
cairo_int_status_t
(*get_extents) (void *surface,
cairo_rectangle_t *rectangle);
(*get_extents) (void *surface,
cairo_rectangle_fixed_t *rectangle);
/*
* This is an optional entry to let the surface manage its own glyph
@ -852,6 +852,8 @@ struct _cairo_surface {
* hide their internal type from the user-level API. */
cairo_surface_type_t type;
cairo_content_t content;
unsigned int ref_count;
cairo_status_t status;
cairo_bool_t finished;
@ -1102,9 +1104,6 @@ _cairo_gstate_get_parent_target (cairo_gstate_t *gstate);
cairo_private cairo_surface_t *
_cairo_gstate_get_original_target (cairo_gstate_t *gstate);
cairo_private void
_cairo_gstate_get_target_offsets_from_original (cairo_gstate_t *gstate, double *dx, double *dy);
cairo_private cairo_clip_t *
_cairo_gstate_get_clip (cairo_gstate_t *gstate);
@ -1415,6 +1414,13 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
cairo_private cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
/* cairo_operator.c */
cairo_private cairo_bool_t
_cairo_operator_always_opaque (cairo_operator_t op);
cairo_private cairo_bool_t
_cairo_operator_always_translucent (cairo_operator_t op);
/* cairo_path.c */
cairo_private void
_cairo_path_fixed_init (cairo_path_fixed_t *path);
@ -1437,6 +1443,9 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y);
cairo_private void
_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
@ -1560,10 +1569,10 @@ _cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
cairo_text_extents_t *extents);
cairo_private cairo_status_t
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_rectangle_t *extents);
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_rectangle_fixed_t *extents);
cairo_private cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
@ -1581,7 +1590,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_private cairo_status_t
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_fixed_t *path);
@ -1627,6 +1636,10 @@ extern const cairo_private cairo_surface_t _cairo_surface_nil;
extern const cairo_private cairo_surface_t _cairo_surface_nil_read_error;
extern const cairo_private cairo_surface_t _cairo_surface_nil_file_not_found;
cairo_private void
_cairo_surface_set_error (cairo_surface_t *surface,
cairo_status_t status);
cairo_private cairo_surface_t *
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
cairo_content_t content,
@ -1642,7 +1655,8 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_private void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend);
const cairo_surface_backend_t *backend,
cairo_content_t content);
cairo_private cairo_clip_mode_t
_cairo_surface_get_clip_mode (cairo_surface_t *surface);
@ -1678,10 +1692,10 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
cairo_rectangle_fixed_t *rects,
int num_rects);
cairo_private cairo_status_t
_cairo_surface_paint (cairo_surface_t *surface,
@ -1754,16 +1768,16 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void **image_extra);
cairo_private void
_cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_t *interest_rect,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
cairo_rectangle_fixed_t *image_rect,
void *image_extra);
cairo_private cairo_status_t
@ -1799,8 +1813,8 @@ cairo_private cairo_status_t
_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle);
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_fixed_t *rectangle);
cairo_private cairo_status_t
_cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
@ -1849,6 +1863,9 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height);
cairo_private cairo_bool_t
_cairo_surface_is_opaque (const cairo_surface_t *surface);
cairo_private cairo_bool_t
_cairo_surface_has_device_offset_or_scale (cairo_surface_t *surface);
@ -1895,6 +1912,19 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data,
cairo_private void
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
/* XXX: It's a nasty kludge that this appears here. Backend functions
* like this should really be static. But we're doing this to work
* around some general defects in the backend clipping interfaces,
* (see some notes in test-paginated-surface.c).
*
* I want to fix the real defects, but it's "hard" as they touch many
* backends, so doing that will require synchronizing several backend
* maintainers.
*/
cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region);
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface);
@ -1999,6 +2029,10 @@ cairo_private cairo_bool_t
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
int *itx, int *ity);
cairo_private cairo_bool_t
_cairo_matrix_is_integer_translation_and_scale(const cairo_matrix_t *m,
int *itx, int *ity, int *sx, int *sy);
cairo_private double
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
@ -2095,7 +2129,10 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse);
cairo_private cairo_bool_t
_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern);
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
cairo_private cairo_int_status_t
_cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
@ -2128,8 +2165,8 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_surface_attributes_t *mask_attributes);
cairo_private cairo_status_t
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_t *extents);
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_fixed_t *extents);
cairo_private cairo_status_t
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
@ -2141,11 +2178,11 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate);
/* cairo-region.c */
cairo_private pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_t *rect);
_cairo_region_create_from_rectangle (cairo_rectangle_fixed_t *rect);
cairo_private void
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_t *rect);
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_fixed_t *rect);
/* cairo_unicode.c */
@ -2165,14 +2202,37 @@ _cairo_utf8_to_utf16 (const unsigned char *str,
typedef struct _cairo_output_stream cairo_output_stream_t;
extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
/* We already have the following declared in cairo.h:
typedef cairo_status_t (*cairo_write_func_t) (void *closure,
const unsigned char *data,
unsigned int length);
*/
typedef cairo_status_t (*cairo_close_func_t) (void *closure);
/* This function never returns NULL. If an error occurs (NO_MEMORY)
* while trying to create the output stream this function returns a
* valid pointer to a nil output stream.
*
* Note that even with a nil surface, the close_func callback will be
* called by a call to _cairo_output_stream_close or
* _cairo_output_stream_destroy.
*/
cairo_private cairo_output_stream_t *
_cairo_output_stream_create (cairo_write_func_t write_func,
cairo_close_func_t close_func,
void *closure);
cairo_private void
_cairo_output_stream_close (cairo_output_stream_t *stream);
cairo_private void
_cairo_output_stream_destroy (cairo_output_stream_t *stream);
cairo_private cairo_status_t
cairo_private void
_cairo_output_stream_write (cairo_output_stream_t *stream,
const void *data, size_t length);
@ -2181,21 +2241,14 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
const char *data,
size_t length);
cairo_private unsigned char *
_cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
cairo_private void
_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
const char *data,
size_t length);
cairo_private void *
_cairo_compress_lzw (void *data,
unsigned long data_size,
unsigned long *compressed_size);
cairo_private cairo_status_t
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap);
cairo_private cairo_status_t
cairo_private void
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
@ -2205,8 +2258,30 @@ _cairo_output_stream_get_position (cairo_output_stream_t *status);
cairo_private cairo_status_t
_cairo_output_stream_get_status (cairo_output_stream_t *stream);
/* This function never returns NULL. If an error occurs (NO_MEMORY or
* WRITE_ERROR) while trying to create the output stream this function
* returns a valid pointer to a nil output stream.
*
* NOTE: Even if a nil surface is returned, the caller should still
* call _cairo_output_stream_destroy (or _cairo_output_stream_close at
* least) in order to ensure that everything is properly cleaned up.
*/
cairo_private cairo_output_stream_t *
_cairo_output_stream_create_for_file (const char *filename);
_cairo_output_stream_create_for_filename (const char *filename);
/* This function never returns NULL. If an error occurs (NO_MEMORY or
* WRITE_ERROR) while trying to create the output stream this function
* returns a valid pointer to a nil output stream.
*
* The caller still "owns" file and is responsible for calling fclose
* on it when finished. The stream will not do this itself.
*/
cairo_private cairo_output_stream_t *
_cairo_output_stream_create_for_file (FILE *file);
/* cairo_base85_stream.c */
cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
cairo_private void
_cairo_error (cairo_status_t status);

View File

@ -82,7 +82,8 @@ _test_fallback_surface_create (cairo_content_t content,
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &test_fallback_surface_backend);
_cairo_surface_init (&surface->base, &test_fallback_surface_backend,
content);
surface->backing = backing;
@ -134,11 +135,11 @@ _test_fallback_surface_release_source_image (void *abstract_surface,
}
static cairo_status_t
_test_fallback_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t**image_out,
cairo_rectangle_t *image_rect_out,
void **image_extra)
_test_fallback_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_fixed_t *image_rect_out,
void **image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -150,11 +151,11 @@ _test_fallback_surface_acquire_dest_image (void *abstract_surface,
}
static void
_test_fallback_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t*image,
cairo_rectangle_t *image_rect,
void *image_extra)
_test_fallback_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_fixed_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_fixed_t *image_rect,
void *image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -166,8 +167,8 @@ _test_fallback_surface_release_dest_image (void *abstract_surface,
}
static cairo_int_status_t
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
test_fallback_surface_t *surface = abstract_surface;

View File

@ -78,7 +78,8 @@ _test_meta_surface_create (cairo_content_t content,
if (surface == NULL)
goto FAIL;
_cairo_surface_init (&surface->base, &test_meta_surface_backend);
_cairo_surface_init (&surface->base, &test_meta_surface_backend,
content);
surface->meta = _cairo_meta_surface_create (content, width, height);
if (cairo_surface_status (surface->meta))
@ -169,7 +170,7 @@ _test_meta_surface_intersect_clip_path (void *abstract_surface,
static cairo_int_status_t
_test_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
cairo_rectangle_fixed_t *rectangle)
{
test_meta_surface_t *surface = abstract_surface;
@ -279,7 +280,7 @@ _test_meta_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_t extents;
cairo_rectangle_fixed_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->image, &extents);

View File

@ -51,6 +51,15 @@
#include "cairo-paginated-surface-private.h"
typedef struct _test_paginated_surface {
cairo_surface_t base;
cairo_surface_t *target;
cairo_paginated_mode_t paginated_mode;
} test_paginated_surface_t;
static const cairo_surface_backend_t test_paginated_surface_backend;
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
cairo_surface_t *
_test_paginated_surface_create_for_data (unsigned char *data,
cairo_content_t content,
@ -58,11 +67,219 @@ _test_paginated_surface_create_for_data (unsigned char *data,
int height,
int stride)
{
cairo_status_t status;
cairo_surface_t *target;
test_paginated_surface_t *surface;
target = _cairo_image_surface_create_for_data_with_content (data, content,
target = _cairo_image_surface_create_for_data_with_content (data, content,
width, height,
stride);
status = cairo_surface_status (target);
if (status) {
_cairo_error (status);
return (cairo_surface_t *) &_cairo_surface_nil;
}
return _cairo_paginated_surface_create (target, content, width, height);
surface = malloc (sizeof (test_paginated_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &test_paginated_surface_backend,
content);
surface->target = target;
return _cairo_paginated_surface_create (&surface->base, content, width, height,
&test_paginated_surface_paginated_backend);
}
static cairo_int_status_t
_test_paginated_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
/* XXX: The whole surface backend clipping interface is a giant
* disaster right now. In particular, its uncleanness shows up
* when trying to implement one surface that wraps another one (as
* we are doing here).
*
* Here are two of the problems that show up:
*
* 1. The most critical piece of information in all this stuff,
* the "clip" isn't getting passed to the backend
* functions. Instead the generic surface layer is caching that as
* surface->clip. This is a problem for surfaces like this one
* that do wrapping. Our base surface will have the clip set, but
* our target's surface will not.
*
* 2. We're here in our backend's set_clip_region function, and we
* want to call into our target surface's set_clip_region.
* Generally, we would do this by calling an equivalent
* _cairo_surface function, but _cairo_surface_set_clip_region
* does not have the same signature/semantics, (it has the
* clip_serial stuff as well).
*
* We kludge around each of these by manually copying the clip
* object from our base surface into the target's base surface
* (yuck!) and by reaching directly into the image surface's
* set_clip_region instead of calling into the generic
* _cairo_surface_set_clip_region (double yuck!).
*/
surface->target->clip = surface->base.clip;
return _cairo_image_surface_set_clip_region (surface->target, region);
}
static cairo_int_status_t
_test_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_fixed_t *rectangle)
{
test_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->target, rectangle);
}
static cairo_int_status_t
_test_paginated_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
return _cairo_surface_paint (surface->target, op, source);
}
static cairo_int_status_t
_test_paginated_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
return _cairo_surface_mask (surface->target, op, source, mask);
}
static cairo_int_status_t
_test_paginated_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
return _cairo_surface_stroke (surface->target, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias);
}
static cairo_int_status_t
_test_paginated_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
return _cairo_surface_fill (surface->target, op, source,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_test_paginated_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
test_paginated_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
return _cairo_surface_show_glyphs (surface->target, op, source,
glyphs, num_glyphs, scaled_font);
}
static void
_test_paginated_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t mode)
{
test_paginated_surface_t *surface = abstract_surface;
surface->paginated_mode = mode;
}
static const cairo_surface_backend_t test_paginated_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
/* Since we are a paginated user, we get to regard most of the
* surface backend interface as historical cruft and ignore it. */
NULL, /* create_similar */
NULL, /* finish */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
_test_paginated_surface_set_clip_region,
NULL, /* intersect_clip_path */
_test_paginated_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 */
/* Here is the more "modern" section of the surface backend
* interface which is mostly just drawing functions */
_test_paginated_surface_paint,
_test_paginated_surface_mask,
_test_paginated_surface_stroke,
_test_paginated_surface_fill,
_test_paginated_surface_show_glyphs,
NULL /* snapshot */
};
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = {
NULL, /* start_page */
_test_paginated_surface_set_paginated_mode
};

View File

@ -430,8 +430,9 @@ nsThebesRenderingContext::Translate(nscoord aX, nscoord aY)
NS_IMETHODIMP
nsThebesRenderingContext::Scale(float aSx, float aSy)
{
// as far as I can tell, noone actually calls this
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::Scale %f %f\n", this, aSx, aSy));
mThebes->Scale (FROM_TWIPS(aSx), FROM_TWIPS(aSy));
mThebes->Scale (aSx, aSy);
return NS_OK;
}

View File

@ -104,6 +104,7 @@ endif
EXTRA_DSO_LDOPTS += $(TK_LIBS)
DEFINES += -DIMPL_THEBES
include $(topsrcdir)/config/rules.mk

View File

@ -75,18 +75,17 @@ gfxASurface *gfxContext::OriginalSurface()
already_AddRefed<gfxASurface> gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy)
{
cairo_surface_t *s = cairo_get_group_target(mCairo, dx, dy);
cairo_surface_t *s = cairo_get_group_target(mCairo);
if (!s) {
if (dx) {
*dx = 0.0;
*dy = 0.0;
}
if (dx && dy)
cairo_surface_get_device_offset (mSurface->CairoSurface(), dx, dy);
gfxASurface *ret = mSurface;
NS_ADDREF(ret);
return ret;
}
if (dx && dy)
cairo_surface_get_device_offset (s, dx, dy);
return gfxASurface::Wrap(s);
}

View File

@ -815,10 +815,6 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
gfxFloat xoff, yoff;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
if (!surf) {
surf = ctx->CurrentSurface();
xoff = yoff = 0.0;
}
HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC();
SaveDC(hdc);
@ -827,18 +823,12 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
/* Need to force the clip to be set */
ctx->UpdateSurfaceClip();
//ctx->CurrentSurface()->Flush();
/* Set the device offsets as appropriate */
POINT origViewportOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x - (int) xoff, origViewportOrigin.y - (int) yoff, NULL);
/* Covert the current transform to a world transform */
gfxMatrix m = ctx->CurrentMatrix();
XFORM xform;
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
xform.eM11 = (FLOAT) dm[0];
xform.eM12 = (FLOAT) dm[1];
xform.eM21 = (FLOAT) dm[2];
@ -847,6 +837,19 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
xform.eDy = (FLOAT) dm[5];
SetWorldTransform (hdc, &xform);
#if 0
fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", dm[0], dm[1], dm[2], dm[3], dm[4], dm[5]);
fprintf (stderr, "tr: [%d %d %d %d]\ncr: [%d %d %d %d]\noff: [%f %f]\n",
tr.x, tr.y, tr.width, tr.height, cr.x, cr.y, cr.width, cr.height,
xoff, yoff);
fflush (stderr);
#endif
/* Set the device offsets as appropriate */
POINT origViewportOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int) xoff, origViewportOrigin.y + (int) yoff, NULL);
#else /* non-MOZ_CAIRO_GFX */
nsTransform2D* transformMatrix;
@ -870,6 +873,13 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
GetNativeRect(tr, widgetRect);
GetNativeRect(cr, clipRect);
#if 0
fprintf (stderr, "widget: [%d %d %d %d]\nclip: [%d %d %d %d]\n",
widgetRect.left, widgetRect.top, widgetRect.right, widgetRect.bottom,
clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
fflush (stderr);
#endif
// For left edge and right edge tabs, we need to adjust the widget
// rects and clip rects so that the edges don't get drawn.
if (aWidgetType == NS_THEME_TAB_LEFT_EDGE || aWidgetType == NS_THEME_TAB_RIGHT_EDGE) {