b=419715, upgrade cairo to 1.6 or as-close-as-possible -- imported patch cairo-upgrade.patch ; r=me

This commit is contained in:
vladimir@pobox.com 2008-04-06 15:14:09 -07:00
Родитель fdff5bb834
Коммит ec70458884
44 изменённых файлов: 2248 добавлений и 1733 удалений

Просмотреть файл

@ -7181,7 +7181,7 @@ if test "$MOZ_TREE_CAIRO"; then
if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
QUARTZ_IMAGE_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_IMAGE_SURFACE 1"
ATSUI_FONT_FEATURE="#define CAIRO_HAS_ATSUI_FONT 1"
QUARTZ_FONT_FEATURE="#define CAIRO_HAS_QUARTZ_FONT 1"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
@ -7231,7 +7231,7 @@ if test "$MOZ_TREE_CAIRO"; then
AC_SUBST(DIRECTFB_SURFACE_FEATURE)
AC_SUBST(FT_FONT_FEATURE)
AC_SUBST(WIN32_FONT_FEATURE)
AC_SUBST(ATSUI_FONT_FEATURE)
AC_SUBST(QUARTZ_FONT_FEATURE)
AC_SUBST(PNG_FUNCTIONS_FEATURE)
if test "$_WIN32_MSVC"; then

Просмотреть файл

@ -7,7 +7,7 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.6.x - 1.5.12-56-ga33351f)
cairo (1.6.x - 1.5.16-23-gbb76eb5)
pixman (0.10.x - pixman-0.10.0-5-g4cde088)
glitz 0.5.2 (cvs - 2006-01-10)

Просмотреть файл

@ -164,8 +164,8 @@ EXPORTS += $(PDF_EXPORTS)
endif
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
CSRCS += cairo-quartz-surface.c cairo-quartz-image-surface.c cairo-atsui-font.c
EXPORTS += cairo-quartz.h cairo-atsui.h cairo-quartz-image.h
CSRCS += cairo-quartz-surface.c cairo-quartz-image-surface.c cairo-quartz-font.c
EXPORTS += cairo-quartz.h cairo-quartz-image.h
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
@ -186,6 +186,7 @@ endif
ifdef MOZ_X11
CSRCS += cairo-xlib-surface.c \
cairo-xlib-screen.c \
cairo-xlib-visual.c \
cairo-xlib-display.c
EXPORTS += cairo-xlib.h cairo-xlib-xrender.h
endif

Просмотреть файл

@ -125,8 +125,20 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
cairo_int_status_t status;
cairo_box_t bbox;
if (rect->width == 0 || rect->height == 0)
return CAIRO_STATUS_SUCCESS;
if (rect->width == 0 || rect->height == 0) {
/* Even though the operation is not visible we must be careful
* to not allow unsupported operations to be replayed to the
* backend during CAIRO_PAGINATED_MODE_RENDER */
if (backend_status == CAIRO_STATUS_SUCCESS ||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
{
return CAIRO_STATUS_SUCCESS;
}
else
{
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
}
if (surface->has_ctm) {
double x1, y1, x2, y2;
@ -143,8 +155,21 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
x2 = ceil (x2) - rect->x;
y2 = ceil (y2) - rect->y;
if (x2 <= 0 || y2 <= 0)
return CAIRO_STATUS_SUCCESS;
if (x2 <= 0 || y2 <= 0) {
/* Even though the operation is not visible we must be
* careful to not allow unsupported operations to be
* replayed to the backend during
* CAIRO_PAGINATED_MODE_RENDER */
if (backend_status == CAIRO_STATUS_SUCCESS ||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
{
return CAIRO_STATUS_SUCCESS;
}
else
{
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
}
rect->width = x2;
rect->height = y2;
@ -434,17 +459,23 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
ctm, ctm_inverse,
tolerance,
&traps);
if (status || traps.num_traps == 0) {
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_traps_extents (&traps, &box);
extents.x = _cairo_fixed_integer_floor (box.p1.x);
extents.y = _cairo_fixed_integer_floor (box.p1.y);
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
if (traps.num_traps == 0) {
extents.x = 0;
extents.y = 0;
extents.width = 0;
extents.height = 0;
} else {
_cairo_traps_extents (&traps, &box);
extents.x = _cairo_fixed_integer_floor (box.p1.x);
extents.y = _cairo_fixed_integer_floor (box.p1.y);
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
}
_cairo_traps_fini (&traps);
}
@ -506,17 +537,23 @@ _cairo_analysis_surface_fill (void *abstract_surface,
fill_rule,
tolerance,
&traps);
if (status || traps.num_traps == 0) {
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_traps_extents (&traps, &box);
extents.x = _cairo_fixed_integer_floor (box.p1.x);
extents.y = _cairo_fixed_integer_floor (box.p1.y);
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
if (traps.num_traps == 0) {
extents.x = 0;
extents.y = 0;
extents.width = 0;
extents.height = 0;
} else {
_cairo_traps_extents (&traps, &box);
extents.x = _cairo_fixed_integer_floor (box.p1.x);
extents.y = _cairo_fixed_integer_floor (box.p1.y);
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
}
_cairo_traps_fini (&traps);
}

Просмотреть файл

@ -110,15 +110,19 @@ _cairo_array_fini (cairo_array_t *array)
* is always increased by doubling as many times as necessary.
**/
cairo_status_t
_cairo_array_grow_by (cairo_array_t *array, int additional)
_cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
{
char *new_elements;
int old_size = array->size;
int required_size = array->num_elements + additional;
int new_size;
unsigned int old_size = array->size;
unsigned int required_size = array->num_elements + additional;
unsigned int new_size;
assert (! array->is_snapshot);
/* check for integer overflow */
if (required_size > INT_MAX || required_size < array->num_elements)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (required_size <= old_size)
return CAIRO_STATUS_SUCCESS;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,58 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Calum Robinson
*
* 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 Calum Robinson
*
* Contributor(s):
* Calum Robinson <calumr@mac.com>
*/
#ifndef CAIRO_ATSUI_H
#define CAIRO_ATSUI_H
#include <cairo.h>
#if CAIRO_HAS_ATSUI_FONT
/* ATSUI platform-specific font interface */
#include <Carbon/Carbon.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_font_face_t *
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id);
CAIRO_END_DECLS
#else /* CAIRO_HAS_ATSUI_FONT */
# error Cairo was not compiled with support for the atsui font backend
#endif /* CAIRO_HAS_ATSUI_FONT */
#endif /* CAIRO_ATSUI_H */

Просмотреть файл

@ -50,6 +50,8 @@
*/
#define CAIRO_FORMAT_RGB16_565 4
#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
#ifndef _CAIROINT_H_
/* Obsolete functions. These definitions exist to coerce the compiler
@ -104,6 +106,7 @@
#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_atsui_font_face_create_for_atsu_font_id cairo_atsui_font_face_create_for_atsu_font_id_REPLACED_BY_cairo_quartz_font_face_create_for_atsu_font_id
#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path
#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat

Просмотреть файл

@ -53,9 +53,9 @@
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 5
#define CAIRO_VERSION_MICRO 12
#define CAIRO_VERSION_MICRO 16
#define CAIRO_VERSION_STRING "1.5.12"
#define CAIRO_VERSION_STRING "1.5.16"
@PS_SURFACE_FEATURE@
@ -87,7 +87,7 @@
@WIN32_FONT_FEATURE@
@ATSUI_FONT_FEATURE@
@QUARTZ_FONT_FEATURE@
@PNG_FUNCTIONS_FEATURE@

Просмотреть файл

@ -433,6 +433,7 @@ _cairo_toy_font_face_create (const char *family,
return &font_face->base;
UNWIND_FONT_FACE_INIT:
_cairo_toy_font_face_fini (font_face);
UNWIND_FONT_FACE_MALLOC:
free (font_face);
UNWIND_HASH_TABLE_LOCK:

Просмотреть файл

@ -817,7 +817,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
(((int) (gradient->stops[i].color.green_short >> 8)) << 8) |
(((int) (gradient->stops[i].color.blue_short >> 8)));
params[n_base_params + 3 * i + 0] = gradient->stops[i].x;
params[n_base_params + 3 * i + 0] = _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
params[n_base_params + 3 * i + 1] = i << 16;
params[n_base_params + 3 * i + 2] = 0;
}

Просмотреть файл

@ -255,7 +255,7 @@ _cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
cairo_status_t
_cairo_gstate_save (cairo_gstate_t **gstate)
{
cairo_gstate_t *top;
cairo_gstate_t *top = NULL;
cairo_status_t status;
status = _cairo_gstate_clone (*gstate, &top);
@ -290,27 +290,6 @@ _cairo_gstate_restore (cairo_gstate_t **gstate)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
cairo_clip_path_t *cpath)
{
cairo_status_t status;
if (cpath == NULL)
return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_recursive_apply_clip_path (gstate, cpath->prev);
if (status)
return status;
return _cairo_clip_clip (&gstate->clip,
&cpath->path,
cpath->fill_rule,
cpath->tolerance,
cpath->antialias,
gstate->target);
}
/**
* _cairo_gstate_redirect_target:
* @gstate: a #cairo_gstate_t

Просмотреть файл

@ -192,7 +192,7 @@ cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
{
cairo_status_t status;
cairo_hull_t *hull;
cairo_hull_t *hull = NULL;
int num_hull = *num_vertices;
status = _cairo_hull_create (vertices, num_hull, &hull);

Просмотреть файл

@ -59,6 +59,7 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_a4: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1:
case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
case PIXMAN_g4: case PIXMAN_g1:
case PIXMAN_yuy2: case PIXMAN_yv12:
default:
return CAIRO_FORMAT_INVALID;
}
@ -100,6 +101,8 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_c4:
case PIXMAN_g4:
case PIXMAN_g1:
case PIXMAN_yuy2:
case PIXMAN_yv12:
return CAIRO_CONTENT_COLOR;
case PIXMAN_a8:
case PIXMAN_a1:
@ -141,143 +144,104 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return &surface->base;
}
/* XXX: This function should really live inside pixman. */
pixman_format_code_t
_pixman_format_from_masks (cairo_format_masks_t *masks)
cairo_int_status_t
_pixman_format_from_masks (cairo_format_masks_t *masks,
pixman_format_code_t *format_ret)
{
switch (masks->bpp) {
case 32:
if (masks->alpha_mask == 0xff000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
return PIXMAN_a8r8g8b8;
}
if (masks->alpha_mask == 0x00000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
return PIXMAN_x8r8g8b8;
}
if (masks->alpha_mask == 0xff000000 &&
masks->red_mask == 0x000000ff &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x00ff0000)
{
return PIXMAN_a8b8g8r8;
}
if (masks->alpha_mask == 0x00000000 &&
masks->red_mask == 0x000000ff &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x00ff0000)
{
return PIXMAN_x8b8g8r8;
}
break;
case 16:
if (masks->alpha_mask == 0x0000 &&
masks->red_mask == 0xf800 &&
masks->green_mask == 0x07e0 &&
masks->blue_mask == 0x001f)
{
return PIXMAN_r5g6b5;
}
if (masks->alpha_mask == 0x0000 &&
masks->red_mask == 0x7c00 &&
masks->green_mask == 0x03e0 &&
masks->blue_mask == 0x001f)
{
return PIXMAN_x1r5g5b5;
}
break;
case 8:
if (masks->alpha_mask == 0xff)
{
return PIXMAN_a8;
}
break;
case 1:
if (masks->alpha_mask == 0x1)
{
return PIXMAN_a1;
}
break;
pixman_format_code_t format;
int format_type;
int a, r, g, b;
cairo_format_masks_t format_masks;
a = _cairo_popcount (masks->alpha_mask);
r = _cairo_popcount (masks->red_mask);
g = _cairo_popcount (masks->green_mask);
b = _cairo_popcount (masks->blue_mask);
if (masks->red_mask) {
if (masks->red_mask > masks->blue_mask)
format_type = PIXMAN_TYPE_ARGB;
else
format_type = PIXMAN_TYPE_ABGR;
} else if (masks->alpha_mask) {
format_type = PIXMAN_TYPE_A;
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
fprintf (stderr,
"Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
"\tDepth: %d\n"
"\tAlpha mask: 0x%08lx\n"
"\tRed mask: 0x%08lx\n"
"\tGreen mask: 0x%08lx\n"
"\tBlue mask: 0x%08lx\n"
"Please file an enhancement request (quoting the above) at:\n"
PACKAGE_BUGREPORT "\n",
masks->bpp, masks->alpha_mask,
masks->red_mask, masks->green_mask, masks->blue_mask);
format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
ASSERT_NOT_REACHED;
return 0;
if (! pixman_format_supported_destination (format))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Sanity check that we got out of PIXMAN_FORMAT exactly what we
* expected. This avoid any problems from something bizarre like
* alpha in the least-significant bits, or insane channel order,
* or whatever. */
_pixman_format_to_masks (format, &format_masks);
if (masks->bpp != format_masks.bpp ||
masks->red_mask != format_masks.red_mask ||
masks->green_mask != format_masks.green_mask ||
masks->blue_mask != format_masks.blue_mask)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
*format_ret = format;
return CAIRO_STATUS_SUCCESS;
}
/* XXX: This function should really live inside pixman. */
/* A mask consisting of N bits set to 1. */
#define MASK(N) ((1 << (N))-1)
void
_pixman_format_to_masks (pixman_format_code_t pixman_format,
uint32_t *bpp,
uint32_t *red,
uint32_t *green,
uint32_t *blue)
_pixman_format_to_masks (pixman_format_code_t format,
cairo_format_masks_t *masks)
{
*red = 0x0;
*green = 0x0;
*blue = 0x0;
int a, r, g, b;
switch (pixman_format)
{
case PIXMAN_a8r8g8b8:
case PIXMAN_x8r8g8b8:
masks->bpp = PIXMAN_FORMAT_BPP (format);
/* Number of bits in each channel */
a = PIXMAN_FORMAT_A (format);
r = PIXMAN_FORMAT_R (format);
g = PIXMAN_FORMAT_G (format);
b = PIXMAN_FORMAT_B (format);
switch (PIXMAN_FORMAT_TYPE (format)) {
case PIXMAN_TYPE_ARGB:
masks->alpha_mask = MASK (a) << (r + g + b);
masks->red_mask = MASK (r) << (g + b);
masks->green_mask = MASK (g) << (b);
masks->blue_mask = MASK (b);
return;
case PIXMAN_TYPE_ABGR:
masks->alpha_mask = MASK (a) << (b + g + r);
masks->blue_mask = MASK (b) << (g +r);
masks->green_mask = MASK (g) << (r);
masks->red_mask = MASK (r);
return;
case PIXMAN_TYPE_A:
masks->alpha_mask = MASK (a);
masks->red_mask = 0;
masks->green_mask = 0;
masks->blue_mask = 0;
return;
case PIXMAN_TYPE_OTHER:
case PIXMAN_TYPE_COLOR:
case PIXMAN_TYPE_GRAY:
case PIXMAN_TYPE_YUY2:
case PIXMAN_TYPE_YV12:
default:
*bpp = 32;
*red = 0x00ff0000;
*green = 0x0000ff00;
*blue = 0x000000ff;
break;
case PIXMAN_a8b8g8r8:
case PIXMAN_x8b8g8r8:
*bpp = 32;
*red = 0x000000ff;
*green = 0x0000ff00;
*blue = 0x00ff0000;
break;
case PIXMAN_r5g6b5:
*bpp = 16;
*red = 0xf800;
*green = 0x07e0;
*blue = 0x001f;
break;
case PIXMAN_x1r5g5b5:
*bpp = 16;
*red = 0x7c00;
*green = 0x03e0;
*blue = 0x001f;
break;
case PIXMAN_a8:
*bpp = 8;
break;
case PIXMAN_a1:
*bpp = 1;
break;
masks->alpha_mask = 0;
masks->red_mask = 0;
masks->green_mask = 0;
masks->blue_mask = 0;
return;
}
}
/* XXX: This function really should be eliminated. We don't really
* want to advertise a cairo image surface that supports any possible
* format. A minimal step would be to replace this function with one
@ -289,9 +253,25 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
int height,
int stride)
{
cairo_int_status_t status;
pixman_format_code_t pixman_format;
pixman_format = _pixman_format_from_masks (masks);
status = _pixman_format_from_masks (masks, &pixman_format);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
fprintf (stderr,
"Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
"\tDepth: %d\n"
"\tAlpha mask: 0x%08lx\n"
"\tRed mask: 0x%08lx\n"
"\tGreen mask: 0x%08lx\n"
"\tBlue mask: 0x%08lx\n"
"Please file an enhancement request (quoting the above) at:\n"
PACKAGE_BUGREPORT "\n",
masks->bpp, masks->alpha_mask,
masks->red_mask, masks->green_mask, masks->blue_mask);
ASSERT_NOT_REACHED;
}
return _cairo_image_surface_create_with_pixman_format (data,
pixman_format,
@ -395,9 +375,6 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
width, height);
}
/* pixman required stride alignment in bytes. should be power of two. */
#define STRIDE_ALIGNMENT (sizeof (uint32_t))
/**
* cairo_format_stride_for_width:
* @format: A #cairo_format_t value
@ -439,7 +416,7 @@ cairo_format_stride_for_width (cairo_format_t format,
if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp))
return -1;
return ((bpp*width+7)/8 + STRIDE_ALIGNMENT-1) & ~(STRIDE_ALIGNMENT-1);
return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
}
slim_hidden_def (cairo_format_stride_for_width);
@ -498,7 +475,7 @@ cairo_image_surface_create_for_data (unsigned char *data,
if (! CAIRO_FORMAT_VALID (format))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
if ((stride & (STRIDE_ALIGNMENT-1)) != 0)
if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
pixman_format = _cairo_format_to_pixman_format_code (format);
@ -547,6 +524,7 @@ cairo_image_surface_get_data (cairo_surface_t *surface)
return image_surface->data;
}
slim_hidden_def (cairo_image_surface_get_data);
/**
* cairo_image_surface_get_format:
@ -643,6 +621,7 @@ cairo_image_surface_get_stride (cairo_surface_t *surface)
return image_surface->stride;
}
slim_hidden_def (cairo_image_surface_get_stride);
cairo_format_t
_cairo_format_from_content (cairo_content_t content)

Просмотреть файл

@ -743,7 +743,11 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
{
cairo_command_t *stroke_command;
stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
if (type != CAIRO_META_CREATE_REGIONS)
stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
else
stroke_command = NULL;
if (stroke_command != NULL &&
type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL)
{
@ -783,14 +787,6 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
stroke_command->stroke.tolerance,
stroke_command->stroke.antialias);
i++;
if (type == CAIRO_META_CREATE_REGIONS) {
if (status == CAIRO_STATUS_SUCCESS) {
stroke_command->header.region = CAIRO_META_REGION_NATIVE;
} else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
stroke_command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK;
status = CAIRO_STATUS_SUCCESS;
}
}
} else
status = _cairo_surface_fill (target,
command->fill.op,

Просмотреть файл

@ -110,9 +110,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
const char *data,
size_t length);
cairo_private void
_cairo_dtostr (char *buffer, size_t size, double d);
cairo_private void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt,

Просмотреть файл

@ -44,6 +44,26 @@
#include <ctype.h>
#include <errno.h>
/* Numbers printed with %f are printed with this number of significant
* digits after the decimal.
*/
#define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
/* Numbers printed with %g are assumed to only have CAIRO_FIXED_FRAC_BITS
* bits of precision available after the decimal point.
*
* FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
* digits after the decimal point required to preserve the available
* precision.
*
* The conversion is:
*
* FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
*
* We can replace ceil(x) with (int)(x+1) since x will never be an
* integer for any likely value of CAIRO_FIXED_FRAC_BITS.
*/
#define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
void
_cairo_output_stream_init (cairo_output_stream_t *stream,
@ -236,8 +256,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
}
}
#define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
/* 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
@ -246,8 +264,8 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
* has been relicensed under the LGPL/MPL dual license for inclusion
* into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
*/
void
_cairo_dtostr (char *buffer, size_t size, double d)
static void
_cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precision)
{
struct lconv *locale_data;
const char *decimal_point;
@ -266,40 +284,44 @@ _cairo_dtostr (char *buffer, size_t size, double d)
assert (decimal_point_len != 0);
/* Using "%f" to print numbers less than 0.1 will result in
* reduced precision due to the default 6 digits after the
* decimal point.
*
* For numbers is < 0.1, we print with maximum precision and count
* the number of zeros between the decimal point and the first
* significant digit. We then print the number again with the
* number of decimal places that gives us the required number of
* significant digits. This ensures the number is correctly
* rounded.
*/
if (fabs (d) >= 0.1) {
snprintf (buffer, size, "%f", d);
if (limited_precision) {
snprintf (buffer, size, "%.*f", FIXED_POINT_DECIMAL_DIGITS, d);
} else {
snprintf (buffer, size, "%.18f", d);
p = buffer;
/* Using "%f" to print numbers less than 0.1 will result in
* reduced precision due to the default 6 digits after the
* decimal point.
*
* For numbers is < 0.1, we print with maximum precision and count
* the number of zeros between the decimal point and the first
* significant digit. We then print the number again with the
* number of decimal places that gives us the required number of
* significant digits. This ensures the number is correctly
* rounded.
*/
if (fabs (d) >= 0.1) {
snprintf (buffer, size, "%f", d);
} else {
snprintf (buffer, size, "%.18f", d);
p = buffer;
if (*p == '+' || *p == '-')
p++;
if (*p == '+' || *p == '-')
p++;
while (isdigit (*p))
p++;
while (isdigit (*p))
p++;
if (strncmp (p, decimal_point, decimal_point_len) == 0)
p += decimal_point_len;
if (strncmp (p, decimal_point, decimal_point_len) == 0)
p += decimal_point_len;
num_zeros = 0;
while (*p++ == '0')
num_zeros++;
num_zeros = 0;
while (*p++ == '0')
num_zeros++;
decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
if (decimal_digits < 18)
snprintf (buffer, size, "%.*f", decimal_digits, d);
if (decimal_digits < 18)
snprintf (buffer, size, "%.*f", decimal_digits, d);
}
}
p = buffer;
@ -441,7 +463,10 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
single_fmt, va_arg (ap, const char *));
break;
case 'f':
_cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double));
_cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), FALSE);
break;
case 'g':
_cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), TRUE);
break;
case 'c':
buffer[0] = va_arg (ap, int);

Просмотреть файл

@ -613,8 +613,10 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
if (other_buf == NULL ||
path_buf->num_ops != other_buf->num_ops ||
path_buf->num_points != other_buf->num_points ||
memcmp (path_buf->op, other_buf->op, path_buf->num_ops) != 0 ||
memcmp (path_buf->points, other_buf->points, path_buf->num_points != 0))
memcmp (path_buf->op, other_buf->op,
sizeof (cairo_path_op_t) * path_buf->num_ops) != 0 ||
memcmp (path_buf->points, other_buf->points,
sizeof (cairo_point_t) * path_buf->num_points) != 0)
{
return FALSE;
}

Просмотреть файл

@ -821,7 +821,6 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
double alpha)
{
cairo_gradient_stop_t *stops;
cairo_fixed_t x;
unsigned int i;
if (pattern->n_stops >= pattern->stops_size) {
@ -834,10 +833,9 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
stops = pattern->stops;
x = _cairo_fixed_from_double (offset);
for (i = 0; i < pattern->n_stops; i++)
{
if (x < stops[i].x)
if (offset < stops[i].offset)
{
memmove (&stops[i + 1], &stops[i],
sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
@ -846,7 +844,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
}
}
stops[i].x = x;
stops[i].offset = offset;
stops[i].color.red = red;
stops[i].color.green = green;
@ -1208,7 +1206,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
}
for (i = 0; i < pattern->n_stops; i++) {
pixman_stops[i].x = _cairo_fixed_to_16_16 (pattern->stops[i].x);
pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
pixman_stops[i].color.red = pattern->stops[i].color.red_short;
pixman_stops[i].color.green = pattern->stops[i].color.green_short;
pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
@ -2155,7 +2153,7 @@ cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
if (offset)
*offset = _cairo_fixed_to_double(gradient->stops[index].x);
*offset = gradient->stops[index].offset;
if (red)
*red = gradient->stops[index].color.red;
if (green)

Просмотреть файл

@ -108,6 +108,7 @@ typedef struct _word_wrap_stream {
int column;
cairo_bool_t last_write_was_space;
cairo_bool_t in_hexstring;
cairo_bool_t empty_hexstring;
} word_wrap_stream_t;
static int
@ -136,11 +137,15 @@ _count_hexstring_up_to (const unsigned char *s, int length, int columns)
{
int word = 0;
while (length-- && columns--) {
while (length--) {
if (*s++ != '>')
word++;
else
return word;
columns--;
if (columns < 0 && word > 1)
return word;
}
return word;
@ -158,14 +163,19 @@ _word_wrap_stream_write (cairo_output_stream_t *base,
while (length) {
if (*data == '<') {
stream->in_hexstring = TRUE;
stream->empty_hexstring = TRUE;
stream->last_write_was_space = FALSE;
data++;
length--;
_cairo_output_stream_printf (stream->output, "<");
stream->column++;
} else if (*data == '>') {
stream->in_hexstring = FALSE;
stream->last_write_was_space = FALSE;
data++;
length--;
_cairo_output_stream_printf (stream->output, ">");
stream->column++;
} else if (isspace (*data)) {
newline = (*data == '\n' || *data == '\r');
if (! newline && stream->column >= stream->max_column) {
@ -175,8 +185,9 @@ _word_wrap_stream_write (cairo_output_stream_t *base,
_cairo_output_stream_write (stream->output, data, 1);
data++;
length--;
if (newline)
if (newline) {
stream->column = 0;
}
else
stream->column++;
stream->last_write_was_space = TRUE;
@ -189,17 +200,21 @@ _word_wrap_stream_write (cairo_output_stream_t *base,
}
/* Don't wrap if this word is a continuation of a non hex
* string word from a previous call to write. */
if (stream->column + word >= stream->max_column &&
(stream->last_write_was_space || stream->in_hexstring))
{
_cairo_output_stream_printf (stream->output, "\n");
stream->column = 0;
if (stream->column + word >= stream->max_column) {
if (stream->last_write_was_space ||
(stream->in_hexstring && !stream->empty_hexstring))
{
_cairo_output_stream_printf (stream->output, "\n");
stream->column = 0;
}
}
_cairo_output_stream_write (stream->output, data, word);
data += word;
length -= word;
stream->column += word;
stream->last_write_was_space = FALSE;
if (stream->in_hexstring)
stream->empty_hexstring = FALSE;
}
}
@ -236,6 +251,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
stream->column = 0;
stream->last_write_was_space = FALSE;
stream->in_hexstring = FALSE;
stream->empty_hexstring = TRUE;
return &stream->base;
}
@ -259,7 +275,7 @@ _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
info->has_sub_path = FALSE;
cairo_matrix_transform_point (info->path_transform, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f m ", x, y);
"%g %g m ", x, y);
return _cairo_output_stream_get_status (info->output);
}
@ -282,7 +298,7 @@ _cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
info->has_sub_path = TRUE;
cairo_matrix_transform_point (info->path_transform, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f l ", x, y);
"%g %g l ", x, y);
return _cairo_output_stream_get_status (info->output);
}
@ -306,7 +322,7 @@ _cairo_pdf_path_curve_to (void *closure,
cairo_matrix_transform_point (info->path_transform, &cx, &cy);
cairo_matrix_transform_point (info->path_transform, &dx, &dy);
_cairo_output_stream_printf (info->output,
"%f %f %f %f %f %f c ",
"%g %g %g %g %g %g c ",
bx, by, cx, cy, dx, dy);
return _cairo_output_stream_get_status (info->output);
}
@ -339,7 +355,7 @@ _cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
cairo_matrix_transform_point (info->path_transform, &x1, &y1);
cairo_matrix_transform_point (info->path_transform, &x2, &y2);
_cairo_output_stream_printf (info->output,
"%f %f %f %f re ",
"%g %g %g %g re ",
x1, y1, x2 - x1, y2 - y1);
return _cairo_output_stream_get_status (info->output);
@ -355,7 +371,7 @@ _cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
* the stroke workaround will not modify the path being emitted.
*/
static cairo_status_t
_cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
_cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_matrix_t *path_transform,
cairo_line_cap_t line_cap)
@ -365,10 +381,10 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
pdf_path_info_t info;
cairo_box_t box;
word_wrap = _word_wrap_stream_create (pdf_operators->stream, 79);
word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72);
status = _cairo_output_stream_get_status (word_wrap);
if (status)
return status;
return _cairo_output_stream_destroy (word_wrap);
info.output = word_wrap;
info.path_transform = path_transform;
@ -464,7 +480,8 @@ _cairo_pdf_line_join (cairo_line_join_t join)
static cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
cairo_stroke_style_t *style)
cairo_stroke_style_t *style,
double scale)
{
double *dash = style->dash;
int num_dashes = style->num_dashes;
@ -535,7 +552,7 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
_cairo_output_stream_printf (pdf_operators->stream,
"%f w\n",
style->line_width);
style->line_width * scale);
_cairo_output_stream_printf (pdf_operators->stream,
"%d J\n",
@ -550,9 +567,9 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
_cairo_output_stream_printf (pdf_operators->stream, "[");
for (d = 0; d < num_dashes; d++)
_cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d]);
_cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
dash_offset);
dash_offset * scale);
} else {
_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
}
@ -566,6 +583,116 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Scale the matrix so the largest absolute value of the non
* translation components is 1.0. Return the scale required to restore
* the matrix to the original values.
*
* eg the matrix [ 100 0 0 50 20 10 ]
*
* is rescaled to [ 1 0 0 0.5 0.2 0.1 ]
* and the scale returned is 100
*/
static void
_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
{
double s;
s = fabs (m->xx);
if (fabs (m->xy) > s)
s = fabs (m->xy);
if (fabs (m->yx) > s)
s = fabs (m->yx);
if (fabs (m->yy) > s)
s = fabs (m->yy);
*scale = s;
s = 1.0/s;
cairo_matrix_scale (m, s, s);
}
static cairo_int_status_t
_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
const char *pdf_operator)
{
cairo_status_t status;
cairo_matrix_t m, path_transform;
cairo_bool_t has_ctm = TRUE;
double scale = 1.0;
/* Optimize away the stroke ctm when it does not affect the
* stroke. There are other ctm cases that could be optimized
* however this is the most common.
*/
if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 &&
fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0)
{
has_ctm = FALSE;
}
/* The PDF CTM is transformed to the user space CTM when stroking
* so the corect pen shape will be used. This also requires that
* the path be transformed to user space when emitted. The
* conversion of path coordinates to user space may cause rounding
* errors. For example the device space point (1.234, 3.142) when
* transformed to a user space CTM of [100 0 0 100 0 0] will be
* emitted as (0.012, 0.031).
*
* To avoid the rounding problem we scale the user space CTM
* matrix so that all the non translation components of the matrix
* are <= 1. The line width and and dashes are scaled by the
* inverse of the scale applied to the CTM. This maintains the
* shape of the stroke pen while keeping the user space CTM within
* the range that maximizes the precision of the emitted path.
*/
if (has_ctm) {
m = *ctm;
/* Zero out the translation since it does not affect the pen
* shape however it may cause unnecessary digits to be emitted.
*/
m.x0 = 0.0;
m.y0 = 0.0;
_cairo_matrix_factor_out_scale (&m, &scale);
path_transform = m;
status = cairo_matrix_invert (&path_transform);
if (status)
return status;
cairo_matrix_multiply (&m, &m, &pdf_operators->cairo_to_pdf);
}
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style, scale);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
if (has_ctm) {
_cairo_output_stream_printf (pdf_operators->stream,
"q %f %f %f %f %f %f cm\n",
m.xx, m.yx, m.xy, m.yy,
m.x0, m.y0);
} else {
path_transform = pdf_operators->cairo_to_pdf;
}
status = _cairo_pdf_operators_emit_path (pdf_operators,
path,
&path_transform,
style->line_cap);
if (status)
return status;
_cairo_output_stream_printf (pdf_operators->stream, "%s", pdf_operator);
if (has_ctm)
_cairo_output_stream_printf (pdf_operators->stream, " Q");
_cairo_output_stream_printf (pdf_operators->stream, "\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
@ -574,31 +701,12 @@ _cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse)
{
cairo_status_t status;
cairo_matrix_t m;
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
_cairo_output_stream_printf (pdf_operators->stream,
"q %f %f %f %f %f %f cm\n",
m.xx, m.yx, m.xy, m.yy,
m.x0, m.y0);
status = _cairo_pdf_operators_emit_path (pdf_operators,
return _cairo_pdf_operators_emit_stroke (pdf_operators,
path,
style,
ctm,
ctm_inverse,
style->line_cap);
if (status)
return status;
_cairo_output_stream_printf (pdf_operators->stream, "S Q\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
"S");
}
cairo_int_status_t
@ -642,45 +750,25 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse)
{
const char *pdf_operator;
cairo_status_t status;
cairo_matrix_t m;
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
_cairo_output_stream_printf (pdf_operators->stream,
"q %f %f %f %f %f %f cm\n",
m.xx, m.yx, m.xy, m.yy,
m.x0, m.y0);
status = _cairo_pdf_operators_emit_path (pdf_operators,
path,
ctm_inverse,
style->line_cap);
if (status)
return status;
const char *operator;
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
pdf_operator = "B";
operator = "B";
break;
case CAIRO_FILL_RULE_EVEN_ODD:
pdf_operator = "B*";
operator = "B*";
break;
default:
ASSERT_NOT_REACHED;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%s Q\n",
pdf_operator);
return _cairo_output_stream_get_status (pdf_operators->stream);
return _cairo_pdf_operators_emit_stroke (pdf_operators,
path,
style,
ctm,
ctm_inverse,
operator);
}
#define GLYPH_POSITION_TOLERANCE 0.001
@ -703,10 +791,10 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
for (i = 0; i < num_glyphs; i++)
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 79);
word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
status = _cairo_output_stream_get_status (word_wrap_stream);
if (status)
return status;
return _cairo_output_stream_destroy (word_wrap_stream);
_cairo_output_stream_printf (word_wrap_stream,
"BT\n");
@ -799,10 +887,28 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
} else {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
int rounded_delta;
_cairo_output_stream_printf (word_wrap_stream,
"> %f <",
-1000.0*delta/scaled_font->scale.xx);
delta = -1000.0*delta/scaled_font->scale.xx;
/* As the delta is in 1/1000 of a unit of text
* space, rounding to an integer should still
* provide sufficient precision. We round the
* delta before adding to Tm_x so that we keep
* track of the accumulated rounding error in
* the PDF interpreter and compensate for it
* when calculating subsequent deltas.
*/
rounded_delta = _cairo_lround (delta);
if (rounded_delta != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"> %d <",
rounded_delta);
}
/* Convert the rounded delta back to cairo
* space before adding to the current text
* position. */
delta = rounded_delta*scaled_font->scale.xx/-1000.0;
Tm_x += delta;
}
_cairo_output_stream_printf (word_wrap_stream,
@ -817,10 +923,16 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
if (in_TJ) {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
int rounded_delta;
_cairo_output_stream_printf (word_wrap_stream,
"> %f <",
-1000.0*delta/scaled_font->scale.xx);
delta = -1000.0*delta/scaled_font->scale.xx;
rounded_delta = _cairo_lround (delta);
if (rounded_delta != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"> %d <",
rounded_delta);
}
delta = rounded_delta*scaled_font->scale.xx/-1000.0;
Tm_x += delta;
}
_cairo_output_stream_printf (word_wrap_stream,

Просмотреть файл

@ -393,10 +393,15 @@ _extract_pdf_surface (cairo_surface_t *surface,
{
cairo_surface_t *target;
if (surface->status)
return surface->status;
if (! _cairo_surface_is_paginated (surface))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
target = _cairo_paginated_surface_get_target (surface);
if (target->status)
return target->status;
if (! _cairo_surface_is_pdf (target))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
@ -1245,7 +1250,6 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
int i, x, y;
cairo_bool_t opaque;
uint8_t a;
int src_bit, dst_bit;
/* This is the only image format we support, which simplifies things. */
assert (image->format == CAIRO_FORMAT_ARGB32 ||
@ -1255,11 +1259,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
stream_ret->id = 0;
if (image->format == CAIRO_FORMAT_A1) {
/* We allocate using slightly different math so that we can get
* the overflow checking from _cairo_malloc_ab, but alpha_size
* needs to be the correct size for emitting the data in the PDF.
*/
alpha_size = (image->width*image->height + 7) / 8;
alpha_size = (image->width + 7) / 8 * image->height;
alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
} else {
alpha_size = image->height * image->width;
@ -1273,8 +1273,6 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
opaque = TRUE;
i = 0;
src_bit = 0;
dst_bit = 7;
for (y = 0; y < image->height; y++) {
if (image->format == CAIRO_FORMAT_ARGB32) {
pixel32 = (uint32_t *) (image->data + y * image->stride);
@ -1297,21 +1295,12 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
} else { /* image->format == CAIRO_FORMAT_A1 */
pixel8 = (uint8_t *) (image->data + y * image->stride);
for (x = 0; x < image->width; x++, pixel8++) {
if (dst_bit == 7)
alpha[i] = 0;
if ((*pixel8 >> src_bit) & 1) {
opaque = FALSE;
alpha[i] |= (1 << dst_bit);
}
if (++src_bit > 7) {
src_bit = 0;
pixel8++;
}
if (--dst_bit < 0) {
dst_bit = 7;
i++;
}
for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
a = *pixel8;
a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
alpha[i++] = a;
if (a != 0xff)
opaque = FALSE;
}
}
}
@ -1494,8 +1483,9 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
double old_width, old_height;
cairo_matrix_t old_cairo_to_pdf;
cairo_paginated_mode_t old_paginated_mode;
cairo_clip_t *old_clip;
cairo_rectangle_int_t meta_extents;
cairo_status_t status;
cairo_status_t status, status2;
int alpha = 0;
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
@ -1506,6 +1496,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
old_height = surface->height;
old_cairo_to_pdf = surface->cairo_to_pdf;
old_paginated_mode = surface->paginated_mode;
old_clip = _cairo_surface_get_clip (&surface->base);
surface->width = meta_extents.width;
surface->height = meta_extents.height;
/* Patterns are emitted after fallback images. The paginated mode
@ -1548,6 +1539,10 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
surface->height = old_height;
surface->paginated_mode = old_paginated_mode;
surface->cairo_to_pdf = old_cairo_to_pdf;
status2 = _cairo_surface_set_clip (&surface->base, old_clip);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
@ -1981,7 +1976,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
stops[i].color[3] = pattern->stops[i].color.alpha;
if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
emit_alpha = TRUE;
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
stops[i].offset = pattern->stops[i].offset;
}
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
@ -2220,8 +2215,8 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
first_stop = gradient->stops[0].offset;
last_stop = gradient->stops[gradient->n_stops - 1].offset;
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
@ -4148,9 +4143,10 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
if (! _pattern_supported (pattern))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) {
if (op == CAIRO_OPERATOR_OVER) {
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if ( _cairo_surface_is_meta (surface_pattern->surface))
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
}
@ -4165,8 +4161,13 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
surface_pattern);
if (_cairo_surface_is_meta (surface_pattern->surface)) {
if (_cairo_pattern_is_opaque (pattern))
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
} else {
return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
surface_pattern);
}
}
if (_cairo_pattern_is_opaque (pattern))
@ -4536,19 +4537,14 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Fill-stroke with patterns requiring an SMask are not currently
* implemented. Non opaque stroke patterns are not supported
* because the PDF fill-stroke operator does not blend a
* transparent stroke with the fill.
/* PDF rendering of fill-stroke is not the same as cairo when
* either the fill or stroke is not opaque.
*/
if (fill_source->type == CAIRO_PATTERN_TYPE_LINEAR ||
fill_source->type == CAIRO_PATTERN_TYPE_RADIAL)
if ( !_cairo_pattern_is_opaque (fill_source) ||
!_cairo_pattern_is_opaque (stroke_source))
{
if (!_cairo_pattern_is_opaque (fill_source))
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (!_cairo_pattern_is_opaque (stroke_source))
return CAIRO_INT_STATUS_UNSUPPORTED;
}
fill_pattern_res.id = 0;
gstate_res.id = 0;

Просмотреть файл

@ -211,9 +211,8 @@ write_png (cairo_surface_t *surface,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
white.red = 0xff;
white.blue = 0xff;
white.green = 0xff;
white.gray = (1 << depth) - 1;
white.red = white.blue = white.green = white.gray;
png_set_bKGD (png, info, &white);
png_convert_from_time_t (&pt, time (NULL));

Просмотреть файл

@ -180,11 +180,12 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
" {\n"
" dup\n"
" type /stringtype eq\n"
" { show } { -0.0001 mul 0 rmoveto } ifelse\n"
" { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
" } forall\n"
"} bind def\n"
"/Td { moveto } bind def\n"
"/Tm { 6 array astore cairo_font exch selectfont 0 0 moveto } bind def\n"
"/Tm { 6 array astore dup /cairo_font_matrix exch def\n"
" cairo_font exch selectfont 0 0 moveto } bind def\n"
"/g { setgray } bind def\n"
"/rg { setrgbcolor } bind def\n");
@ -858,10 +859,15 @@ _extract_ps_surface (cairo_surface_t *surface,
{
cairo_surface_t *target;
if (surface->status)
return surface->status;
if (! _cairo_surface_is_paginated (surface))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
target = _cairo_paginated_surface_get_target (surface);
if (target->status)
return target->status;
if (! _cairo_surface_is_ps (target))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
@ -2029,6 +2035,7 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
double old_width, old_height;
cairo_matrix_t old_cairo_to_ps;
cairo_content_t old_content;
cairo_clip_t *old_clip;
cairo_rectangle_int_t meta_extents;
cairo_status_t status;
@ -2040,6 +2047,7 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
old_width = surface->width;
old_height = surface->height;
old_cairo_to_ps = surface->cairo_to_ps;
old_clip = _cairo_surface_get_clip (&surface->base);
surface->width = meta_extents.width;
surface->height = meta_extents.height;
cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
@ -2071,6 +2079,10 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
surface->width = old_width;
surface->height = old_height;
surface->cairo_to_ps = old_cairo_to_ps;
status = _cairo_surface_set_clip (&surface->base, old_clip);
if (status)
return status;
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_ps);
@ -2135,17 +2147,23 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
cairo_rectangle_int_t pattern_extents;
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
if (status)
return status;
*width = pattern_extents.width;
*height = pattern_extents.height;
} else {
status = _cairo_surface_acquire_source_image (pattern->surface,
&surface->image,
&surface->image_extra);
if (status)
return status;
*width = surface->image->width;
*height = surface->image->height;
}
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -2206,6 +2224,14 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
(int)(height/scale),
scale*72,
(long)width*height*3);
} else {
if (op == CAIRO_OPERATOR_SOURCE) {
_cairo_output_stream_printf (surface->stream,
"%d g 0 0 %f %f rectfill\n",
surface->content == CAIRO_CONTENT_COLOR ? 0 : 1,
surface->width,
surface->height);
}
}
status = cairo_matrix_invert (&cairo_p2d);
@ -2312,6 +2338,12 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
old_use_string_datasource = surface->use_string_datasource;
surface->use_string_datasource = TRUE;
if (op == CAIRO_OPERATOR_SOURCE) {
_cairo_output_stream_printf (surface->stream,
"%d g 0 0 %f %f rectfill\n",
surface->content == CAIRO_CONTENT_COLOR ? 0 : 1,
xstep, ystep);
}
status = _cairo_ps_surface_emit_surface (surface, pattern, op);
if (status)
return status;
@ -2343,10 +2375,17 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
pattern_height*2,
pattern_width*2);
} else {
if (op == CAIRO_OPERATOR_SOURCE) {
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %f %f]\n",
xstep, ystep);
} else {
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %d %d]\n",
pattern_width, pattern_height);
}
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %d %d]\n"
" /PaintProc { CairoPattern }\n",
pattern_width, pattern_height);
" /PaintProc { CairoPattern }\n");
}
_cairo_output_stream_printf (surface->stream,
@ -2466,7 +2505,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
stops[i].color[1] = stop->color.green;
stops[i].color[2] = stop->color.blue;
stops[i].color[3] = stop->color.alpha;
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
stops[i].offset = pattern->stops[i].offset;
}
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
@ -2585,8 +2624,8 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
first_stop = gradient->stops[0].offset;
last_stop = gradient->stops[gradient->n_stops - 1].offset;
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
@ -2861,7 +2900,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_rectangle_int_t extents, surface_extents;
cairo_rectangle_int_t extents;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -2874,22 +2913,15 @@ _cairo_ps_surface_paint (void *abstract_surface,
"%% _cairo_ps_surface_paint\n");
#endif
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
status = _cairo_pattern_get_extents (source, &extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &surface_extents);
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
{
_cairo_output_stream_printf (stream, "q %d %d %d %d rectclip\n",
extents.x,
surface_extents.height - extents.y - extents.height,
_cairo_output_stream_printf (stream, "q 0 0 %d %d rectclip\n",
extents.width,
extents.height);
@ -2908,9 +2940,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
if (status)
return status;
_cairo_output_stream_printf (stream, "%d %d %d %d rectfill\n",
extents.x,
surface_extents.height - extents.y - extents.height,
_cairo_output_stream_printf (stream, "0 0 %d %d rectfill\n",
extents.width,
extents.height);
}
@ -2976,7 +3006,8 @@ _cairo_ps_surface_fill (void *abstract_surface,
#endif
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
{
_cairo_output_stream_printf (surface->stream, "q\n");

Просмотреть файл

@ -0,0 +1,794 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright <EFBFBD> 2008 Mozilla Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@mozilla.com>
*/
#include "cairoint.h"
#include <dlfcn.h>
#include "cairo-quartz.h"
#include "cairo-quartz-private.h"
/* CreateWithFontName exists in 10.5, but not in 10.4; CreateWithName isn't public in 10.4 */
static CGFontRef (*CGFontCreateWithFontNamePtr) (CFStringRef) = NULL;
static CGFontRef (*CGFontCreateWithNamePtr) (const char *) = NULL;
/* These aren't public before 10.5, and some have different names in 10.4 */
static int (*CGFontGetUnitsPerEmPtr) (CGFontRef) = NULL;
static bool (*CGFontGetGlyphAdvancesPtr) (CGFontRef, const CGGlyph[], size_t, int[]) = NULL;
static bool (*CGFontGetGlyphBBoxesPtr) (CGFontRef, const CGGlyph[], size_t, CGRect[]) = NULL;
static CGRect (*CGFontGetFontBBoxPtr) (CGFontRef) = NULL;
/* Not public, but present */
static void (*CGFontGetGlyphsForUnicharsPtr) (CGFontRef, const UniChar[], const CGGlyph[], size_t) = NULL;
/* Not public in the least bit */
static CGPathRef (*CGFontGetGlyphPathPtr) (CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph) = NULL;
/* CGFontGetHMetrics isn't public, but the other functions are public/present in 10.5 */
typedef struct {
int ascent;
int descent;
int leading;
} quartz_CGFontMetrics;
static quartz_CGFontMetrics* (*CGFontGetHMetricsPtr) (CGFontRef fontRef) = NULL;
static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL;
static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL;
static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL;
static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
static void
quartz_font_ensure_symbols(void)
{
if (_cairo_quartz_font_symbol_lookup_done)
return;
/* Look for the 10.5 versions first */
CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBBoxes");
if (!CGFontGetGlyphBBoxesPtr)
CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBoundingBoxes");
CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars");
if (!CGFontGetGlyphsForUnicharsPtr)
CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes");
CGFontGetFontBBoxPtr = dlsym(RTLD_DEFAULT, "CGFontGetFontBBox");
/* We just need one of these two */
CGFontCreateWithFontNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithFontName");
CGFontCreateWithNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithName");
/* These have the same name in 10.4 and 10.5 */
CGFontGetUnitsPerEmPtr = dlsym(RTLD_DEFAULT, "CGFontGetUnitsPerEm");
CGFontGetGlyphAdvancesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphAdvances");
CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath");
CGFontGetHMetricsPtr = dlsym(RTLD_DEFAULT, "CGFontGetHMetrics");
CGFontGetAscentPtr = dlsym(RTLD_DEFAULT, "CGFontGetAscent");
CGFontGetDescentPtr = dlsym(RTLD_DEFAULT, "CGFontGetDescent");
CGFontGetLeadingPtr = dlsym(RTLD_DEFAULT, "CGFontGetLeading");
if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
CGFontGetGlyphBBoxesPtr &&
CGFontGetGlyphsForUnicharsPtr &&
CGFontGetUnitsPerEmPtr &&
CGFontGetGlyphAdvancesPtr &&
CGFontGetGlyphPathPtr &&
(CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr)))
_cairo_quartz_font_symbols_present = TRUE;
_cairo_quartz_font_symbol_lookup_done = TRUE;
}
typedef struct _cairo_quartz_font_face cairo_quartz_font_face_t;
typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t;
struct _cairo_quartz_scaled_font {
cairo_scaled_font_t base;
};
struct _cairo_quartz_font_face {
cairo_font_face_t base;
CGFontRef cgFont;
};
/**
** font face backend
**/
static void
_cairo_quartz_font_face_destroy (void *abstract_face)
{
cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
CGFontRelease (font_face->cgFont);
}
static cairo_status_t
_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **font_out)
{
cairo_quartz_font_face_t *font_face = abstract_face;
cairo_quartz_scaled_font_t *font = NULL;
cairo_status_t status;
cairo_font_extents_t fs_metrics;
double ems;
CGRect bbox;
quartz_font_ensure_symbols();
if (!_cairo_quartz_font_symbols_present)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font = malloc(sizeof(cairo_quartz_scaled_font_t));
if (font == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memset (font, 0, sizeof(cairo_quartz_scaled_font_t));
status = _cairo_scaled_font_init (&font->base,
&font_face->base, font_matrix, ctm, options,
&cairo_quartz_scaled_font_backend);
if (status)
goto FINISH;
ems = CGFontGetUnitsPerEmPtr (font_face->cgFont);
/* initialize metrics */
if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) {
fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems);
fs_metrics.descent = - (CGFontGetDescentPtr (font_face->cgFont) / ems);
fs_metrics.height = fs_metrics.ascent + fs_metrics.descent +
(CGFontGetLeadingPtr (font_face->cgFont) / ems);
bbox = CGFontGetFontBBoxPtr (font_face->cgFont);
fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems;
fs_metrics.max_y_advance = 0.0;
} else {
CGGlyph wGlyph;
UniChar u;
quartz_CGFontMetrics *m;
m = CGFontGetHMetricsPtr (font_face->cgFont);
fs_metrics.ascent = (m->ascent / ems);
fs_metrics.descent = - (m->descent / ems);
fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems);
/* We kind of have to guess here; W's big, right? */
u = (UniChar) 'W';
CGFontGetGlyphsForUnicharsPtr (font_face->cgFont, &u, &wGlyph, 1);
if (wGlyph && CGFontGetGlyphBBoxesPtr (font_face->cgFont, &wGlyph, 1, &bbox)) {
fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems;
fs_metrics.max_y_advance = 0.0;
} else {
fs_metrics.max_x_advance = 0.0;
fs_metrics.max_y_advance = 0.0;
}
}
status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics);
FINISH:
if (status != CAIRO_STATUS_SUCCESS) {
free (font);
} else {
*font_out = (cairo_scaled_font_t*) font;
}
return status;
}
static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
CAIRO_FONT_TYPE_QUARTZ,
_cairo_quartz_font_face_destroy,
_cairo_quartz_font_face_scaled_font_create
};
/**
* cairo_quartz_font_face_create_for_cgfont
* @font: a #CGFontRef obtained through a method external to cairo.
*
* Creates a new font for the Quartz font backend based on a
* #CGFontRef. This font can then be used with
* cairo_set_font_face() or cairo_scaled_font_create().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
*
* Since: 1.6
*/
cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
{
cairo_quartz_font_face_t *font_face;
quartz_font_ensure_symbols();
font_face = malloc (sizeof (cairo_quartz_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
font_face->cgFont = CGFontRetain (font);
_cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
return &font_face->base;
}
/**
** scaled font backend
**/
static cairo_quartz_font_face_t *
_cairo_quartz_scaled_to_face (void *abstract_font)
{
cairo_quartz_scaled_font_t *sfont = (cairo_quartz_scaled_font_t*) abstract_font;
cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (&sfont->base);
if (!font_face || font_face->backend->type != CAIRO_FONT_TYPE_QUARTZ)
return NULL;
return (cairo_quartz_font_face_t*) font_face;
}
static cairo_status_t
_cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **font_out)
{
const char *family = toy_face->family;
char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
CFStringRef cgFontName = NULL;
CGFontRef cgFont = NULL;
int loop;
cairo_status_t status;
cairo_font_face_t *face;
cairo_scaled_font_t *scaled_font;
quartz_font_ensure_symbols();
if (!_cairo_quartz_font_symbols_present)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* handle CSS-ish faces */
if (!strcmp(family, "serif") || !strcmp(family, "Times Roman"))
family = "Times";
else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans"))
family = "Helvetica";
else if (!strcmp(family, "cursive"))
family = "Apple Chancery";
else if (!strcmp(family, "fantasy"))
family = "Papyrus";
else if (!strcmp(family, "monospace") || !strcmp(family, "mono"))
family = "Courier";
/* Try to build up the full name, e.g. "Helvetica Bold Oblique" first,
* then drop the bold, then drop the slant, then drop both.. finally
* just use "Helvetica". And if Helvetica doesn't exist, give up.
*/
for (loop = 0; loop < 5; loop++) {
if (loop == 4)
family = "Helvetica";
strcpy (full_name, family);
if (loop < 3 && (loop & 1) == 0) {
if (toy_face->weight == CAIRO_FONT_WEIGHT_BOLD)
strcat (full_name, " Bold");
}
if (loop < 3 && (loop & 2) == 0) {
if (toy_face->slant == CAIRO_FONT_SLANT_ITALIC)
strcat (full_name, " Italic");
else if (toy_face->slant == CAIRO_FONT_SLANT_OBLIQUE)
strcat (full_name, " Oblique");
}
if (CGFontCreateWithFontNamePtr) {
cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
cgFont = CGFontCreateWithFontNamePtr (cgFontName);
CFRelease (cgFontName);
} else {
cgFont = CGFontCreateWithNamePtr (full_name);
}
if (cgFont)
break;
}
if (!cgFont) {
/* Give up */
return CAIRO_STATUS_NO_MEMORY;
}
face = cairo_quartz_font_face_create_for_cgfont (cgFont);
if (face->status)
return face->status;
status = _cairo_quartz_font_face_scaled_font_create (face,
font_matrix, ctm,
options,
&scaled_font);
cairo_font_face_destroy (face);
if (status)
return status;
*font_out = scaled_font;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_quartz_font_fini(void *abstract_font)
{
}
#define INVALID_GLYPH 0x00
static inline CGGlyph
_cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
if (index > 0xffff)
return INVALID_GLYPH;
return (CGGlyph) index;
}
static inline cairo_status_t
_cairo_matrix_to_unit_quartz_matrix (const cairo_matrix_t *m, CGAffineTransform *txout,
double *xout, double *yout)
{
CGAffineTransform transform;
double xscale, yscale;
cairo_status_t status;
status = _cairo_matrix_compute_scale_factors (m, &xscale, &yscale, 1);
if (status)
return status;
transform = CGAffineTransformMake (m->xx, - m->yx,
- m->xy, m->yy,
0.0f, 0.0f);
if (xout)
*xout = xscale;
if (yout)
*yout = yscale;
if (xscale)
xscale = 1.0 / xscale;
if (yscale)
yscale = 1.0 / yscale;
*txout = CGAffineTransformScale (transform, xscale, yscale);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
CGAffineTransform textMatrix;
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
int advance;
CGRect bbox;
double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
double xscale, yscale;
double xmin, ymin, xmax, ymax;
if (glyph == INVALID_GLYPH)
goto FAIL;
if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
goto FAIL;
status = _cairo_matrix_compute_scale_factors (&font->base.scale,
&xscale, &yscale, 1);
if (status)
goto FAIL;
bbox = CGRectMake (bbox.origin.x / emscale,
bbox.origin.y / emscale,
bbox.size.width / emscale,
bbox.size.height / emscale);
/* Should we want to always integer-align glyph extents, we can do so in this way */
#if 0
{
CGAffineTransform textMatrix;
textMatrix = CGAffineTransformMake (font->base.scale.xx,
-font->base.scale.yx,
-font->base.scale.xy,
font->base.scale.yy,
0.0f, 0.0f);
bbox = CGRectApplyAffineTransform (bbox, textMatrix);
bbox = CGRectIntegral (bbox);
bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix));
}
#endif
#if 0
fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph,
bbox.origin.x / emscale, bbox.origin.y / emscale,
bbox.size.width / emscale, bbox.size.height / emscale);
#endif
xmin = CGRectGetMinX(bbox);
ymin = CGRectGetMinY(bbox);
xmax = CGRectGetMaxX(bbox);
ymax = CGRectGetMaxY(bbox);
extents.x_bearing = xmin;
extents.y_bearing = - ymax;
extents.width = xmax - xmin;
extents.height = ymax - ymin;
extents.x_advance = (double) advance / emscale;
extents.y_advance = 0.0;
#if 0
fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph,
extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance);
#endif
FAIL:
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&font->base,
&extents);
return status;
}
static void
_cairo_quartz_path_apply_func (void *info, const CGPathElement *el)
{
cairo_path_fixed_t *path = (cairo_path_fixed_t *) info;
switch (el->type) {
case kCGPathElementMoveToPoint:
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_double(el->points[0].x),
_cairo_fixed_from_double(el->points[0].y));
break;
case kCGPathElementAddLineToPoint:
_cairo_path_fixed_line_to (path,
_cairo_fixed_from_double(el->points[0].x),
_cairo_fixed_from_double(el->points[0].y));
break;
case kCGPathElementAddQuadCurveToPoint: {
cairo_fixed_t fx, fy;
double x, y;
if (!_cairo_path_fixed_get_current_point (path, &fx, &fy))
fx = fy = 0;
x = _cairo_fixed_to_double (fx);
y = _cairo_fixed_to_double (fy);
_cairo_path_fixed_curve_to (path,
_cairo_fixed_from_double((x + el->points[0].x * 2.0) / 3.0),
_cairo_fixed_from_double((y + el->points[0].y * 2.0) / 3.0),
_cairo_fixed_from_double((el->points[0].x * 2.0 + el->points[1].x) / 3.0),
_cairo_fixed_from_double((el->points[0].y * 2.0 + el->points[1].y) / 3.0),
_cairo_fixed_from_double(el->points[1].x),
_cairo_fixed_from_double(el->points[1].y));
}
break;
case kCGPathElementAddCurveToPoint:
_cairo_path_fixed_curve_to (path,
_cairo_fixed_from_double(el->points[0].x),
_cairo_fixed_from_double(el->points[0].y),
_cairo_fixed_from_double(el->points[1].x),
_cairo_fixed_from_double(el->points[1].y),
_cairo_fixed_from_double(el->points[2].x),
_cairo_fixed_from_double(el->points[2].y));
break;
case kCGPathElementCloseSubpath:
_cairo_path_fixed_close_path (path);
break;
}
}
static cairo_int_status_t
_cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
CGAffineTransform textMatrix;
CGPathRef glyphPath;
cairo_path_fixed_t *path;
if (glyph == INVALID_GLYPH) {
_cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create());
return CAIRO_STATUS_SUCCESS;
}
textMatrix = CGAffineTransformMake (font->base.scale.xx,
-font->base.scale.yx,
-font->base.scale.xy,
font->base.scale.yy,
font->base.scale.x0,
font->base.scale.y0);
textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph);
if (!glyphPath)
return CAIRO_INT_STATUS_UNSUPPORTED;
path = _cairo_path_fixed_create ();
if (!path) {
CGPathRelease (glyphPath);
return _cairo_error(CAIRO_STATUS_NO_MEMORY);
}
CGPathApply (glyphPath, path, _cairo_quartz_path_apply_func);
CGPathRelease (glyphPath);
_cairo_scaled_glyph_set_path (scaled_glyph, &font->base, path);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
cairo_image_surface_t *surface = NULL;
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
int advance;
CGRect bbox;
double width, height;
double xscale, yscale;
double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
CGColorSpaceRef gray;
CGContextRef cgContext = NULL;
CGAffineTransform textMatrix;
CGRect glyphRect, glyphRectInt;
CGPoint glyphOrigin;
//fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);
/* Create blank 2x2 image if we don't have this character.
* Maybe we should draw a better missing-glyph slug or something,
* but this is ok for now.
*/
if (glyph == INVALID_GLYPH) {
surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
status = cairo_surface_status ((cairo_surface_t *) surface);
if (status)
return status;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&font->base,
surface);
return CAIRO_STATUS_SUCCESS;
}
if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
status = _cairo_matrix_compute_scale_factors (&font->base.scale,
&xscale, &yscale, 1);
if (status)
return status;
textMatrix = CGAffineTransformMake (font->base.scale.xx,
-font->base.scale.yx,
-font->base.scale.xy,
font->base.scale.yy,
0.0f, 0.0f);
glyphRect = CGRectMake (bbox.origin.x / emscale,
bbox.origin.y / emscale,
bbox.size.width / emscale,
bbox.size.height / emscale);
glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);
/* Round the rectangle outwards, so that we don't have to deal
* with non-integer-pixel origins or dimensions.
*/
glyphRectInt = CGRectIntegral (glyphRect);
#if 0
fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
fprintf (stderr, "glyphRectInt: %f %f %f %f\n",
glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height);
#endif
glyphOrigin = glyphRectInt.origin;
//textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));
width = glyphRectInt.size.width;
height = glyphRectInt.size.height;
//fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
if (surface->base.status)
return surface->base.status;
gray = CGColorSpaceCreateDeviceGray ();
cgContext = CGBitmapContextCreate (surface->data,
surface->width,
surface->height,
8,
surface->stride,
gray,
kCGImageAlphaNone);
CGColorSpaceRelease (gray);
CGContextSetFont (cgContext, font_face->cgFont);
CGContextSetFontSize (cgContext, 1.0);
CGContextSetTextMatrix (cgContext, textMatrix);
CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height));
if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE)
CGContextSetShouldAntialias (cgContext, false);
CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0);
CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1);
CGContextRelease (cgContext);
cairo_surface_set_device_offset (&surface->base,
- glyphOrigin.x,
height + glyphOrigin.y);
_cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);
return status;
}
static cairo_int_status_t
_cairo_quartz_font_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_info_t info)
{
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t *) abstract_font;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
if (!status && (info & CAIRO_SCALED_GLYPH_INFO_METRICS))
status = _cairo_quartz_init_glyph_metrics (font, scaled_glyph);
if (!status && (info & CAIRO_SCALED_GLYPH_INFO_PATH))
status = _cairo_quartz_init_glyph_path (font, scaled_glyph);
if (!status && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE))
status = _cairo_quartz_init_glyph_surface (font, scaled_glyph);
return status;
}
static unsigned long
_cairo_quartz_ucs4_to_index (void *abstract_font,
uint32_t ucs4)
{
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font;
cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font);
UniChar u = (UniChar) ucs4;
CGGlyph glyph;
CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1);
return glyph;
}
const cairo_scaled_font_backend_t cairo_quartz_scaled_font_backend = {
CAIRO_FONT_TYPE_QUARTZ,
_cairo_quartz_font_create_toy,
_cairo_quartz_font_fini,
_cairo_quartz_font_scaled_glyph_init,
NULL, /* text_to_glyphs */
_cairo_quartz_ucs4_to_index,
NULL, /* show_glyphs */
NULL, /* load_truetype_table */
NULL, /* map_glyphs_to_unicode */
};
/*
* private methods that the quartz surface uses
*/
CGFontRef
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
{
cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
return ffont->cgFont;
}
/*
* compat with old ATSUI backend
*/
/**
* cairo_quartz_font_face_create_for_atsu_font_id
* @font_id: an ATSUFontID for the font.
*
* Creates a new font for the Quartz font backend based on an
* #ATSUFontID. This font can then be used with
* cairo_set_font_face() or cairo_scaled_font_create().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
*
* Since: 1.6
**/
cairo_font_face_t *
cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id)
{
ATSFontRef atsFont = FMGetATSFontRefFromFont (font_id);
CGFontRef cgFont = CGFontCreateWithPlatformFont (&atsFont);
return cairo_quartz_font_face_create_for_cgfont (cgFont);
}
/* This is the old name for the above function, exported for compat purposes */
cairo_font_face_t *cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id);
cairo_font_face_t *
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
{
return cairo_quartz_font_face_create_for_atsu_font_id (font_id);
}

Просмотреть файл

@ -92,17 +92,14 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
CGDataProviderReleaseDataCallback releaseCallback,
void *releaseInfo);
CGFontRef
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
#if CAIRO_HAS_ATSUI_FONT
ATSUStyle
_cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont);
ATSUFontID
_cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont);
#if CAIRO_HAS_CGFONT_FONT
CGFontRef
_cairo_atsui_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
#endif /* CAIRO_HAS_ATSUI_FONT */
_cairo_cgfont_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
#endif /* CAIRO_HAS_CGFONT_FONT */
#endif /* CAIRO_QUARTZ_PRIVATE_H */

Просмотреть файл

@ -48,7 +48,6 @@
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
#endif
#include <Carbon/Carbon.h>
#include <limits.h>
#undef QUARTZ_DEBUG
@ -102,13 +101,14 @@ CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
#endif
/* Only present in 10.4+ */
/* Some of these are present in earlier versions of the OS than where
* they are public; others are not public at all (CGContextCopyPath,
* CGContextReplacePathWithClipPath, many of the getters, etc.)
*/
static void (*CGContextClipToMaskPtr) (CGContextRef, CGRect, CGImageRef) = NULL;
/* Only present in 10.5+ */
static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL;
static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL;
static void (*CGContextSetShouldAntialiasFontsPtr) (CGContextRef, bool) = NULL;
static void (*CGContextSetShouldSmoothFontsPtr) (CGContextRef, bool) = NULL;
static bool (*CGContextGetShouldAntialiasFontsPtr) (CGContextRef) = NULL;
static bool (*CGContextGetShouldSmoothFontsPtr) (CGContextRef) = NULL;
static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
@ -116,6 +116,8 @@ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL;
static void (*CGContextReplacePathWithClipPathPtr) (CGContextRef) = NULL;
static SInt32 _cairo_quartz_osx_version = 0x0;
static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
/*
@ -143,7 +145,6 @@ static void quartz_ensure_symbols(void)
CGContextDrawTiledImagePtr = dlsym(RTLD_DEFAULT, "CGContextDrawTiledImage");
CGContextGetTypePtr = dlsym(RTLD_DEFAULT, "CGContextGetType");
CGContextSetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldAntialiasFonts");
CGContextSetShouldSmoothFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldSmoothFonts");
CGContextGetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldAntialiasFonts");
CGContextGetShouldSmoothFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldSmoothFonts");
CGContextCopyPathPtr = dlsym(RTLD_DEFAULT, "CGContextCopyPath");
@ -151,6 +152,11 @@ static void quartz_ensure_symbols(void)
CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) {
// assume 10.4
_cairo_quartz_osx_version = 0x1040;
}
_cairo_quartz_symbol_lookup_done = TRUE;
}
@ -479,6 +485,10 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
if (op->u.show_glyphs.isClipping) {
/* Note that the comment in show_glyphs about kCGTextClip
* and the text transform still applies here; however, the
* cg_advances we have were already transformed, so we
* don't have to do anything. */
CGContextSetTextDrawingMode (cgc, kCGTextClip);
CGContextSaveGState (cgc);
}
@ -540,7 +550,6 @@ static void
ComputeGradientValue (void *info, const float *in, float *out)
{
double fdist = *in;
cairo_fixed_t fdist_fix;
cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
unsigned int i;
@ -556,10 +565,8 @@ ComputeGradientValue (void *info, const float *in, float *out)
}
}
fdist_fix = _cairo_fixed_from_double(fdist);
for (i = 0; i < grad->n_stops; i++) {
if (grad->stops[i].x > fdist_fix)
if (grad->stops[i].offset > fdist)
break;
}
@ -571,8 +578,8 @@ ComputeGradientValue (void *info, const float *in, float *out)
out[2] = grad->stops[i].color.blue;
out[3] = grad->stops[i].color.alpha;
} else {
float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
float ax = grad->stops[i-1].offset;
float bx = grad->stops[i].offset - ax;
float bp = (fdist - ax)/bx;
float ap = 1.0 - bp;
@ -1731,7 +1738,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
cairo_quartz_action_t action;
quartz_stroke_t stroke;
CGAffineTransform strokeTransform;
CGAffineTransform origCTM, strokeTransform;
CGPathRef path_for_unbounded = NULL;
ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
@ -1752,6 +1759,9 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
origCTM = CGContextGetCTM (surface->cgContext);
_cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
CGContextConcatCTM (surface->cgContext, strokeTransform);
@ -1798,6 +1808,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
CGContextReplacePathWithStrokedPath (surface->cgContext);
CGContextClip (surface->cgContext);
CGContextSetCTM (surface->cgContext, origCTM);
CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
CGContextScaleCTM (surface->cgContext, 1, -1);
@ -1810,6 +1822,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
CGContextReplacePathWithStrokedPath (surface->cgContext);
CGContextClip (surface->cgContext);
CGContextSetCTM (surface->cgContext, origCTM);
CGContextConcatCTM (surface->cgContext, surface->sourceTransform);
CGContextDrawShading (surface->cgContext, surface->sourceShading);
} else if (action != DO_NOTHING) {
@ -1854,7 +1868,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
return rv;
}
#if CAIRO_HAS_ATSUI_FONT
#if CAIRO_HAS_QUARTZ_FONT
static cairo_int_status_t
_cairo_quartz_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
@ -1889,7 +1903,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
if (op == CAIRO_OPERATOR_DEST)
return CAIRO_STATUS_SUCCESS;
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_ATSUI)
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ)
return CAIRO_INT_STATUS_UNSUPPORTED;
CGContextSaveGState (surface->cgContext);
@ -1909,33 +1923,31 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
/* this doesn't addref */
cgfref = _cairo_atsui_scaled_font_get_cg_font_ref (scaled_font);
cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font);
CGContextSetFont (surface->cgContext, cgfref);
CGContextSetFontSize (surface->cgContext, 1.0);
if (CGContextSetShouldAntialiasFontsPtr) {
switch (scaled_font->options.antialias) {
case CAIRO_ANTIALIAS_SUBPIXEL:
CGContextSetShouldAntialiasFontsPtr (surface->cgContext, TRUE);
CGContextSetShouldSmoothFontsPtr (surface->cgContext, TRUE);
if (CGContextSetAllowsFontSmoothingPtr &&
!CGContextGetAllowsFontSmoothingPtr (surface->cgContext))
{
didForceFontSmoothing = TRUE;
CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE);
}
break;
case CAIRO_ANTIALIAS_NONE:
CGContextSetShouldAntialiasFontsPtr (surface->cgContext, FALSE);
break;
case CAIRO_ANTIALIAS_GRAY:
CGContextSetShouldAntialiasFontsPtr (surface->cgContext, TRUE);
CGContextSetShouldSmoothFontsPtr (surface->cgContext, FALSE);
break;
case CAIRO_ANTIALIAS_DEFAULT:
/* Don't do anything */
break;
}
switch (scaled_font->options.antialias) {
case CAIRO_ANTIALIAS_SUBPIXEL:
CGContextSetShouldAntialias (surface->cgContext, TRUE);
CGContextSetShouldSmoothFonts (surface->cgContext, TRUE);
if (CGContextSetAllowsFontSmoothingPtr &&
!CGContextGetAllowsFontSmoothingPtr (surface->cgContext))
{
didForceFontSmoothing = TRUE;
CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE);
}
break;
case CAIRO_ANTIALIAS_NONE:
CGContextSetShouldAntialias (surface->cgContext, FALSE);
break;
case CAIRO_ANTIALIAS_GRAY:
CGContextSetShouldAntialias (surface->cgContext, TRUE);
CGContextSetShouldSmoothFonts (surface->cgContext, FALSE);
break;
case CAIRO_ANTIALIAS_DEFAULT:
/* Don't do anything */
break;
}
if (num_glyphs > STATIC_BUF_SIZE) {
@ -1984,10 +1996,13 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
yprev = yf;
}
if (isClipping) {
/* If we're clipping, we get multiplied by the inverse of our text matrix; no,
* I don't understand why this is any different. So pre-apply our textTransform.
* Note that the new CGContextShowGlyphsAtPositions has a similar problem. */
if (_cairo_quartz_osx_version >= 0x1050 && isClipping) {
/* If we're clipping, OSX 10.5 (at least as of 10.5.2) has a
* bug (apple bug ID #5834794) where the glyph
* advances/positions are not transformed by the text matrix
* if kCGTextClip is being used. So, we pre-transform here.
* 10.4 does not have this problem (as of 10.4.11).
*/
for (i = 0; i < num_glyphs - 1; i++)
cg_advances[i] = CGSizeApplyAffineTransform(cg_advances[i], textTransform);
}
@ -2060,7 +2075,7 @@ BAIL:
return rv;
}
#endif /* CAIRO_HAS_ATSUI_FONT */
#endif /* CAIRO_HAS_QUARTZ_FONT */
static cairo_int_status_t
_cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
@ -2293,11 +2308,11 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
_cairo_quartz_surface_mask,
_cairo_quartz_surface_stroke,
_cairo_quartz_surface_fill,
#if CAIRO_HAS_ATSUI_FONT
#if CAIRO_HAS_QUARTZ_FONT
_cairo_quartz_surface_show_glyphs,
#else
NULL, /* surface_show_glyphs */
#endif /* CAIRO_HAS_ATSUI_FONT */
NULL, /* show_glyphs */
#endif
NULL, /* snapshot */
NULL, /* is_similar */
@ -2358,22 +2373,20 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
* @height: height of the surface, in pixels
*
* Creates a Quartz surface that wraps the given CGContext. The
* CGContext is assumed to be in the QuickDraw coordinate space (that
* is, with the origin at the upper left and the Y axis increasing
* downward.) If the CGContext is in the Quartz coordinate space (with
* the origin at the bottom left), then it should be flipped before
* this function is called:
* CGContext is assumed to be in the standard Cairo coordinate space
* (that is, with the origin at the upper left and the Y axis
* increasing downward). If the CGContext is in the Quartz coordinate
* space (with the origin at the bottom left), then it should be
* flipped before this function is called. The flip can be accomplished
* using a translate and a scale; for example:
*
* <informalexample><programlisting>
* CGContextTranslateCTM (cgContext, 0.0, height);
* CGContextScaleCTM (cgContext, 1.0, -1.0);
* </programlisting></informalexample>
*
* A very small number of Cairo operations cannot be translated to
* Quartz operations; those operations will fail on this surface.
* If all Cairo operations are required to succeed, consider rendering
* to a surface created by cairo_quartz_surface_create() and then copying
* the result to the CGContext.
* All Cairo operations are implemented in terms of Quartz operations,
* as long as Quartz-compatible elements are used (such as Quartz fonts).
*
* Return value: the newly created Cairo surface.
*

Просмотреть файл

@ -40,7 +40,7 @@
#if CAIRO_HAS_QUARTZ_SURFACE
#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
CAIRO_BEGIN_DECLS
@ -57,10 +57,26 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
cairo_public CGContextRef
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
/*
* Quartz font support
*/
#ifdef CAIRO_HAS_QUARTZ_FONT
cairo_public cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
cairo_public cairo_font_face_t *
cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id);
#endif /* CAIRO_HAS_QUARTZ_FONT */
CAIRO_END_DECLS
#else /* CAIRO_HAS_QUARTZ_SURFACE */
#else
# error Cairo was not compiled with support for the quartz backend
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
#endif /* CAIRO_QUARTZ_H */

Просмотреть файл

@ -108,7 +108,7 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *
cairo_bool_t
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line)
{
cairo_fixed_t t1, t2, t3, t4;
cairo_fixed_t t1=0, t2=0, t3=0, t4=0;
cairo_int64_t t1y, t2y, t3x, t4x;
cairo_fixed_t xlen, ylen;

Просмотреть файл

@ -1151,9 +1151,9 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
if (rects[i].y < y1)
y1 = rects[i].y;
if (rects[i].x + rects[i].width > x2)
if ((int)(rects[i].x + rects[i].width) > x2)
x2 = rects[i].x + rects[i].width;
if (rects[i].y + rects[i].height > y2)
if ((int)(rects[i].y + rects[i].height) > y2)
y2 = rects[i].y + rects[i].height;
}

Просмотреть файл

@ -1985,6 +1985,12 @@ _cairo_surface_set_empty_clip_path (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
cairo_clip_t *
_cairo_surface_get_clip (cairo_surface_t *surface)
{
return surface->clip;
}
cairo_status_t
_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
{
@ -2487,6 +2493,24 @@ _cairo_surface_create_in_error (cairo_status_t status)
return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
case CAIRO_STATUS_INVALID_STRIDE:
return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
case CAIRO_STATUS_SUCCESS:
ASSERT_NOT_REACHED;
/* fall-through */
case CAIRO_STATUS_INVALID_RESTORE:
case CAIRO_STATUS_INVALID_POP_GROUP:
case CAIRO_STATUS_NO_CURRENT_POINT:
case CAIRO_STATUS_INVALID_MATRIX:
case CAIRO_STATUS_INVALID_STATUS:
case CAIRO_STATUS_NULL_POINTER:
case CAIRO_STATUS_INVALID_STRING:
case CAIRO_STATUS_INVALID_PATH_DATA:
case CAIRO_STATUS_SURFACE_FINISHED:
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_DASH:
case CAIRO_STATUS_INVALID_DSC_COMMENT:
case CAIRO_STATUS_INVALID_INDEX:
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;

Просмотреть файл

@ -233,10 +233,15 @@ _extract_svg_surface (cairo_surface_t *surface,
{
cairo_surface_t *target;
if (surface->status)
return surface->status;
if (! _cairo_surface_is_paginated (surface))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
target = _cairo_paginated_surface_get_target (surface);
if (target->status)
return target->status;
if (! _cairo_surface_is_svg (target))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
@ -486,15 +491,21 @@ _cairo_svg_surface_show_page (void *abstract_surface)
static void
_cairo_svg_surface_emit_transform (cairo_output_stream_t *output,
char const *attribute_str,
cairo_matrix_t *matrix)
const cairo_matrix_t *object_matrix,
const cairo_matrix_t *parent_matrix)
{
if (!_cairo_matrix_is_identity (matrix))
cairo_matrix_t matrix = *object_matrix;
if (parent_matrix != NULL)
cairo_matrix_multiply (&matrix, &matrix, parent_matrix);
if (!_cairo_matrix_is_identity (&matrix))
_cairo_output_stream_printf (output,
"%s=\"matrix(%f,%f,%f,%f,%f,%f)\"",
attribute_str,
matrix->xx, matrix->yx,
matrix->xy, matrix->yy,
matrix->x0, matrix->y0);
matrix.xx, matrix.yx,
matrix.xy, matrix.yy,
matrix.x0, matrix.y0);
}
typedef struct
@ -654,7 +665,8 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
}
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
_cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", &image->base.device_transform_inverse);
_cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform",
&image->base.device_transform_inverse, NULL);
_cairo_output_stream_printf (document->xml_node_glyphs, ">/n");
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
@ -949,7 +961,8 @@ static cairo_status_t
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *svg_surface,
cairo_surface_pattern_t *pattern,
int pattern_id,
int pattern_id,
const cairo_matrix_t *parent_matrix,
const char *extra_attributes)
{
cairo_surface_t *surface;
@ -967,7 +980,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
status = _cairo_surface_get_extents (surface, &extents);
if (status)
return status;
goto FAIL;
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
@ -981,7 +994,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
"width=\"%d\" height=\"%d\"",
pattern_id,
extents.width, extents.height);
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (output, ">\n");
}
@ -990,7 +1003,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
extents.width, extents.height);
if (pattern_id == invalid_pattern_id)
_cairo_svg_surface_emit_transform (output, " transform", &p2u);
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@ -1004,6 +1017,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
if (pattern_id != invalid_pattern_id)
_cairo_output_stream_printf (output, "</pattern>\n");
FAIL:
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern,
surface, &surface_attr);
@ -1144,6 +1158,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_surface_pattern_t *pattern,
int pattern_id,
const cairo_matrix_t *parent_matrix,
const char *extra_attributes)
{
cairo_svg_document_t *document = surface->document;
@ -1171,7 +1186,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
pattern_id,
meta_surface->width_pixels,
meta_surface->height_pixels);
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (output, ">\n");
}
@ -1180,7 +1195,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
id);
if (pattern_id == invalid_pattern_id)
_cairo_svg_surface_emit_transform (output, " transform", &p2u);
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@ -1198,16 +1213,17 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_surface_pattern_t *pattern,
int pattern_id,
const cairo_matrix_t *parent_matrix,
const char *extra_attributes)
{
if (_cairo_surface_is_meta (pattern->surface)) {
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern,
pattern_id, extra_attributes);
pattern_id, parent_matrix, extra_attributes);
}
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern,
pattern_id, extra_attributes);
pattern_id, parent_matrix, extra_attributes);
}
static void
@ -1253,7 +1269,8 @@ static cairo_status_t
_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
cairo_surface_pattern_t *pattern,
cairo_output_stream_t *style,
cairo_bool_t is_stroke)
cairo_bool_t is_stroke,
const cairo_matrix_t *parent_matrix)
{
cairo_svg_document_t *document = surface->document;
cairo_status_t status;
@ -1262,13 +1279,13 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
pattern_id = document->pattern_id++;
status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs,
surface, pattern,
pattern_id, NULL);
pattern_id, parent_matrix, NULL);
if (status)
return status;
_cairo_output_stream_printf (style,
"%s: url(#pattern%d);",
is_stroke ? "color" : "fill",
is_stroke ? "stroke" : "fill",
pattern_id);
return CAIRO_STATUS_SUCCESS;
@ -1294,7 +1311,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
_cairo_fixed_to_double (pattern->stops[0].x),
pattern->stops[0].offset,
pattern->stops[0].color.red * 100.0,
pattern->stops[0].color.green * 100.0,
pattern->stops[0].color.blue * 100.0,
@ -1311,22 +1328,20 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
for (i = 0; i < pattern->n_stops; i++) {
if (reverse_stops) {
stops[i] = pattern->stops[pattern->n_stops - i - 1];
stops[i].x = _cairo_fixed_from_double (1.0 - _cairo_fixed_to_double (stops[i].x));
stops[i].offset = 1.0 - stops[i].offset;
} else
stops[i] = pattern->stops[i];
if (emulate_reflect) {
stops[i].x /= 2;
stops[i].offset /= 2;
if (i > 0 && i < (pattern->n_stops - 1)) {
if (reverse_stops) {
stops[i + pattern->n_stops - 1] = pattern->stops[i];
stops[i + pattern->n_stops - 1].x =
_cairo_fixed_from_double (0.5 + 0.5
* _cairo_fixed_to_double (stops[i + pattern->n_stops - 1].x));
stops[i + pattern->n_stops - 1].offset =
0.5 + 0.5 * stops[i + pattern->n_stops - 1].offset;
} else {
stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1];
stops[i + pattern->n_stops - 1].x =
_cairo_fixed_from_double (1 - 0.5
* _cairo_fixed_to_double (stops [i + pattern->n_stops - 1].x));
stops[i + pattern->n_stops - 1].offset =
1 - 0.5 * stops[i + pattern->n_stops - 1].offset;
}
}
}
@ -1338,8 +1353,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
if (start_offset >= 0.0)
for (i = 0; i < n_stops; i++) {
offset = start_offset + (1 - start_offset ) *
_cairo_fixed_to_double (stops[i].x);
offset = start_offset + (1 - start_offset ) * stops[i].offset;
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
@ -1356,14 +1370,14 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
cairo_color_t offset_color_start, offset_color_stop;
for (i = 0; i < n_stops; i++) {
if (_cairo_fixed_to_double (stops[i].x) >= -start_offset) {
if (stops[i].offset >= -start_offset) {
if (i > 0) {
if (stops[i].x != stops[i-1].x) {
if (stops[i].offset != stops[i-1].offset) {
double x0, x1;
cairo_color_t *color0, *color1;
x0 = _cairo_fixed_to_double (stops[i-1].x);
x1 = _cairo_fixed_to_double (stops[i].x);
x0 = stops[i-1].offset;
x1 = stops[i].offset;
color0 = &stops[i-1].color;
color1 = &stops[i].color;
offset_color_start.red = color0->red + (color1->red - color0->red)
@ -1405,7 +1419,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
_cairo_fixed_to_double (stops[i].x) + start_offset,
stops[i].offset + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
@ -1416,7 +1430,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
1.0 + _cairo_fixed_to_double (stops[i].x) + start_offset,
1.0 + stops[i].offset + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
@ -1461,7 +1475,8 @@ static cairo_status_t
_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
cairo_linear_pattern_t *pattern,
cairo_output_stream_t *style,
cairo_bool_t is_stroke)
cairo_bool_t is_stroke,
const cairo_matrix_t *parent_matrix)
{
cairo_svg_document_t *document = surface->document;
double x0, y0, x1, y1;
@ -1486,7 +1501,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
x0, y0, x1, y1);
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
@ -1500,7 +1515,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
_cairo_output_stream_printf (style,
"%s: url(#linear%d);",
is_stroke ? "color" : "fill",
is_stroke ? "stroke" : "fill",
document->linear_pattern_id);
document->linear_pattern_id++;
@ -1512,7 +1527,8 @@ static cairo_status_t
_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
cairo_radial_pattern_t *pattern,
cairo_output_stream_t *style,
cairo_bool_t is_stroke)
cairo_bool_t is_stroke,
const cairo_matrix_t *parent_matrix)
{
cairo_svg_document_t *document = surface->document;
cairo_matrix_t p2u;
@ -1563,7 +1579,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
document->radial_pattern_id,
x1, y1,
x1, y1, r1);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
@ -1647,7 +1663,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
_cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" ");
else
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
/* To support cairo's EXTEND_NONE, (for which SVG has no similar
@ -1684,7 +1700,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
_cairo_output_stream_printf (style,
"%s: url(#radial%d);",
is_stroke ? "color" : "fill",
is_stroke ? "stroke" : "fill",
document->radial_pattern_id);
document->radial_pattern_id++;
@ -1696,20 +1712,25 @@ static cairo_status_t
_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface,
cairo_pattern_t *pattern,
cairo_output_stream_t *output,
cairo_bool_t is_stroke)
cairo_bool_t is_stroke,
const cairo_matrix_t *parent_matrix)
{
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern,
output, is_stroke);
case CAIRO_PATTERN_TYPE_SURFACE:
return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern,
output, is_stroke, parent_matrix);
case CAIRO_PATTERN_TYPE_LINEAR:
return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern,
output, is_stroke, parent_matrix);
case CAIRO_PATTERN_TYPE_RADIAL:
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern,
output, is_stroke, parent_matrix);
}
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
}
@ -1719,14 +1740,15 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_fill_rule_t fill_rule)
cairo_fill_rule_t fill_rule,
cairo_matrix_t *parent_matrix)
{
_cairo_output_stream_printf (output,
"fill-rule: %s; ",
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
"evenodd" : "nonzero");
_cairo_svg_surface_emit_operator (output, surface, op);
return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix);
}
static cairo_status_t
@ -1734,7 +1756,8 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_stroke_style_t *stroke_style)
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *parent_matrix)
{
cairo_status_t status;
const char *line_cap, *line_join;
@ -1776,7 +1799,7 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
line_cap,
line_join);
status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE);
status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE, parent_matrix);
if (status)
return status;
@ -1826,11 +1849,13 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
cairo_status_t status;
_cairo_output_stream_printf (surface->xml_node, "<path style=\"");
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, fill_source, fill_rule);
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op,
fill_source, fill_rule, stroke_ctm_inverse);
if (status)
return status;
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, stroke_source, stroke_style);
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op,
stroke_source, stroke_style, stroke_ctm_inverse);
if (status)
return status;
@ -1840,7 +1865,7 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
if (status)
return status;
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm);
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm, NULL);
_cairo_output_stream_printf (surface->xml_node, "/>\n");
return CAIRO_STATUS_SUCCESS;
@ -1864,7 +1889,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
assert (_cairo_svg_surface_operation_supported (surface, op, source));
_cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;");
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule);
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule, NULL);
if (status)
return status;
@ -1913,6 +1938,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
surface,
(cairo_surface_pattern_t *) source,
invalid_pattern_id,
NULL,
extra_attributes);
_cairo_output_stream_printf (output,
@ -1921,7 +1947,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
"style=\"",
surface->width, surface->height);
_cairo_svg_surface_emit_operator (output, surface, op);
status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL);
if (status)
return status;
@ -2086,14 +2112,18 @@ _cairo_svg_surface_stroke (void *abstract_dst,
assert (_cairo_svg_surface_operation_supported (surface, op, source));
_cairo_output_stream_printf (surface->xml_node, "<path style=\"fill: none; ");
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op, source, stroke_style);
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op,
source, stroke_style, ctm_inverse);
if (status)
return status;
_cairo_output_stream_printf (surface->xml_node, "\" ");
status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
if (status)
return status;
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm);
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm, NULL);
_cairo_output_stream_printf (surface->xml_node, "/>\n");
return CAIRO_STATUS_SUCCESS;
@ -2130,7 +2160,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
_cairo_output_stream_printf (surface->xml_node, "<g style=\"");
status = _cairo_svg_surface_emit_pattern (surface, pattern,
surface->xml_node, FALSE);
surface->xml_node, FALSE, NULL);
if (status)
return status;

Просмотреть файл

@ -85,8 +85,10 @@ struct _cairo_truetype_font {
};
static int
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
static cairo_status_t
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font,
unsigned short glyph,
unsigned short *out);
#define SFNT_VERSION 0x00010000
#define SFNT_STRING_MAX_LENGTH 65535
@ -491,29 +493,38 @@ cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
return CAIRO_STATUS_SUCCESS;
}
static void
cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
unsigned char *buffer)
static cairo_status_t
cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
unsigned char *buffer,
unsigned long size)
{
tt_glyph_data_t *glyph_data;
tt_composite_glyph_t *composite_glyph;
tt_composite_glyph_t *composite_glyph, *last_glyph;
int num_args;
int has_more_components;
unsigned short flags;
unsigned short index;
cairo_status_t status;
if (font->status)
return;
return font->status;
if (size < sizeof (tt_glyph_data_t))
return CAIRO_INT_STATUS_UNSUPPORTED;
glyph_data = (tt_glyph_data_t *) buffer;
if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
return;
return CAIRO_STATUS_SUCCESS;
composite_glyph = &glyph_data->glyph;
last_glyph = (tt_composite_glyph_t *) (buffer + size);
do {
flags = be16_to_cpu (composite_glyph->flags);
has_more_components = flags & TT_MORE_COMPONENTS;
index = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index));
status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index);
if (status)
return status;
composite_glyph->index = cpu_to_be16 (index);
num_args = 1;
if (flags & TT_ARG_1_AND_2_ARE_WORDS)
@ -525,7 +536,12 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
num_args += 3;
composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
if (has_more_components && composite_glyph >= last_glyph)
return CAIRO_INT_STATUS_UNSUPPORTED;
} while (has_more_components);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -580,6 +596,12 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
end = be32_to_cpu (u.long_offsets[index + 1]);
}
/* quick sanity check... */
if (end < begin) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FAIL;
}
size = end - begin;
status = cairo_truetype_font_align_output (font, &next);
if (status)
@ -601,7 +623,9 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
if (status)
goto FAIL;
cairo_truetype_font_remap_composite_glyph (font, buffer);
status = cairo_truetype_font_remap_composite_glyph (font, buffer, size);
if (status)
goto FAIL;
}
}
@ -932,16 +956,22 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
return _cairo_truetype_font_set_error (font, status);
}
static int
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph)
static cairo_status_t
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font,
unsigned short glyph,
unsigned short *out)
{
if (glyph >= font->num_glyphs_in_face)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (font->parent_to_subset[glyph] == 0) {
font->parent_to_subset[glyph] = font->base.num_glyphs;
font->glyphs[font->base.num_glyphs].parent_index = glyph;
font->base.num_glyphs++;
}
return font->parent_to_subset[glyph];
*out = font->parent_to_subset[glyph];
return CAIRO_STATUS_SUCCESS;
}
static void
@ -1037,7 +1067,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
cairo_status_t status;
const char *data = NULL; /* squelch bogus compiler warning */
unsigned long length = 0; /* squelch bogus compiler warning */
unsigned long parent_glyph, offsets_length;
unsigned long offsets_length;
unsigned int i;
const unsigned long *string_offsets = NULL;
unsigned long num_strings = 0;
@ -1047,8 +1077,9 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
return status;
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
parent_glyph = font->scaled_font_subset->glyphs[i];
cairo_truetype_font_use_glyph (font, parent_glyph);
unsigned short parent_glyph = font->scaled_font_subset->glyphs[i];
status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph);
assert (status == CAIRO_STATUS_SUCCESS);
}
cairo_truetype_font_create_truetype_table_list (font);

Просмотреть файл

@ -1907,7 +1907,7 @@ cairo_font_face_t *
cairo_win32_font_face_create_for_hfont (HFONT font)
{
LOGFONTW logfont;
GetObject (font, sizeof(logfont), &logfont);
GetObjectW (font, sizeof(logfont), &logfont);
if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
logfont.lfWidth != 0) {

Просмотреть файл

@ -757,7 +757,7 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
}
stop = i%num_rects + 1;
vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + _cairo_fixed_to_double (pattern->base.stops[stop].x)));
vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset));
vert[i*2+1].y = (LONG) clip.bottom;
if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
stop = num_rects - stop;
@ -1419,6 +1419,9 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
{
cairo_win32_surface_t *surface = abstract_surface;
XFORM xform;
double x_res, y_res;
cairo_matrix_t inverse_ctm;
cairo_status_t status;
SaveDC (surface->dc); /* Save application context first, before doing MWT */
@ -1431,6 +1434,17 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
surface->ctm.x0 = xform.eDx;
surface->ctm.y0 = xform.eDy;
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
inverse_ctm = surface->ctm;
status = cairo_matrix_invert (&inverse_ctm);
if (status)
return status;
x_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSX);
y_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSY);
cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res);
_cairo_surface_set_resolution (&surface->base, x_res, y_res);
if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY))
return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform");
@ -1468,7 +1482,6 @@ cairo_surface_t *
cairo_win32_printing_surface_create (HDC hdc)
{
cairo_win32_surface_t *surface;
int xr, yr;
RECT rect;
surface = malloc (sizeof (cairo_win32_surface_t));
@ -1504,10 +1517,6 @@ cairo_win32_printing_surface_create (HDC hdc)
_cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
xr = GetDeviceCaps(hdc, LOGPIXELSX);
yr = GetDeviceCaps(hdc, LOGPIXELSY);
_cairo_surface_set_resolution (&surface->base, (double) xr, (double) yr);
return _cairo_paginated_surface_create (&surface->base,
CAIRO_CONTENT_COLOR_ALPHA,
surface->extents.width,

Просмотреть файл

@ -410,9 +410,15 @@ _cairo_win32_surface_create_similar_internal (void *abstract_src,
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
new_surf->bitmap = ddb;
new_surf->saved_dc_bitmap = saved_dc_bitmap;
new_surf->is_dib = FALSE;
if (new_surf->base.status == CAIRO_STATUS_SUCCESS) {
new_surf->bitmap = ddb;
new_surf->saved_dc_bitmap = saved_dc_bitmap;
new_surf->is_dib = FALSE;
} else {
SelectObject (ddb_dc, saved_dc_bitmap);
DeleteDC (ddb_dc);
DeleteObject (ddb);
}
}
return (cairo_surface_t*) new_surf;

Просмотреть файл

@ -70,6 +70,12 @@ struct _cairo_xlib_display {
unsigned int closed :1;
};
typedef struct _cairo_xlib_visual_info {
VisualID visualid;
XColor colors[256];
unsigned long rgb333_to_pseudocolor[512];
} cairo_xlib_visual_info_t;
struct _cairo_xlib_screen_info {
cairo_xlib_screen_info_t *next;
cairo_reference_count_t ref_count;
@ -82,6 +88,8 @@ struct _cairo_xlib_screen_info {
GC gc[9];
unsigned int gc_needs_clip_reset;
cairo_array_t visuals;
};
cairo_private cairo_xlib_display_t *
@ -125,4 +133,18 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
cairo_private cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
cairo_private cairo_status_t
_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
Visual *visual,
cairo_xlib_visual_info_t **out);
cairo_private cairo_status_t
_cairo_xlib_visual_info_create (Display *dpy,
int screen,
VisualID visualid,
cairo_xlib_visual_info_t **out);
cairo_private void
_cairo_xlib_visual_info_destroy (Display *dpy, cairo_xlib_visual_info_t *info);
#endif /* CAIRO_XLIB_PRIVATE_H */

Просмотреть файл

@ -269,6 +269,8 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
{
cairo_xlib_screen_info_t **prev;
cairo_xlib_screen_info_t *list;
cairo_xlib_visual_info_t **visuals;
int i;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
@ -282,12 +284,17 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
break;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
_cairo_xlib_screen_info_close_display (info);
_cairo_xlib_display_destroy (info->display);
_cairo_array_fini (&info->visuals);
free (info);
}
@ -335,6 +342,9 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
memset (info->gc, 0, sizeof (info->gc));
info->gc_needs_clip_reset = 0;
_cairo_array_init (&info->visuals,
sizeof (cairo_xlib_visual_info_t*));
if (screen) {
int event_base, error_base;
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
@ -411,3 +421,62 @@ _cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cai
return status;
}
cairo_status_t
_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
Visual *visual,
cairo_xlib_visual_info_t **out)
{
cairo_xlib_visual_info_t **visuals, *ret = NULL;
cairo_status_t status;
int i, n_visuals;
CAIRO_MUTEX_LOCK (info->display->mutex);
visuals = _cairo_array_index (&info->visuals, 0);
n_visuals = _cairo_array_num_elements (&info->visuals);
for (i = 0; i < n_visuals; i++) {
if (visuals[i]->visualid == visual->visualid) {
ret = visuals[i];
break;
}
}
CAIRO_MUTEX_UNLOCK (info->display->mutex);
if (ret != NULL) {
*out = ret;
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_xlib_visual_info_create (info->display->display,
XScreenNumberOfScreen (info->screen),
visual->visualid,
&ret);
if (status)
return status;
CAIRO_MUTEX_LOCK (info->display->mutex);
if (n_visuals != _cairo_array_num_elements (&info->visuals)) {
/* check that another thread has not added our visual */
int new_visuals = _cairo_array_num_elements (&info->visuals);
visuals = _cairo_array_index (&info->visuals, 0);
for (i = n_visuals; i < new_visuals; i++) {
if (visuals[i]->visualid == visual->visualid) {
_cairo_xlib_visual_info_destroy (info->display->display, ret);
ret = visuals[i];
break;
}
}
if (i == new_visuals)
status = _cairo_array_append (&info->visuals, &ret);
} else
status = _cairo_array_append (&info->visuals, &ret);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
if (status) {
_cairo_xlib_visual_info_destroy (info->display->display, ret);
return status;
}
*out = ret;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -91,6 +91,11 @@ struct _cairo_xlib_surface {
cairo_filter_t filter;
int repeat;
XTransform xtransform;
uint32_t a_mask;
uint32_t r_mask;
uint32_t g_mask;
uint32_t b_mask;
};
enum {

Просмотреть файл

@ -48,6 +48,16 @@
typedef int (*cairo_xlib_error_func_t) (Display *display,
XErrorEvent *event);
static cairo_surface_t *
_cairo_xlib_surface_create_internal (Display *dpy,
Drawable drawable,
Screen *screen,
Visual *visual,
XRenderPictFormat *xrender_format,
int width,
int height,
int depth);
static cairo_status_t
_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);
@ -71,10 +81,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
#endif
/*
* Instead of taking two round trips for each blending request,
* assume that if a particular drawable fails GetImage that it will
@ -173,9 +179,11 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
depth);
surface = (cairo_xlib_surface_t *)
cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen,
xrender_format,
width, height);
_cairo_xlib_surface_create_internal (dpy, pix,
src->screen, src->visual,
xrender_format,
width, height,
depth);
if (surface->base.status) {
XFreePixmap (dpy, pix);
return &surface->base;
@ -251,10 +259,11 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
xrender_format->depth);
surface = (cairo_xlib_surface_t *)
cairo_xlib_surface_create_with_xrender_format (src->dpy, pix,
src->screen,
xrender_format,
width, height);
_cairo_xlib_surface_create_internal (src->dpy, pix,
src->screen, src->visual,
xrender_format,
width, height,
xrender_format->depth);
if (surface->base.status != CAIRO_STATUS_SUCCESS) {
XFreePixmap (src->dpy, pix);
return &surface->base;
@ -455,18 +464,70 @@ _swap_ximage_to_native (XImage *ximage)
}
}
/* Given a mask, (with a single sequence of contiguous 1 bits), return
* the number of 1 bits in 'width' and the number of 0 bits to its
* right in 'shift'. */
static inline void
_characterize_field (uint32_t mask, int *width, int *shift)
{
*width = _cairo_popcount (mask);
/* The final '& 31' is to force a 0 mask to result in 0 shift. */
*shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
}
/* Convert a field of 'width' bits to 'new_width' bits with correct
* rounding. */
static inline uint32_t
_resize_field (uint32_t field, int width, int new_width)
{
if (width == 0)
return 0;
if (width >= new_width) {
return field >> (width - new_width);
} else {
uint32_t result = field << (new_width - width);
while (width < new_width) {
result |= result >> width;
width <<= 1;
}
return result;
}
}
/* Given a shifted field value, (described by 'width' and 'shift),
* resize it 8-bits and return that value.
*
* Note that the original field value must not have any non-field bits
* set.
*/
static inline uint32_t
_field_to_8 (uint32_t field, int width, int shift)
{
return _resize_field (field >> shift, width, 8);
}
/* Given an 8-bit value, convert it to a field of 'width', shift it up
* to 'shift, and return it. */
static inline uint32_t
_field_from_8 (uint32_t field, int width, int shift)
{
return _resize_field (field, 8, width) << shift;
}
static cairo_status_t
_get_image_surface (cairo_xlib_surface_t *surface,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect)
{
cairo_int_status_t status;
cairo_image_surface_t *image;
XImage *ximage;
short x1, y1, x2, y2;
cairo_format_masks_t masks;
unsigned short x1, y1, x2, y2;
pixman_format_code_t pixman_format;
cairo_status_t status;
cairo_format_masks_t xlib_masks;
x1 = 0;
y1 = 0;
@ -567,55 +628,127 @@ _get_image_surface (cairo_xlib_surface_t *surface,
_swap_ximage_to_native (ximage);
/*
* Compute the pixel format masks from either a XrenderFormat or
* else from a visual; failing that we assume the drawable is an
* alpha-only pixmap as it could only have been created that way
* through the cairo_xlib_surface_create_for_bitmap function.
*/
if (surface->xrender_format) {
masks.bpp = ximage->bits_per_pixel;
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 if (surface->visual) {
masks.bpp = ximage->bits_per_pixel;
masks.alpha_mask = 0;
masks.red_mask = surface->visual->red_mask;
masks.green_mask = surface->visual->green_mask;
masks.blue_mask = surface->visual->blue_mask;
xlib_masks.bpp = ximage->bits_per_pixel;
xlib_masks.alpha_mask = surface->a_mask;
xlib_masks.red_mask = surface->r_mask;
xlib_masks.green_mask = surface->g_mask;
xlib_masks.blue_mask = surface->b_mask;
status = _pixman_format_from_masks (&xlib_masks, &pixman_format);
if (status == CAIRO_STATUS_SUCCESS) {
image = (cairo_image_surface_t*)
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
pixman_format,
ximage->width,
ximage->height,
ximage->bytes_per_line);
status = image->base.status;
if (status) {
XDestroyImage (ximage);
return status;
}
/* Let the surface take ownership of the data */
_cairo_image_surface_assume_ownership_of_data (image);
ximage->data = NULL;
} else {
masks.bpp = ximage->bits_per_pixel;
masks.red_mask = 0;
masks.green_mask = 0;
masks.blue_mask = 0;
if (surface->depth < 32)
masks.alpha_mask = (1 << surface->depth) - 1;
else
masks.alpha_mask = 0xffffffff;
cairo_format_t format;
unsigned char *data;
uint32_t *row;
uint32_t in_pixel, out_pixel;
unsigned int rowstride;
uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0;
int a_width=0, r_width=0, g_width=0, b_width=0;
int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
int x, y;
XColor *colors = NULL;
/* The visual we are dealing with is not supported by the
* standard pixman formats. So we must first convert the data
* to a supported format. */
if (surface->visual->class == TrueColor) {
cairo_bool_t has_color;
cairo_bool_t has_alpha;
has_color = (surface->r_mask ||
surface->g_mask ||
surface->b_mask);
has_alpha = surface->a_mask;
if (has_color) {
if (has_alpha) {
format = CAIRO_FORMAT_ARGB32;
} else {
format = CAIRO_FORMAT_RGB24;
}
} else {
/* XXX: Using CAIRO_FORMAT_A8 here would be more
* efficient, but would require slightly different code in
* the image conversion to put the alpha channel values
* into the right place. */
format = CAIRO_FORMAT_ARGB32;
}
a_mask = surface->a_mask;
r_mask = surface->r_mask;
g_mask = surface->g_mask;
b_mask = surface->b_mask;
_characterize_field (a_mask, &a_width, &a_shift);
_characterize_field (r_mask, &r_width, &r_shift);
_characterize_field (g_mask, &g_width, &g_shift);
_characterize_field (b_mask, &b_width, &b_shift);
} else {
cairo_xlib_visual_info_t *visual_info;
format = CAIRO_FORMAT_RGB24;
status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
surface->visual,
&visual_info);
if (status) {
XDestroyImage (ximage);
return status;
}
colors = visual_info->colors;
}
image = (cairo_image_surface_t *) cairo_image_surface_create
(format, ximage->width, ximage->height);
status = image->base.status;
if (status) {
XDestroyImage (ximage);
return status;
}
data = cairo_image_surface_get_data (&image->base);
rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
row = (uint32_t *) data;
for (y = 0; y < ximage->height; y++) {
for (x = 0; x < ximage->width; x++) {
in_pixel = XGetPixel (ximage, x, y);
if (surface->visual->class == TrueColor) {
out_pixel = (
_field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 |
_field_to_8 (in_pixel & r_mask, r_width, r_shift) << 16 |
_field_to_8 (in_pixel & g_mask, g_width, g_shift) << 8 |
_field_to_8 (in_pixel & b_mask, b_width, b_shift));
} else {
XColor *color;
color = &colors[in_pixel & 0xff];
out_pixel = (
_field_to_8 (color->red, 16, 0) << 16 |
_field_to_8 (color->green, 16, 0) << 8 |
_field_to_8 (color->blue, 16, 0));
}
row[x] = out_pixel;
}
row += rowstride;
}
}
pixman_format = _pixman_format_from_masks (&masks);
image = (cairo_image_surface_t*)
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
pixman_format,
ximage->width,
ximage->height,
ximage->bytes_per_line);
status = image->base.status;
if (status) {
XDestroyImage (ximage);
return status;
}
/* Let the surface take ownership of the data */
_cairo_image_surface_assume_ownership_of_data (image);
ximage->data = NULL;
XDestroyImage (ximage);
*image_out = image;
@ -719,39 +852,118 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
int dst_y)
{
XImage ximage;
uint32_t bpp, red, green, blue;
cairo_format_masks_t image_masks;
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
cairo_status_t status;
cairo_bool_t own_data;
unsigned long *rgb333_to_pseudocolor = NULL;
_pixman_format_to_masks (image->pixman_format, &image_masks);
_pixman_format_to_masks (image->pixman_format, &bpp, &red, &green, &blue);
ximage.width = image->width;
ximage.height = image->height;
ximage.format = ZPixmap;
ximage.data = (char *)image->data;
ximage.byte_order = native_byte_order;
ximage.bitmap_unit = 32; /* always for libpixman */
ximage.bitmap_bit_order = native_byte_order;
ximage.bitmap_pad = 32; /* always for libpixman */
ximage.depth = image->depth;
ximage.bytes_per_line = image->stride;
ximage.bits_per_pixel = bpp;
ximage.red_mask = red;
ximage.green_mask = green;
ximage.blue_mask = blue;
ximage.depth = surface->depth;
ximage.red_mask = surface->r_mask;
ximage.green_mask = surface->g_mask;
ximage.blue_mask = surface->b_mask;
ximage.xoffset = 0;
XInitImage (&ximage);
if (image_masks.red_mask == surface->r_mask &&
image_masks.green_mask == surface->g_mask &&
image_masks.blue_mask == surface->b_mask)
{
ximage.bits_per_pixel = image_masks.bpp;
ximage.bytes_per_line = image->stride;
ximage.data = (char *)image->data;
own_data = FALSE;
XInitImage (&ximage);
} else {
unsigned int stride, rowstride;
int x, y;
uint32_t in_pixel, out_pixel, *row;
int a_width=0, r_width=0, g_width=0, b_width=0;
int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
if (surface->depth > 16) {
ximage.bits_per_pixel = 32;
} else if (surface->depth > 8) {
ximage.bits_per_pixel = 16;
} else if (surface->depth > 1) {
ximage.bits_per_pixel = 8;
} else {
ximage.bits_per_pixel = 1;
}
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
ximage.bits_per_pixel);
ximage.bytes_per_line = stride;
ximage.data = _cairo_malloc_ab (stride, ximage.height);
if (ximage.data == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
own_data = TRUE;
XInitImage (&ximage);
if (surface->visual->class == TrueColor) {
_characterize_field (surface->a_mask, &a_width, &a_shift);
_characterize_field (surface->r_mask, &r_width, &r_shift);
_characterize_field (surface->g_mask, &g_width, &g_shift);
_characterize_field (surface->b_mask, &b_width, &b_shift);
} else {
cairo_xlib_visual_info_t *visual_info;
status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
surface->visual,
&visual_info);
if (status)
goto BAIL;
rgb333_to_pseudocolor = visual_info->rgb333_to_pseudocolor;
}
rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
row = (uint32_t *) cairo_image_surface_get_data (&image->base);
for (y = 0; y < ximage.height; y++) {
for (x = 0; x < ximage.width; x++) {
int a, r, g, b;
in_pixel = row[x];
a = (in_pixel >> 24) & 0xff;
r = (in_pixel >> 16) & 0xff;
g = (in_pixel >> 8) & 0xff;
b = (in_pixel ) & 0xff;
if (surface->visual->class == TrueColor)
out_pixel = (_field_from_8 (a, a_width, a_shift) |
_field_from_8 (r, r_width, r_shift) |
_field_from_8 (g, g_width, g_shift) |
_field_from_8 (b, b_width, b_shift));
else
out_pixel = rgb333_to_pseudocolor[_field_from_8 (r, 3, 6) |
_field_from_8 (g, 3, 3) |
_field_from_8 (b, 3, 0)];
XPutPixel (&ximage, x, y, out_pixel);
}
row += rowstride;
}
}
status = _cairo_xlib_surface_ensure_gc (surface);
if (status)
return status;
goto BAIL;
XPutImage(surface->dpy, surface->drawable, surface->gc,
&ximage, src_x, src_y, dst_x, dst_y,
width, height);
return CAIRO_STATUS_SUCCESS;
BAIL:
if (own_data)
free (ximage.data);
return status;
}
static cairo_status_t
@ -2032,6 +2244,40 @@ _cairo_xlib_surface_create_internal (Display *dpy,
surface->clip_rects = surface->embedded_clip_rects;
surface->num_clip_rects = 0;
/*
* Compute the pixel format masks from either a XrenderFormat or
* else from a visual; failing that we assume the drawable is an
* alpha-only pixmap as it could only have been created that way
* through the cairo_xlib_surface_create_for_bitmap function.
*/
if (xrender_format) {
surface->a_mask = (unsigned long)
surface->xrender_format->direct.alphaMask
<< surface->xrender_format->direct.alpha;
surface->r_mask = (unsigned long)
surface->xrender_format->direct.redMask
<< surface->xrender_format->direct.red;
surface->g_mask = (unsigned long)
surface->xrender_format->direct.greenMask
<< surface->xrender_format->direct.green;
surface->b_mask = (unsigned long)
surface->xrender_format->direct.blueMask
<< surface->xrender_format->direct.blue;
} else if (visual) {
surface->a_mask = 0;
surface->r_mask = visual->red_mask;
surface->g_mask = visual->green_mask;
surface->b_mask = visual->blue_mask;
} else {
if (depth < 32)
surface->a_mask = (1 << depth) - 1;
else
surface->a_mask = 0xffffffff;
surface->r_mask = 0;
surface->g_mask = 0;
surface->b_mask = 0;
}
return (cairo_surface_t *) surface;
}
@ -2155,7 +2401,6 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
NULL, format, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
/**
* cairo_xlib_surface_get_xrender_format:
@ -2665,7 +2910,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
cairo_xlib_font_glyphset_info_t *glyphset_info;
if (!glyph_surface) {
status = _cairo_scaled_glyph_lookup (scaled_font,
_cairo_scaled_glyph_index (scaled_glyph),
CAIRO_SCALED_GLYPH_INFO_METRICS |
@ -2694,17 +2938,18 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
/* If the glyph surface has zero height or width, we create
* a clear 1x1 surface, to avoid various X server bugs.
*/
if ((glyph_surface->width == 0) || (glyph_surface->height == 0)) {
if (glyph_surface->width == 0 || glyph_surface->height == 0) {
cairo_t *cr;
cairo_surface_t *tmp_surface;
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
if (tmp_surface->status)
goto BAIL;
cr = cairo_create (tmp_surface);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
status = cairo_status (cr);
cairo_destroy (cr);
tmp_surface->device_transform = glyph_surface->base.device_transform;
@ -2727,17 +2972,17 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
tmp_surface = cairo_image_surface_create (glyphset_info->format,
glyph_surface->width,
glyph_surface->height);
if (tmp_surface->status)
goto BAIL;
tmp_surface->device_transform = glyph_surface->base.device_transform;
tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
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;
@ -2821,7 +3066,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
XRenderAddGlyphs (dpy, glyphset_info->glyphset,
&glyph_index, &(glyph_info), 1,
&glyph_index, &glyph_info, 1,
(char *) data,
glyph_surface->stride * glyph_surface->height);

Просмотреть файл

@ -0,0 +1,148 @@
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2008 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 Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include "cairo-xlib-private.h"
/* A perceptual distance metric between two colors. No sqrt needed
* since the square of the distance is still a valid metric. */
/* XXX: This is currently using linear distance in RGB space which is
* decidedly not perceptually linear. If someone cared a lot about the
* quality, they might choose something else here. Then again, they
* might also choose not to use a PseudoColor visual... */
static inline int
_color_distance (unsigned short r1, unsigned short g1, unsigned short b1,
unsigned short r2, unsigned short g2, unsigned short b2)
{
r1 >>= 8; g1 >>= 8; b1 >>= 8;
r2 >>= 8; g2 >>= 8; b2 >>= 8;
return ((r2 - r1) * (r2 - r1) +
(g2 - g1) * (g2 - g1) +
(b2 - b1) * (b2 - b1));
}
cairo_status_t
_cairo_xlib_visual_info_create (Display *dpy,
int screen,
VisualID visualid,
cairo_xlib_visual_info_t **out)
{
cairo_xlib_visual_info_t *info;
Colormap colormap = DefaultColormap (dpy, screen);
XColor color;
int gray, red, green, blue;
int i, index, distance, min_distance = 0;
const unsigned short index5_to_short[5] = {
0x0000, 0x4000, 0x8000, 0xc000, 0xffff
};
const unsigned short index8_to_short[8] = {
0x0000, 0x2492, 0x4924, 0x6db6,
0x9249, 0xb6db, 0xdb6d, 0xffff
};
info = malloc (sizeof (cairo_xlib_visual_info_t));
if (info == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
info->visualid = visualid;
/* Allocate a 16-entry gray ramp and a 5x5x5 color cube. Give up
* as soon as failures start. */
for (gray = 0; gray < 16; gray++) {
color.red = (gray << 12) | (gray << 8) | (gray << 4) | gray;
color.green = (gray << 12) | (gray << 8) | (gray << 4) | gray;
color.blue = (gray << 12) | (gray << 8) | (gray << 4) | gray;
if (! XAllocColor (dpy, colormap, &color))
goto DONE_ALLOCATE;
}
/* XXX: Could do this in a more clever order to have the best
* possible results from early failure. Could also choose a cube
* uniformly distributed in a better space than RGB. */
for (red = 0; red < 5; red++) {
for (green = 0; green < 5; green++) {
for (blue = 0; blue < 5; blue++) {
color.red = index5_to_short[red];
color.green = index5_to_short[green];
color.blue = index5_to_short[blue];
color.pixel = 0;
color.flags = 0;
color.pad = 0;
if (! XAllocColor (dpy, colormap, &color))
goto DONE_ALLOCATE;
}
}
}
DONE_ALLOCATE:
for (i = 0; i < ARRAY_LENGTH (info->colors); i++)
info->colors[i].pixel = i;
XQueryColors (dpy, colormap, info->colors, ARRAY_LENGTH (info->colors));
/* Search for nearest colors within allocated colormap. */
for (red = 0; red < 8; red++) {
for (green = 0; green < 8; green++) {
for (blue = 0; blue < 8; blue++) {
index = (red << 6) | (green << 3) | (blue);
for (i = 0; i < 256; i++) {
distance = _color_distance (index8_to_short[red],
index8_to_short[green],
index8_to_short[blue],
info->colors[i].red,
info->colors[i].green,
info->colors[i].blue);
if (i == 0 || distance < min_distance) {
info->rgb333_to_pseudocolor[index] = info->colors[i].pixel;
min_distance = distance;
}
}
}
}
}
*out = info;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_xlib_visual_info_destroy (Display *dpy, cairo_xlib_visual_info_t *info)
{
/* No need for XFreeColors() whilst using DefaultColormap */
free (info);
}

Просмотреть файл

@ -2295,10 +2295,15 @@ cairo_in_fill (cairo_t *cr, double x, double y)
* taken into account.
*
* Note that if the line width is set to exactly zero, then
* cairo_stroke_extents will return an empty rectangle. Contrast with
* cairo_stroke_extents() will return an empty rectangle. Contrast with
* cairo_path_extents() which can be used to compute the non-empty
* bounds as the line width approaches zero.
*
* Note that cairo_stroke_extents() must necessarily do more work to
* compute the precise inked areas in light of the stroke parameters,
* so cairo_path_extents() may be more desirable for sake of
* performance if non-inked path extents are desired.
*
* See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
* cairo_set_line_cap(), cairo_set_dash(), and
* cairo_stroke_preserve().
@ -2344,8 +2349,13 @@ cairo_stroke_extents (cairo_t *cr,
* dimensions and clipping are not taken into account.
*
* Contrast with cairo_path_extents(), which is similar, but returns
* non-zero extents for some paths no inked area, (such as a simple
* line segment).
* non-zero extents for some paths with no inked area, (such as a
* simple line segment).
*
* Note that cairo_fill_extents() must necessarily do more work to
* compute the precise inked areas in light of the fill rule, so
* cairo_path_extents() may be more desirable for sake of performance
* if the non-inked path extents are desired.
*
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
**/

Просмотреть файл

@ -1148,7 +1148,7 @@ cairo_font_face_status (cairo_font_face_t *font_face);
* @CAIRO_FONT_TYPE_TOY: The font was created using cairo's toy font api
* @CAIRO_FONT_TYPE_FT: The font is of type FreeType
* @CAIRO_FONT_TYPE_WIN32: The font is of type Win32
* @CAIRO_FONT_TYPE_ATSUI: The font is of type ATSUI
* @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6)
*
* #cairo_font_type_t is used to describe the type of a given font
* face or scaled font. The font types are also known as "font
@ -1183,7 +1183,7 @@ typedef enum _cairo_font_type {
CAIRO_FONT_TYPE_TOY,
CAIRO_FONT_TYPE_FT,
CAIRO_FONT_TYPE_WIN32,
CAIRO_FONT_TYPE_ATSUI
CAIRO_FONT_TYPE_QUARTZ
} cairo_font_type_t;
cairo_public cairo_font_type_t

Просмотреть файл

@ -147,6 +147,27 @@ do { \
*/
#define CAIRO_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16)
/* Return the number of 1 bits in mask.
*
* GCC 3.4 supports a "population count" builtin, which on many targets is
* implemented with a single instruction. There is a fallback definition
* in libgcc in case a target does not have one, which should be just as
* good as the open-coded solution below, (which is "HACKMEM 169").
*/
static inline int
_cairo_popcount (uint32_t mask)
{
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
return __builtin_popcount (mask);
#else
register int y;
y = (mask >> 1) &033333333333;
y = mask - y - ((y >>1) & 033333333333);
return (((y + (y >> 3)) & 030707070707) % 077);
#endif
}
#ifdef WORDS_BIGENDIAN
#define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) (c)
#else
@ -217,7 +238,7 @@ cairo_private void
_cairo_array_fini (cairo_array_t *array);
cairo_private cairo_status_t
_cairo_array_grow_by (cairo_array_t *array, int additional);
_cairo_array_grow_by (cairo_array_t *array, unsigned int additional);
cairo_private void
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements);
@ -439,9 +460,9 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_win32_scaled_
#endif
#if CAIRO_HAS_ATSUI_FONT
#if CAIRO_HAS_QUARTZ_FONT
extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_font_backend;
extern const cairo_private struct _cairo_scaled_font_backend cairo_quartz_scaled_font_backend;
#endif
@ -776,7 +797,7 @@ typedef struct _cairo_surface_pattern {
} cairo_surface_pattern_t;
typedef struct _cairo_gradient_stop {
cairo_fixed_t x;
double offset;
cairo_color_t color;
} cairo_gradient_stop_t;
@ -848,7 +869,7 @@ typedef struct _cairo_traps {
#define CAIRO_FONT_WEIGHT_DEFAULT CAIRO_FONT_WEIGHT_NORMAL
#define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial"
#define CAIRO_ATSUI_FONT_FAMILY_DEFAULT "Helvetica"
#define CAIRO_QUARTZ_FONT_FAMILY_DEFAULT "Helvetica"
#define CAIRO_FT_FONT_FAMILY_DEFAULT ""
#if CAIRO_HAS_WIN32_FONT
@ -856,10 +877,10 @@ typedef struct _cairo_traps {
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_win32_scaled_font_backend
#elif CAIRO_HAS_ATSUI_FONT
#elif CAIRO_HAS_QUARTZ_FONT
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_ATSUI_FONT_FAMILY_DEFAULT
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_atsui_scaled_font_backend
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_QUARTZ_FONT_FAMILY_DEFAULT
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_quartz_scaled_font_backend
#elif CAIRO_HAS_FT_FONT
@ -1736,6 +1757,9 @@ _cairo_surface_intersect_clip_path (cairo_surface_t *surface,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_clip_t *
_cairo_surface_get_clip (cairo_surface_t *surface);
cairo_private cairo_status_t
_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip);
@ -1836,6 +1860,11 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
#define CAIRO_FORMAT_INVALID ((unsigned int) -1)
#define CAIRO_FORMAT_VALID(format) ((format) <= CAIRO_FORMAT_A1)
/* pixman-required stride alignment in bytes. */
#define CAIRO_STRIDE_ALIGNMENT (sizeof (uint32_t))
#define CAIRO_STRIDE_FOR_WIDTH_BPP(w,bpp) \
(((bpp)*(w)+7)/8 + CAIRO_STRIDE_ALIGNMENT-1) & ~(CAIRO_STRIDE_ALIGNMENT-1)
#define CAIRO_CONTENT_VALID(content) ((content) && \
(((content) & ~(CAIRO_CONTENT_COLOR | \
CAIRO_CONTENT_ALPHA | \
@ -1855,15 +1884,13 @@ cairo_private cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
pixman_format_code_t pixman_format);
cairo_private pixman_format_code_t
_pixman_format_from_masks (cairo_format_masks_t *masks);
cairo_private cairo_int_status_t
_pixman_format_from_masks (cairo_format_masks_t *masks,
pixman_format_code_t *format_ret);
cairo_private void
_pixman_format_to_masks (pixman_format_code_t pixman_format,
uint32_t *bpp,
uint32_t *red,
uint32_t *green,
uint32_t *blue);
cairo_format_masks_t *masks);
cairo_private cairo_surface_t *
_cairo_image_surface_create_with_pixman_format (unsigned char *data,
@ -2209,7 +2236,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
uint32_t **result,
int *items_written);
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_ATSUI_FONT+0
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
#if CAIRO_HAS_UTF8_TO_UTF16
@ -2253,7 +2280,9 @@ slim_hidden_proto (cairo_get_matrix);
slim_hidden_proto (cairo_get_tolerance);
slim_hidden_proto (cairo_image_surface_create);
slim_hidden_proto (cairo_image_surface_create_for_data);
slim_hidden_proto (cairo_image_surface_get_data);
slim_hidden_proto (cairo_image_surface_get_height);
slim_hidden_proto (cairo_image_surface_get_stride);
slim_hidden_proto (cairo_image_surface_get_width);
slim_hidden_proto (cairo_format_stride_for_width);
slim_hidden_proto (cairo_line_to);

Просмотреть файл

@ -54,7 +54,7 @@
#include "gfxFontTest.h"
#include "gfxFontUtils.h"
#include "cairo-atsui.h"
#include "cairo-quartz.h"
#include "gfxQuartzSurface.h"
#include "gfxQuartzFontCache.h"
@ -116,7 +116,7 @@ gfxAtsuiFont::gfxAtsuiFont(MacOSFontEntry *aFontEntry,
InitMetrics(fontID, fontRef);
mFontFace = cairo_atsui_font_face_create_for_atsu_font_id(fontID);
mFontFace = cairo_quartz_font_face_create_for_atsu_font_id(fontID);
cairo_matrix_t sizeMatrix, ctm;
cairo_matrix_init_identity(&ctm);