зеркало из https://github.com/mozilla/gecko-dev.git
b=419715, upgrade cairo to 1.6 or as-close-as-possible -- imported patch cairo-upgrade.patch ; r=me
This commit is contained in:
Родитель
fdff5bb834
Коммит
ec70458884
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче