b=462938, Upgrade cairo to 1.8.2 and pixman to 0.12.0 [cairo piece]

This commit is contained in:
Vladimir Vukicevic 2008-11-05 23:48:23 -08:00
Родитель ad77c191d9
Коммит b22735849c
95 изменённых файлов: 6090 добавлений и 3698 удалений

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

@ -7,8 +7,8 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.7.4-136-g5ea2555)
pixman (pixman-0.11.10-8-g7180230)
cairo (1.8.2)
pixman (pixman-0.12.0-19-g95f2af9)
***** NOTE FOR VISUAL C++ 6.0 *****
@ -28,6 +28,8 @@ buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug
tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds
==== pixman patches ====
endian.patch: include cairo-platform.h for endian macros

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

@ -85,6 +85,8 @@ CSRCS = \
cairo-deflate-stream.c \
cairo-fixed.c \
cairo-font-face.c \
cairo-font-face-twin.c \
cairo-font-face-twin-data.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \

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

@ -66,6 +66,9 @@ cairo_private void
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
cairo_box_t *bbox);
cairo_private cairo_int_status_t
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
cairo_int_status_t status_b);
cairo_private cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content);

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

@ -62,9 +62,41 @@ typedef struct {
} cairo_analysis_surface_t;
cairo_int_status_t
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
cairo_int_status_t status_b)
{
/* fatal errors should be checked and propagated at source */
assert (! _cairo_status_is_error (status_a));
assert (! _cairo_status_is_error (status_b));
/* return the most important status */
if (status_a == CAIRO_INT_STATUS_UNSUPPORTED ||
status_b == CAIRO_INT_STATUS_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK ||
status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK)
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
if (status_a == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN ||
status_b == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY ||
status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
/* at this point we have checked all the valid internal codes, so... */
assert (status_a == CAIRO_STATUS_SUCCESS &&
status_b == CAIRO_STATUS_SUCCESS);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
cairo_pattern_t *pattern)
_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
cairo_pattern_t *pattern)
{
cairo_surface_t *analysis = &surface->base;
cairo_surface_pattern_t *surface_pattern;
@ -118,9 +150,9 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
}
static cairo_int_status_t
_cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
cairo_rectangle_int_t *rect,
cairo_int_status_t backend_status)
_add_operation (cairo_analysis_surface_t *surface,
cairo_rectangle_int_t *rect,
cairo_int_status_t backend_status)
{
cairo_int_status_t status;
cairo_box_t bbox;
@ -302,8 +334,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
source);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -320,7 +351,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &surface->current_clip);
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -332,7 +363,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
cairo_pattern_t *mask)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_int_status_t status, backend_status;
cairo_rectangle_int_t extents;
if (!surface->target->backend->mask)
@ -342,25 +373,32 @@ _cairo_analysis_surface_mask (void *abstract_surface,
source, mask);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
if (_cairo_surface_is_meta (surface_pattern->surface))
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
if (backend_status != CAIRO_STATUS_SUCCESS &&
backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
return backend_status;
if (_cairo_surface_is_meta (surface_pattern->surface)) {
backend_source_status =
_analyze_meta_surface_pattern (surface, source);
if (_cairo_status_is_error (backend_source_status))
return backend_source_status;
}
}
if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
if (_cairo_surface_is_meta (surface_pattern->surface))
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
mask);
if (backend_status != CAIRO_STATUS_SUCCESS &&
backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
return backend_status;
if (_cairo_surface_is_meta (surface_pattern->surface)) {
backend_mask_status =
_analyze_meta_surface_pattern (surface, mask);
if (_cairo_status_is_error (backend_mask_status))
return backend_mask_status;
}
}
backend_status =
_cairo_analysis_surface_merge_status (backend_source_status,
backend_mask_status);
}
status = _cairo_surface_get_extents (&surface->base, &extents);
@ -384,7 +422,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &surface->current_clip);
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -403,7 +441,6 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_traps_t traps;
cairo_box_t box;
cairo_rectangle_int_t extents;
if (!surface->target->backend->stroke)
@ -415,8 +452,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
tolerance, antialias);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -434,10 +470,9 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
box.p1.x = _cairo_fixed_from_int (extents.x);
box.p1.y = _cairo_fixed_from_int (extents.y);
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
cairo_box_t box;
_cairo_box_from_rectangle (&box, &extents);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &box);
@ -451,22 +486,13 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
return status;
}
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_extents (&traps, &box);
_cairo_traps_fini (&traps);
_cairo_box_round_to_rectangle (&box, &extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -483,7 +509,6 @@ _cairo_analysis_surface_fill (void *abstract_surface,
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_traps_t traps;
cairo_box_t box;
cairo_rectangle_int_t extents;
if (!surface->target->backend->fill)
@ -494,8 +519,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
tolerance, antialias);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -513,10 +537,9 @@ _cairo_analysis_surface_fill (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
box.p1.x = _cairo_fixed_from_int (extents.x);
box.p1.y = _cairo_fixed_from_int (extents.y);
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
cairo_box_t box;
_cairo_box_from_rectangle (&box, &extents);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &box);
@ -529,23 +552,13 @@ _cairo_analysis_surface_fill (void *abstract_surface,
return status;
}
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_extents (&traps, &box);
_cairo_traps_fini (&traps);
_cairo_box_round_to_rectangle (&box, &extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -582,8 +595,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -611,7 +623,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &glyph_extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -634,7 +646,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_analysis_surface_t *surface = abstract_surface;
@ -648,8 +660,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
clusters, num_clusters, cluster_flags,
scaled_font);
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
@ -665,8 +676,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
}
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
@ -694,7 +704,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &glyph_extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
status = _add_operation (surface, &extents, backend_status);
return status;
}
@ -742,6 +752,11 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
int height)
{
cairo_analysis_surface_t *surface;
cairo_status_t status;
status = target->status;
if (status)
return _cairo_surface_create_in_error (status);
surface = malloc (sizeof (cairo_analysis_surface_t));
if (surface == NULL)
@ -785,17 +800,22 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
return &surface->base;
}
cairo_private void
void
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
cairo_analysis_surface_t *surface;
if (abstract_surface->status)
return;
surface = (cairo_analysis_surface_t *) abstract_surface;
surface->ctm = *ctm;
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
}
cairo_private void
void
_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{

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

@ -85,6 +85,7 @@ _cairo_array_init_snapshot (cairo_array_t *array,
/**
* _cairo_array_fini:
* @array: A #cairo_array_t
*
* Free all resources associated with @array. After this call, @array
* should not be used again without a subsequent call to
@ -104,6 +105,7 @@ _cairo_array_fini (cairo_array_t *array)
/**
* _cairo_array_grow_by:
* @array: a #cairo_array_t
*
* Increase the size of @array (if needed) so that there are at least
* @additional free spaces in the array. The actual size of the array
@ -158,6 +160,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
/**
* _cairo_array_truncate:
* @array: a #cairo_array_t
*
* Truncate size of the array to @num_elements if less than the
* current size. No memory is actually freed. The stored objects
@ -174,14 +177,16 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
/**
* _cairo_array_index:
* @array: a #cairo_array_t
* Returns: A pointer to the object stored at @index.
*
* Return value: A pointer to object stored at @index. If the
* resulting value is assigned to a pointer to an object of the same
* If the resulting value is assigned to a pointer to an object of the same
* element_size as initially passed to _cairo_array_init() then that
* pointer may be used for further direct indexing with []. For
* example:
*
* #cairo_array_t array;
* <informalexample><programlisting>
* cairo_array_t array;
* double *values;
*
* _cairo_array_init (&array, sizeof(double));
@ -190,6 +195,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
* values = _cairo_array_index (&array, 0);
* for (i = 0; i < _cairo_array_num_elements (&array); i++)
* ... use values[i] here ...
* </programlisting></informalexample>
**/
void *
_cairo_array_index (cairo_array_t *array, unsigned int index)
@ -215,6 +221,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index)
/**
* _cairo_array_copy_element:
* @array: a #cairo_array_t
*
* Copy a single element out of the array from index @index into the
* location pointed to by @dst.
@ -227,6 +234,7 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
/**
* _cairo_array_append:
* @array: a #cairo_array_t
*
* Append a single item onto the array by growing the array by at
* least one element, then copying element_size bytes from @element
@ -250,6 +258,7 @@ _cairo_array_append (cairo_array_t *array,
/**
* _cairo_array_append:
* @array: a #cairo_array_t
*
* Append one or more items onto the array by growing the array by
* @num_elements, then copying @num_elements * element_size bytes from
@ -280,6 +289,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
/**
* _cairo_array_allocate:
* @array: a #cairo_array_t
*
* Allocate space at the end of the array for @num_elements additional
* elements, providing the address of the new memory chunk in
@ -314,8 +324,10 @@ _cairo_array_allocate (cairo_array_t *array,
/**
* _cairo_array_num_elements:
* @array: a #cairo_array_t
* Returns: The number of elements stored in @array.
*
* Return value: The number of elements stored in @array.
* This space was left intentionally blank, but gtk-doc filled it.
**/
int
_cairo_array_num_elements (cairo_array_t *array)
@ -325,9 +337,11 @@ _cairo_array_num_elements (cairo_array_t *array)
/**
* _cairo_array_size:
* @array: a #cairo_array_t
* Returns: The number of elements for which there is currently space
* allocated in @array.
*
* Return value: The number of elements for which there is currently
* space allocated in array.
* This space was left intentionally blank, but gtk-doc filled it.
**/
int
_cairo_array_size (cairo_array_t *array)

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

@ -37,15 +37,17 @@
#ifndef CAIRO_ATOMIC_PRIVATE_H
#define CAIRO_ATOMIC_PRIVATE_H
# include "cairo-compiler-private.h"
#if HAVE_CONFIG_H
#include "config.h"
#endif
CAIRO_BEGIN_DECLS
#define CAIRO_HAS_ATOMIC_OPS 1
#if HAVE_INTEL_ATOMIC_PRIMITIVES
#if CAIRO_HAS_INTEL_ATOMIC_PRIMITIVES
#define HAS_ATOMIC_OPS 1
typedef int cairo_atomic_int_t;
@ -53,11 +55,10 @@ typedef int cairo_atomic_int_t;
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
#else
#endif
# include "cairo-compiler-private.h"
# undef CAIRO_HAS_ATOMIC_OPS
#ifndef HAS_ATOMIC_OPS
typedef int cairo_atomic_int_t;
@ -73,7 +74,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
#endif
#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
# include "cairo-compiler-private.h"

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

@ -36,7 +36,7 @@
#include "cairo-atomic-private.h"
#include "cairo-mutex-private.h"
#ifndef CAIRO_HAS_ATOMIC_OPS
#ifndef HAS_ATOMIC_OPS
void
_cairo_atomic_int_inc (int *x)
{
@ -73,7 +73,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
#endif
#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
int
_cairo_atomic_int_get (int *x)
{

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

@ -39,6 +39,9 @@
#include "cairo-skiplist-private.h"
#include "cairo-freelist-private.h"
#define DEBUG_VALIDATE 0
#define DEBUG_PRINT_STATE 0
typedef cairo_point_t cairo_bo_point32_t;
typedef struct _cairo_bo_point128 {
@ -198,60 +201,163 @@ _slope_compare (cairo_bo_edge_t *a,
* with respect to x. */
if ((adx ^ bdx) < 0) {
return adx < 0 ? -1 : +1;
}
else {
} else {
int32_t ady = a->bottom.y - a->top.y;
int32_t bdy = b->bottom.y - b->top.y;
int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
/* if (adx * bdy > bdx * ady) */
if (_cairo_int64_gt (adx_bdy, bdx_ady))
return 1;
/* if (adx * bdy < bdx * ady) */
if (_cairo_int64_lt (adx_bdy, bdx_ady))
return -1;
return 0;
return _cairo_int64_cmp (adx_bdy, bdx_ady);
}
}
static cairo_quorem64_t
edge_x_for_y (cairo_bo_edge_t *edge,
int32_t y)
/*
* We need to compare the x-coordinates of a pair of lines for a particular y,
* without loss of precision.
*
* The x-coordinate along an edge for a given y is:
* X = A_x + (Y - A_y) * A_dx / A_dy
*
* So the inequality we wish to test is:
* A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
* where -?- is our inequality operator.
*
* By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
* all positive, so we can rearrange it thus without causing a sign change:
* A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
* - (Y - A_y) * A_dx * B_dy
*
* Given the assumption that all the deltas fit within 32 bits, we can compute
* this comparison directly using 128 bit arithmetic.
*
* (And put the burden of the work on developing fast 128 bit ops, which are
* required throughout the tessellator.)
*
* See the similar discussion for _slope_compare().
*/
static int
edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b,
int32_t y)
{
/* XXX: We're assuming here that dx and dy will still fit in 32
* bits. That's not true in general as there could be overflow. We
* should prevent that before the tessellation algorithm
* begins.
*/
int32_t dx = edge->bottom.x - edge->top.x;
int32_t dy = edge->bottom.y - edge->top.y;
int64_t numerator;
cairo_quorem64_t quorem;
int32_t adx, ady;
int32_t bdx, bdy;
cairo_int128_t L, R;
if (edge->middle.y == y) {
quorem.quo = edge->middle.x;
quorem.rem = 0;
return quorem;
}
if (edge->bottom.y == y) {
quorem.quo = edge->bottom.x;
quorem.rem = 0;
return quorem;
}
if (dy == 0) {
quorem.quo = _cairo_int32_to_int64 (edge->top.x);
quorem.rem = 0;
return quorem;
}
adx = a->bottom.x - a->top.x;
ady = a->bottom.y - a->top.y;
/* edge->top.x + (y - edge->top.y) * dx / dy */
numerator = _cairo_int32x32_64_mul ((y - edge->top.y), dx);
quorem = _cairo_int64_divrem (numerator, dy);
quorem.quo += edge->top.x;
bdx = b->bottom.x - b->top.x;
bdy = b->bottom.y - b->top.y;
return quorem;
L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
a->top.x - b->top.x);
R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
ady),
y - b->top.y),
_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
bdy),
y - a->top.y));
/* return _cairo_int128_cmp (L, R); */
if (_cairo_int128_lt (L, R))
return -1;
if (_cairo_int128_gt (L, R))
return 1;
return 0;
}
/*
* We need to compare the x-coordinate of a line for a particular y wrt to a
* given x, without loss of precision.
*
* The x-coordinate along an edge for a given y is:
* X = A_x + (Y - A_y) * A_dx / A_dy
*
* So the inequality we wish to test is:
* A_x + (Y - A_y) * A_dx / A_dy -?- X
* where -?- is our inequality operator.
*
* By construction, we know that A_dy (and (Y - A_y)) are
* all positive, so we can rearrange it thus without causing a sign change:
* (Y - A_y) * A_dx -?- (X - A_x) * A_dy
*
* Given the assumption that all the deltas fit within 32 bits, we can compute
* this comparison directly using 64 bit arithmetic.
*
* See the similar discussion for _slope_compare() and
* edges_compare_x_for_y_general().
*/
static int
edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
int32_t y,
int32_t x)
{
int32_t adx, ady;
int32_t dx, dy;
cairo_int64_t L, R;
adx = a->bottom.x - a->top.x;
ady = a->bottom.y - a->top.y;
dy = y - a->top.y;
dx = x - a->top.x;
L = _cairo_int32x32_64_mul (dy, adx);
R = _cairo_int32x32_64_mul (dx, ady);
return _cairo_int64_cmp (L, R);
}
static int
edges_compare_x_for_y (const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b,
int32_t y)
{
/* If the sweep-line is currently on an end-point of a line,
* then we know its precise x value (and considering that we often need to
* compare events at end-points, this happens frequently enough to warrant
* special casing).
*/
enum {
HAVE_NEITHER = 0x0,
HAVE_AX = 0x1,
HAVE_BX = 0x2,
HAVE_BOTH = HAVE_AX | HAVE_BX
} have_ax_bx = HAVE_BOTH;
int32_t ax, bx;
if (y == a->top.y)
ax = a->top.x;
else if (y == a->bottom.y)
ax = a->bottom.x;
else
have_ax_bx &= ~HAVE_AX;
if (y == b->top.y)
bx = b->top.x;
else if (y == b->bottom.y)
bx = b->bottom.x;
else
have_ax_bx &= ~HAVE_BX;
switch (have_ax_bx) {
default:
case HAVE_NEITHER:
return edges_compare_x_for_y_general (a, b, y);
case HAVE_AX:
return - edge_compare_for_y_against_x (b, y, ax);
case HAVE_BX:
return edge_compare_for_y_against_x (a, y, bx);
case HAVE_BOTH:
return ax - bx;
}
}
static int
@ -259,8 +365,6 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *a,
cairo_bo_edge_t *b)
{
cairo_quorem64_t ax;
cairo_quorem64_t bx;
int cmp;
if (a == b)
@ -289,18 +393,9 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
if (amin > bmax) return +1;
}
ax = edge_x_for_y (a, sweep_line->current_y);
bx = edge_x_for_y (b, sweep_line->current_y);
if (ax.quo > bx.quo)
return 1;
else if (ax.quo < bx.quo)
return -1;
/* Quotients are identical, test remainder. */
if (ax.rem > bx.rem)
return 1;
else if (ax.rem < bx.rem)
return -1;
cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
if (cmp)
return cmp;
/* The two edges intersect exactly at y, so fall back on slope
* comparison. We know that this compare_edges function will be
@ -489,17 +584,17 @@ det32_64 (int32_t a,
}
static inline cairo_int128_t
det64_128 (cairo_int64_t a,
cairo_int64_t b,
cairo_int64_t c,
cairo_int64_t d)
det64x32_128 (cairo_int64_t a,
int32_t b,
cairo_int64_t c,
int32_t d)
{
cairo_int128_t ad;
cairo_int128_t bc;
/* det = a * d - b * c */
ad = _cairo_int64x64_128_mul (a, d);
bc = _cairo_int64x64_128_mul (b, c);
ad = _cairo_int64x32_128_mul (a, d);
bc = _cairo_int64x32_128_mul (c, b);
return _cairo_int128_sub (ad, bc);
}
@ -532,7 +627,7 @@ intersect_lines (cairo_bo_edge_t *a,
cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
cairo_quorem64_t qr;
if (_cairo_int64_eq (den_det, 0))
if (_cairo_int64_is_zero (den_det))
return CAIRO_BO_STATUS_PARALLEL;
a_det = det32_64 (a->top.x, a->top.y,
@ -541,22 +636,22 @@ intersect_lines (cairo_bo_edge_t *a,
b->bottom.x, b->bottom.y);
/* x = det (a_det, dx1, b_det, dx2) / den_det */
qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dx1,
b_det, dx2),
den_det);
if (_cairo_int64_eq (qr.rem,den_det))
return CAIRO_BO_STATUS_NO_INTERSECTION;
intersection->x.ordinate = qr.quo;
intersection->x.exactness = qr.rem ? INEXACT : EXACT;
/* y = det (a_det, dy1, b_det, dy2) / den_det */
qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dy1,
b_det, dy2),
qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
b_det, dx2),
den_det);
if (_cairo_int64_eq (qr.rem, den_det))
return CAIRO_BO_STATUS_NO_INTERSECTION;
intersection->y.ordinate = qr.quo;
intersection->y.exactness = qr.rem ? INEXACT : EXACT;
intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
/* y = det (a_det, dy1, b_det, dy2) / den_det */
qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
b_det, dy2),
den_det);
if (_cairo_int64_eq (qr.rem, den_det))
return CAIRO_BO_STATUS_NO_INTERSECTION;
intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
return CAIRO_BO_STATUS_INTERSECTION;
}
@ -941,7 +1036,6 @@ _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line,
left->prev = right;
}
#define DEBUG_PRINT_STATE 0
#if DEBUG_PRINT_STATE
static void
_cairo_bo_edge_print (cairo_bo_edge_t *edge)
@ -1078,35 +1172,35 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
/* Only emit trapezoids with positive height. */
if (fixed_top < fixed_bot) {
cairo_point_t left_top, left_bot, right_top, right_bot;
cairo_line_t left_line;
cairo_line_t right_line;
cairo_fixed_t xmin = bo_traps->xmin;
cairo_fixed_t ymin = bo_traps->ymin;
fixed_top += ymin;
fixed_bot += ymin;
left_top.x = left->top.x + xmin;
left_top.y = left->top.y + ymin;
right_top.x = right->top.x + xmin;
right_top.y = right->top.y + ymin;
left_bot.x = left->bottom.x + xmin;
left_bot.y = left->bottom.y + ymin;
right_bot.x = right->bottom.x + xmin;
right_bot.y = right->bottom.y + ymin;
left_line.p1.x = left->top.x + xmin;
left_line.p1.y = left->top.y + ymin;
right_line.p1.x = right->top.x + xmin;
right_line.p1.y = right->top.y + ymin;
left_line.p2.x = left->bottom.x + xmin;
left_line.p2.y = left->bottom.y + ymin;
right_line.p2.x = right->bottom.x + xmin;
right_line.p2.y = right->bottom.y + ymin;
/* Avoid emitting the trapezoid if it is obviously degenerate.
* TODO: need a real collinearity test here for the cases
* where the trapezoid is degenerate, yet the top and bottom
* coordinates aren't equal. */
if (left_top.x != right_top.x ||
left_top.y != right_top.y ||
left_bot.x != right_bot.x ||
left_bot.y != right_bot.y)
if (left_line.p1.x != right_line.p1.x ||
left_line.p1.y != right_line.p1.y ||
left_line.p2.x != right_line.p2.x ||
left_line.p2.y != right_line.p2.y)
{
_cairo_traps_add_trap_from_points (bo_traps->traps,
fixed_top,
fixed_bot,
left_top, left_bot,
right_top, right_bot);
_cairo_traps_add_trap (bo_traps->traps,
fixed_top, fixed_bot,
&left_line, &right_line);
#if DEBUG_PRINT_STATE
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
@ -1177,6 +1271,7 @@ _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
_cairo_freelist_fini (&bo_traps->freelist);
}
#if DEBUG_VALIDATE
static void
_cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
{
@ -1193,15 +1288,16 @@ _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
{
if (SKIP_ELT_TO_EDGE (elt) != edge) {
fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n");
exit (1);
abort ();
}
}
if (edge || elt) {
fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
exit (1);
abort ();
}
}
#endif
static cairo_status_t
@ -1324,9 +1420,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
#if DEBUG_PRINT_STATE
print_state ("After processing start", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
case CAIRO_BO_EVENT_TYPE_STOP:
edge = event->e1;
@ -1346,9 +1441,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
#if DEBUG_PRINT_STATE
print_state ("After processing stop", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
case CAIRO_BO_EVENT_TYPE_INTERSECTION:
edge1 = event->e1;
edge2 = event->e2;
@ -1382,10 +1476,11 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
#if DEBUG_PRINT_STATE
print_state ("After processing intersection", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
}
#if DEBUG_VALIDATE
_cairo_bo_sweep_line_validate (&sweep_line);
#endif
}
*num_intersections = intersection_count;
@ -1427,12 +1522,16 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_fixed_t ymin = 0x7FFFFFFF;
cairo_fixed_t xmax = -0x80000000;
cairo_fixed_t ymax = -0x80000000;
cairo_box_t limit;
cairo_bool_t has_limits;
int num_bo_edges;
int i;
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
has_limits = _cairo_traps_get_limit (traps, &limit);
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
edges = stack_edges;
} else {
@ -1471,6 +1570,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_point_t top = polygon->edges[i].edge.p1;
cairo_point_t bot = polygon->edges[i].edge.p2;
/* Discard the edge if it lies outside the limits of traps. */
if (has_limits) {
/* Strictly above or below the limits? */
if (bot.y <= limit.p1.y || top.y >= limit.p2.y)
continue;
}
/* Offset coordinates into the non-negative range. */
top.x -= xmin;
top.y -= ymin;

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

@ -92,6 +92,7 @@ _cairo_cache_fini (cairo_cache_t *cache)
* @keys_equal: a function to return %TRUE if two keys are equal
* @entry_destroy: destroy notifier for cache entries
* @max_size: the maximum size for this cache
* Returns: the newly created #cairo_cache_t
*
* Creates a new cache using the keys_equal() function to determine
* the equality of entries.
@ -119,8 +120,6 @@ _cairo_cache_fini (cairo_cache_t *cache)
* _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
* used to establish a window during which no automatic removal of
* entries will occur.
*
* Return value:
**/
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,

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

@ -148,7 +148,10 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_box_t extents;
cairo_rectangle_int_t extents_rect;
_cairo_box_from_rectangle (&extents, rectangle);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &extents);
status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
clip_path->fill_rule,
@ -160,11 +163,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
}
_cairo_traps_extents (&traps, &extents);
_cairo_traps_fini (&traps);
_cairo_box_round_to_rectangle (&extents, &extents_rect);
_cairo_rectangle_intersect (rectangle, &extents_rect);
_cairo_traps_fini (&traps);
clip_path = clip_path->prev;
}
@ -436,9 +439,8 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
/* Intersect with the target surface rectangle so we don't use
* more memory and time than we need to. */
status = _cairo_surface_get_extents (target, &target_rect);
if (!status)
if (status == CAIRO_STATUS_SUCCESS)
_cairo_rectangle_intersect (&surface_rect, &target_rect);
if (surface_rect.width == 0 || surface_rect.height == 0) {
@ -561,6 +563,7 @@ _cairo_clip_clip (cairo_clip_t *clip,
cairo_surface_t *target)
{
cairo_status_t status;
cairo_rectangle_int_t rectangle;
cairo_traps_t traps;
if (clip->all_clipped)
@ -582,6 +585,17 @@ _cairo_clip_clip (cairo_clip_t *clip,
return status;
_cairo_traps_init (&traps);
/* Limit the traps to the target surface
* - so we don't add more traps than needed. */
status = _cairo_surface_get_extents (target, &rectangle);
if (status == CAIRO_STATUS_SUCCESS) {
cairo_box_t box;
_cairo_box_from_rectangle (&box, &rectangle);
_cairo_traps_limit (&traps, &box);
}
status = _cairo_path_fixed_fill_to_traps (path,
fill_rule,
tolerance,
@ -676,16 +690,22 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
}
if (other->surface) {
int dx, dy;
status = _cairo_surface_clone_similar (target, other->surface,
0,
0,
other->surface_rect.width,
other->surface_rect.height,
&dx, &dy,
&clip->surface);
if (status)
goto BAIL;
clip->surface_rect = other->surface_rect;
/* src offset was 0, so we expect an exact replica of the surface */
assert (dx == 0);
assert (dy == 0);
}
if (other->path) {

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

@ -165,6 +165,9 @@ cairo_bool_t
_cairo_color_equal (const cairo_color_t *color_a,
const cairo_color_t *color_b)
{
if (color_a == color_b)
return TRUE;
return color_a->red_short == color_b->red_short &&
color_a->green_short == color_b->green_short &&
color_a->blue_short == color_b->blue_short &&

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

@ -38,6 +38,8 @@
#ifndef CAIRO_COMPILER_PRIVATE_H
#define CAIRO_COMPILER_PRIVATE_H
#include "cairo.h"
#if HAVE_CONFIG_H
#include "config.h"
#endif
@ -109,6 +111,34 @@
# define CAIRO_FUNCTION_ALIAS(old, new)
#endif
/*
* Cairo uses the following function attributes in order to improve the
* generated code (effectively by manual inter-procedural analysis).
*
* 'cairo_pure': The function is only allowed to read from its arguments
* and global memory (i.e. following a pointer argument or
* accessing a shared variable). The return value should
* only depend on its arguments, and for an identical set of
* arguments should return the same value.
*
* 'cairo_const': The function is only allowed to read from its arguments.
* It is not allowed to access global memory. The return
* value should only depend its arguments, and for an
* identical set of arguments should return the same value.
* This is currently the most strict function attribute.
*
* Both these function attributes allow gcc to perform CSE and
* constant-folding, with 'cairo_const 'also guaranteeing that pointer contents
* do not change across the function call.
*/
#if __GNUC__ >= 3
#define cairo_pure __attribute__((pure))
#define cairo_const __attribute__((const))
#else
#define cairo_pure
#define cairo_const
#endif
#ifndef __GNUC__
#undef __attribute__
#define __attribute__(x)
@ -116,6 +146,7 @@
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#define popen _popen
#endif
#ifdef _MSC_VER

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

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

@ -49,7 +49,7 @@
#include "cairo.h"
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
#if CAIRO_HAS_DIRECTFB_SURFACE
#include <directfb.h>

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

@ -1,14 +0,0 @@
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
#define HAVE_WINDOWS_H 1
#define CAIRO_HAS_SVG_SURFACE 1
#define CAIRO_HAS_PDF_SURFACE 1
#define CAIRO_HAS_PS_SURFACE 1
#define CAIRO_HAS_WIN32_SURFACE 1
#define CAIRO_HAS_WIN32_FONT 1
#define CAIRO_HAS_PNG_FUNCTIONS 1
#endif

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

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

@ -0,0 +1,209 @@
/*
* Copyright © 2004 Keith Packard
* 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 Keith Packard
*
* Contributor(s):
* Keith Packard <keithp@keithp.com>
* Behdad Esfahbod <behdad@behdad.org>
*/
#include "cairoint.h"
/*
* This file implements a user-font rendering the decendant of the Hershey
* font coded by Keith Packard for use in the Twin window system.
* The actual font data is in cairo-font-face-twin-data.c
*
* Ported to cairo user font by Behdad Esfahbod.
*/
#define twin_glyph_left(g) ((g)[0])
#define twin_glyph_right(g) ((g)[1])
#define twin_glyph_ascent(g) ((g)[2])
#define twin_glyph_descent(g) ((g)[3])
#define twin_glyph_n_snap_x(g) ((g)[4])
#define twin_glyph_n_snap_y(g) ((g)[5])
#define twin_glyph_snap_x(g) (&g[6])
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
#define SNAPI(p) (p)
#define SNAPH(p) (p)
#define FX(g) ((g) / 64.)
#define FY(g) ((g) / 64.)
static cairo_status_t
twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
cairo_t *cr,
cairo_font_extents_t *metrics)
{
metrics->ascent = FY (50);
metrics->descent = FY (14);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
unsigned long unicode,
unsigned long *glyph)
{
/* We use an identity charmap. Which means we could live
* with no unicode_to_glyph method too. But we define this
* to map all unknown chars to a single unknown glyph to
* reduce pressure on cache. */
if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
*glyph = unicode;
else
*glyph = 0;
return CAIRO_STATUS_SUCCESS;
}
#define SNAPX(p) _twin_snap (p, info.snap_x, info.n_snap_x)
#define SNAPY(p) _twin_snap (p, info.snap_y, info.n_snap_y)
static double
_twin_snap (double v, int a, int b)
{
return v; /* XXX */
}
static cairo_status_t
twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
unsigned long glyph,
cairo_t *cr,
cairo_text_extents_t *metrics)
{
double x1, y1, x2, y2, x3, y3;
const int8_t *b = _cairo_twin_outlines +
_cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
const int8_t *g = twin_glyph_draw(b);
struct {
cairo_bool_t snap;
int snap_x;
int snap_y;
int n_snap_x;
int n_snap_y;
} info = {FALSE};
cairo_set_line_width (cr, 0.06);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
for (;;) {
switch (*g++) {
case 'M':
cairo_close_path (cr);
/* fall through */
case 'm':
x1 = FX(*g++);
y1 = FY(*g++);
if (info.snap)
{
x1 = SNAPX (x1);
y1 = SNAPY (y1);
}
cairo_move_to (cr, x1, y1);
continue;
case 'L':
cairo_close_path (cr);
/* fall through */
case 'l':
x1 = FX(*g++);
y1 = FY(*g++);
if (info.snap)
{
x1 = SNAPX (x1);
y1 = SNAPY (y1);
}
cairo_line_to (cr, x1, y1);
continue;
case 'C':
cairo_close_path (cr);
/* fall through */
case 'c':
x1 = FX(*g++);
y1 = FY(*g++);
x2 = FX(*g++);
y2 = FY(*g++);
x3 = FX(*g++);
y3 = FY(*g++);
if (info.snap)
{
x1 = SNAPX (x1);
y1 = SNAPY (y1);
x2 = SNAPX (x2);
y2 = SNAPY (y2);
x3 = SNAPX (x3);
y3 = SNAPY (y3);
}
cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
continue;
case 'E':
cairo_close_path (cr);
/* fall through */
case 'e':
cairo_stroke (cr);
break;
case 'X':
/* filler */
continue;
}
break;
}
metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */;
if (info.snap)
metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
return CAIRO_STATUS_SUCCESS;
}
cairo_font_face_t *
_cairo_font_face_twin_create (cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
cairo_font_face_t *twin_font_face;
twin_font_face = cairo_user_font_face_create ();
cairo_user_font_face_set_init_func (twin_font_face, twin_scaled_font_init);
cairo_user_font_face_set_render_glyph_func (twin_font_face, twin_scaled_font_render_glyph);
cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
return twin_font_face;
}

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

@ -282,6 +282,7 @@ cairo_font_face_get_user_data (cairo_font_face_t *font_face,
return _cairo_user_data_array_get_data (&font_face->user_data,
key);
}
slim_hidden_def (cairo_font_face_get_user_data);
/**
* cairo_font_face_set_user_data:
@ -306,11 +307,12 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return font_face->status;
return _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
}
slim_hidden_def (cairo_font_face_set_user_data);
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
@ -566,6 +568,38 @@ _cairo_toy_font_face_destroy (void *abstract_face)
_cairo_toy_font_face_fini (font_face);
}
static cairo_status_t
_cairo_toy_font_face_scaled_font_get_implementation (void *abstract_font_face,
cairo_font_face_t **font_face_out)
{
cairo_toy_font_face_t *font_face = abstract_font_face;
cairo_status_t status;
if (font_face->base.status)
return font_face->base.status;
if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
{
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
if (backend->get_implementation == NULL) {
*font_face_out = &font_face->base;
return CAIRO_STATUS_SUCCESS;
}
status = backend->get_implementation (font_face,
font_face_out);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_font_face_set_error (&font_face->base, status);
}
status = _cairo_user_scaled_font_backend.get_implementation (font_face,
font_face_out);
return _cairo_font_face_set_error (&font_face->base, status);
}
static cairo_status_t
_cairo_toy_font_face_scaled_font_create (void *abstract_font_face,
const cairo_matrix_t *font_matrix,
@ -574,7 +608,6 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
cairo_scaled_font_t **scaled_font)
{
cairo_toy_font_face_t *font_face = abstract_font_face;
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
cairo_status_t status;
if (font_face->base.status)
@ -584,12 +617,31 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
if (status)
return status;
return _cairo_font_face_set_error (&font_face->base,
backend->create_toy (font_face,
font_matrix,
ctm,
options,
scaled_font));
if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
{
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
*scaled_font = NULL;
status = backend->create_toy (font_face,
font_matrix,
ctm,
options,
scaled_font);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_font_face_set_error (&font_face->base, status);
if (*scaled_font)
cairo_scaled_font_destroy (*scaled_font);
}
status = _cairo_user_scaled_font_backend.create_toy (font_face,
font_matrix,
ctm,
options,
scaled_font);
return _cairo_font_face_set_error (&font_face->base, status);
}
static cairo_bool_t
@ -641,6 +693,7 @@ cairo_toy_font_face_get_slant (cairo_font_face_t *font_face)
}
return toy_font_face->slant;
}
slim_hidden_def (cairo_toy_font_face_get_slant);
/**
* cairo_toy_font_face_get_weight:
@ -662,10 +715,12 @@ cairo_toy_font_face_get_weight (cairo_font_face_t *font_face)
}
return toy_font_face->weight;
}
slim_hidden_def (cairo_toy_font_face_get_weight);
static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
CAIRO_FONT_TYPE_TOY,
_cairo_toy_font_face_destroy,
_cairo_toy_font_face_scaled_font_get_implementation,
_cairo_toy_font_face_scaled_font_create
};

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

@ -39,7 +39,6 @@
static const cairo_font_options_t _cairo_font_options_nil = {
CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_LCD_FILTER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
};
@ -55,7 +54,6 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
{
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}
@ -66,7 +64,6 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
{
options->antialias = other->antialias;
options->subpixel_order = other->subpixel_order;
options->lcd_filter = other->lcd_filter;
options->hint_style = other->hint_style;
options->hint_metrics = other->hint_metrics;
}
@ -192,8 +189,6 @@ cairo_font_options_merge (cairo_font_options_t *options,
options->antialias = other->antialias;
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
options->subpixel_order = other->subpixel_order;
if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
options->lcd_filter = other->lcd_filter;
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
options->hint_style = other->hint_style;
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
@ -226,7 +221,6 @@ cairo_font_options_equal (const cairo_font_options_t *options,
return (options->antialias == other->antialias &&
options->subpixel_order == other->subpixel_order &&
options->lcd_filter == other->lcd_filter &&
options->hint_style == other->hint_style &&
options->hint_metrics == other->hint_metrics);
}
@ -252,8 +246,7 @@ cairo_font_options_hash (const cairo_font_options_t *options)
return ((options->antialias) |
(options->subpixel_order << 4) |
(options->lcd_filter << 8) |
(options->hint_style << 12) |
(options->hint_style << 8) |
(options->hint_metrics << 16));
}
slim_hidden_def (cairo_font_options_hash);
@ -334,49 +327,6 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
return options->subpixel_order;
}
/**
* cairo_font_options_set_lcd_filter:
* @options: a #cairo_font_options_t
* @lcd_filter: the new LCD filter
*
* Sets the LCD filter for the font options object. The LCD filter
* specifies how pixels are filtered when rendered with an antialiasing
* mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_lcd_filter_t for full details.
*
* Since: 1.8
**/
void
cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
cairo_lcd_filter_t lcd_filter)
{
if (cairo_font_options_status (options))
return;
options->lcd_filter = lcd_filter;
}
slim_hidden_def (cairo_font_options_set_lcd_filter);
/**
* cairo_font_options_get_lcd_filter:
* @options: a #cairo_font_options_t
*
* Gets the LCD filter for the font options object.
* See the documentation for #cairo_lcd_filter_t for full details.
*
* Return value: the LCD filter for the font options object
*
* Since: 1.8
**/
cairo_lcd_filter_t
cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
{
if (cairo_font_options_status ((cairo_font_options_t *) options))
return CAIRO_LCD_FILTER_DEFAULT;
return options->lcd_filter;
}
/**
* cairo_font_options_set_hint_style:
* @options: a #cairo_font_options_t

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

@ -57,30 +57,6 @@
#include FT_SYNTHESIS_H
#endif
#if HAVE_FT_LIBRARY_SETLCDFILTER
#include FT_LCD_FILTER_H
#endif
/* Fontconfig version older than 2.6 didn't have these options */
#ifndef FC_LCD_FILTER
#define FC_LCD_FILTER "lcdfilter"
#endif
/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
#ifndef FC_LCD_NONE
#define FC_LCD_NONE 0
#define FC_LCD_DEFAULT 1
#define FC_LCD_LIGHT 2
#define FC_LCD_LEGACY 3
#endif
/* FreeType version older than 2.3.5(?) didn't have these options */
#ifndef FT_LCD_FILTER_NONE
#define FT_LCD_FILTER_NONE 0
#define FT_LCD_FILTER_DEFAULT 1
#define FT_LCD_FILTER_LIGHT 2
#define FT_LCD_FILTER_LEGACY 16
#endif
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
@ -767,286 +743,23 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
return CAIRO_STATUS_SUCCESS;
}
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
* into a different format. For example, we want to convert a
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
* ARGB or ABGR bitmap.
*
* this function prepares a target descriptor for this operation.
*
* input :: target bitmap descriptor. The function will set its
* 'width', 'rows' and 'pitch' fields, and only these
*
* slot :: the glyph slot containing the source bitmap. this
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
*
* mode :: the requested final rendering mode. supported values are
* MONO, NORMAL (i.e. gray), LCD and LCD_V
*
* the function returns the size in bytes of the corresponding buffer,
* it's up to the caller to allocate the corresponding memory block
* before calling _fill_xrender_bitmap
*
* it also returns -1 in case of error (e.g. incompatible arguments,
* like trying to convert a gray bitmap into a monochrome one)
*/
static int
_compute_xrender_bitmap_size(FT_Bitmap *target,
FT_GlyphSlot slot,
FT_Render_Mode mode)
{
FT_Bitmap *ftbit;
int width, height, pitch;
if (slot->format != FT_GLYPH_FORMAT_BITMAP)
return -1;
/* compute the size of the final bitmap */
ftbit = &slot->bitmap;
width = ftbit->width;
height = ftbit->rows;
pitch = (width + 3) & ~3;
switch (ftbit->pixel_mode) {
case FT_PIXEL_MODE_MONO:
if (mode == FT_RENDER_MODE_MONO) {
pitch = (((width + 31) & ~31) >> 3);
break;
}
/* fall-through */
case FT_PIXEL_MODE_GRAY:
if (mode == FT_RENDER_MODE_LCD ||
mode == FT_RENDER_MODE_LCD_V)
{
/* each pixel is replicated into a 32-bit ARGB value */
pitch = width * 4;
}
break;
case FT_PIXEL_MODE_LCD:
if (mode != FT_RENDER_MODE_LCD)
return -1;
/* horz pixel triplets are packed into 32-bit ARGB values */
width /= 3;
pitch = width * 4;
break;
case FT_PIXEL_MODE_LCD_V:
if (mode != FT_RENDER_MODE_LCD_V)
return -1;
/* vert pixel triplets are packed into 32-bit ARGB values */
height /= 3;
pitch = width * 4;
break;
default: /* unsupported source format */
return -1;
}
target->width = width;
target->rows = height;
target->pitch = pitch;
target->buffer = NULL;
return pitch * height;
}
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
* into a different format (see _compute_xrender_bitmap_size)
*
* you should call this function after _compute_xrender_bitmap_size
*
* target :: target bitmap descriptor. Note that its 'buffer' pointer
* must point to memory allocated by the caller
*
* slot :: the glyph slot containing the source bitmap
*
* mode :: the requested final rendering mode
*
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed
*/
static void
_fill_xrender_bitmap(FT_Bitmap *target,
FT_GlyphSlot slot,
FT_Render_Mode mode,
int bgr)
{
FT_Bitmap *ftbit = &slot->bitmap;
unsigned char *srcLine = ftbit->buffer;
unsigned char *dstLine = target->buffer;
int src_pitch = ftbit->pitch;
int width = target->width;
int height = target->rows;
int pitch = target->pitch;
int subpixel;
int h;
subpixel = (mode == FT_RENDER_MODE_LCD ||
mode == FT_RENDER_MODE_LCD_V);
if (src_pitch < 0)
srcLine -= src_pitch * (ftbit->rows - 1);
target->pixel_mode = ftbit->pixel_mode;
switch (ftbit->pixel_mode) {
case FT_PIXEL_MODE_MONO:
if (subpixel) {
/* convert mono to ARGB32 values */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
for (x = 0; x < width; x++) {
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
((unsigned int *) dstLine)[x] = 0xffffffffU;
}
}
target->pixel_mode = FT_PIXEL_MODE_LCD;
} else if (mode == FT_RENDER_MODE_NORMAL) {
/* convert mono to 8-bit gray */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
for (x = 0; x < width; x++) {
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
dstLine[x] = 0xff;
}
}
target->pixel_mode = FT_PIXEL_MODE_GRAY;
} else {
/* copy mono to mono */
int bytes = (width + 7) >> 3;
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
memcpy (dstLine, srcLine, bytes);
}
break;
case FT_PIXEL_MODE_GRAY:
if (subpixel) {
/* convert gray to ARGB32 values */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++) {
unsigned int pix = srcLine[x];
pix |= (pix << 8);
pix |= (pix << 16);
dst[x] = pix;
}
}
target->pixel_mode = FT_PIXEL_MODE_LCD;
} else {
/* copy gray into gray */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
memcpy (dstLine, srcLine, width);
}
break;
case FT_PIXEL_MODE_LCD:
if (!bgr) {
/* convert horizontal RGB into ARGB32 */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 3) {
unsigned int pix;
pix = ((unsigned int)src[0] << 16) |
((unsigned int)src[1] << 8) |
((unsigned int)src[2] ) |
((unsigned int)src[1] << 24) ;
dst[x] = pix;
}
}
} else {
/* convert horizontal BGR into ARGB32 */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 3) {
unsigned int pix;
pix = ((unsigned int)src[2] << 16) |
((unsigned int)src[1] << 8) |
((unsigned int)src[0] ) |
((unsigned int)src[1] << 24) ;
dst[x] = pix;
}
}
}
break;
default: /* FT_PIXEL_MODE_LCD_V */
/* convert vertical RGB into ARGB32 */
if (!bgr) {
for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
int x;
unsigned char* src = srcLine;
unsigned int* dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 1) {
unsigned int pix;
#if 1
pix = ((unsigned int)src[0] << 16) |
((unsigned int)src[src_pitch] << 8) |
((unsigned int)src[src_pitch*2] ) |
0xFF000000 ;
#else
pix = ((unsigned int)src[0] << 16) |
((unsigned int)src[src_pitch] << 8) |
((unsigned int)src[src_pitch*2] ) |
((unsigned int)src[src_pitch] << 24) ;
/* Empirically-derived subpixel filtering values thanks to Keith
* Packard and libXft. */
static const int filters[3][3] = {
/* red */
#if 0
{ 65538*4/7,65538*2/7,65538*1/7 },
/* green */
{ 65536*1/4, 65536*2/4, 65537*1/4 },
/* blue */
{ 65538*1/7,65538*2/7,65538*4/7 },
#endif
dst[x] = pix;
}
}
} else {
for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 1) {
unsigned int pix;
pix = ((unsigned int)src[src_pitch * 2] << 16) |
((unsigned int)src[src_pitch] << 8) |
((unsigned int)src[0] ) |
((unsigned int)src[src_pitch] << 24) ;
dst[x] = pix;
}
}
}
}
}
{ 65538*9/13,65538*3/13,65538*1/13 },
/* green */
{ 65538*1/6, 65538*4/6, 65538*1/6 },
/* blue */
{ 65538*1/13,65538*3/13,65538*9/13 },
};
/* Fills in val->image with an image surface created from @bitmap
*/
@ -1059,7 +772,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
int width, height, stride;
unsigned char *data;
int format = CAIRO_FORMAT_A8;
cairo_image_surface_t *image;
cairo_bool_t subpixel = FALSE;
width = bitmap->width;
height = bitmap->rows;
@ -1116,7 +829,11 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_GRAY:
if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_NONE:
default:
stride = bitmap->pitch;
if (own_buffer) {
data = bitmap->buffer;
@ -1128,16 +845,104 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
} else {
/* if we get there, the data from the source bitmap
* really comes from _fill_xrender_bitmap, and is
* made of 32-bit ARGB or ABGR values */
assert (own_buffer != 0);
assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
break;
case CAIRO_ANTIALIAS_SUBPIXEL: {
int x, y;
unsigned char *in_line, *out_line, *in;
unsigned int *out;
unsigned int red, green, blue;
int rf, gf, bf;
int s;
int o, os;
unsigned char *data_rgba;
unsigned int width_rgba, stride_rgba;
int vmul = 1;
int hmul = 1;
data = bitmap->buffer;
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
default:
width /= 3;
hmul = 3;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
vmul = 3;
height /= 3;
break;
}
/*
* Filter the glyph to soften the color fringes
*/
width_rgba = width;
stride = bitmap->pitch;
stride_rgba = (width_rgba * 4 + 3) & ~3;
data_rgba = calloc (stride_rgba, height);
if (data_rgba == NULL) {
if (own_buffer)
free (bitmap->buffer);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
os = 1;
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_VRGB:
os = stride;
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
default:
rf = 0;
gf = 1;
bf = 2;
break;
case CAIRO_SUBPIXEL_ORDER_VBGR:
os = stride;
case CAIRO_SUBPIXEL_ORDER_BGR:
bf = 0;
gf = 1;
rf = 2;
break;
}
in_line = bitmap->buffer;
out_line = data_rgba;
for (y = 0; y < height; y++)
{
in = in_line;
out = (unsigned int *) out_line;
in_line += stride * vmul;
out_line += stride_rgba;
for (x = 0; x < width * hmul; x += hmul)
{
red = green = blue = 0;
o = 0;
for (s = 0; s < 3; s++)
{
red += filters[rf][s]*in[x+o];
green += filters[gf][s]*in[x+o];
blue += filters[bf][s]*in[x+o];
o += os;
}
red = red / 65536;
green = green / 65536;
blue = blue / 65536;
*out++ = (green << 24) | (red << 16) | (green << 8) | blue;
}
}
/* Images here are stored in native format. The
* backend must convert to its own format as needed
*/
if (own_buffer)
free (bitmap->buffer);
data = data_rgba;
stride = stride_rgba;
format = CAIRO_FORMAT_ARGB32;
subpixel = TRUE;
break;
}
}
break;
case FT_PIXEL_MODE_GRAY2:
@ -1149,20 +954,19 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
/* XXX */
*surface = image = (cairo_image_surface_t *)
*surface = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
format,
width, height, stride);
if (image->base.status) {
if ((*surface)->base.status) {
free (data);
return (*surface)->base.status;
}
if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
pixman_image_set_component_alpha (image->pixman_image, TRUE);
if (subpixel)
pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
_cairo_image_surface_assume_ownership_of_data (image);
_cairo_image_surface_assume_ownership_of_data ((*surface));
return CAIRO_STATUS_SUCCESS;
}
@ -1187,59 +991,16 @@ _render_glyph_outline (FT_Face face,
cairo_font_options_t *font_options,
cairo_image_surface_t **surface)
{
int rgba = FC_RGBA_UNKNOWN;
int lcd_filter = FT_LCD_FILTER_LEGACY;
FT_GlyphSlot glyphslot = face->glyph;
FT_Outline *outline = &glyphslot->outline;
FT_Bitmap bitmap;
FT_BBox cbox;
unsigned int width, height;
FT_Matrix matrix;
int hmul = 1;
int vmul = 1;
unsigned int width, height, stride;
cairo_bool_t subpixel = FALSE;
cairo_status_t status;
FT_Error fterror;
FT_Library library = glyphslot->library;
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
render_mode = FT_RENDER_MODE_MONO;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
render_mode = FT_RENDER_MODE_LCD;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
render_mode = FT_RENDER_MODE_LCD_V;
break;
}
switch (font_options->lcd_filter) {
case CAIRO_LCD_FILTER_NONE:
lcd_filter = FT_LCD_FILTER_NONE;
break;
case CAIRO_LCD_FILTER_DEFAULT:
case CAIRO_LCD_FILTER_INTRA_PIXEL:
lcd_filter = FT_LCD_FILTER_LEGACY;
break;
case CAIRO_LCD_FILTER_FIR3:
lcd_filter = FT_LCD_FILTER_LIGHT;
break;
case CAIRO_LCD_FILTER_FIR5:
lcd_filter = FT_LCD_FILTER_DEFAULT;
break;
}
break;
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
render_mode = FT_RENDER_MODE_NORMAL;
}
FT_Outline_Get_CBox (outline, &cbox);
@ -1250,21 +1011,20 @@ _render_glyph_outline (FT_Face face,
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
stride = (width * hmul + 3) & ~3;
if (width * height == 0) {
cairo_format_t format;
/* Looks like fb handles zero-sized images just fine */
switch (render_mode) {
case FT_RENDER_MODE_MONO:
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
format = CAIRO_FORMAT_A1;
break;
case FT_RENDER_MODE_LCD:
case FT_RENDER_MODE_LCD_V:
case CAIRO_ANTIALIAS_SUBPIXEL:
format= CAIRO_FORMAT_ARGB32;
break;
case FT_RENDER_MODE_LIGHT:
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_MAX:
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
default:
format = CAIRO_FORMAT_A8;
break;
@ -1276,74 +1036,74 @@ _render_glyph_outline (FT_Face face,
return (*surface)->base.status;
} else {
int bitmap_size;
matrix.xx = matrix.yy = 0x10000L;
matrix.xy = matrix.yx = 0;
switch (render_mode) {
case FT_RENDER_MODE_LCD:
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
rgba = FC_RGBA_BGR;
} else {
rgba = FC_RGBA_RGB;
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
bitmap.num_grays = 1;
stride = ((width + 31) & -32) >> 3;
break;
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width + 3) & -4;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
default:
matrix.xx *= 3;
hmul = 3;
subpixel = TRUE;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
matrix.yy *= 3;
vmul = 3;
subpixel = TRUE;
break;
}
break;
case FT_RENDER_MODE_LCD_V:
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
rgba = FC_RGBA_VBGR;
} else {
rgba = FC_RGBA_VRGB;
}
break;
case FT_RENDER_MODE_MONO:
case FT_RENDER_MODE_LIGHT:
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_MAX:
default:
break;
FT_Outline_Transform (outline, &matrix);
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width * hmul + 3) & -4;
}
#if HAVE_FT_LIBRARY_SETLCDFILTER
FT_Library_SetLcdFilter (library, lcd_filter);
#endif
fterror = FT_Render_Glyph (face->glyph, render_mode);
#if HAVE_FT_LIBRARY_SETLCDFILTER
FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
#endif
if (fterror != 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
bitmap_size = _compute_xrender_bitmap_size (&bitmap,
face->glyph,
render_mode);
if (bitmap_size < 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
bitmap.buffer = calloc (1, bitmap_size);
bitmap.pitch = stride;
bitmap.width = width * hmul;
bitmap.rows = height * vmul;
bitmap.buffer = calloc (stride, bitmap.rows);
if (bitmap.buffer == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
(rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
/* Note:
* _get_bitmap_surface will free bitmap.buffer if there is an error
*/
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
if (status)
return status;
/* Note: the font's coordinate system is upside down from ours, so the
* Y coordinate of the control box needs to be negated. Moreover, device
* offsets are position of glyph origin relative to top left while xMin
* and yMax are offsets of top left relative to origin. Another negation.
*/
cairo_surface_set_device_offset (&(*surface)->base,
(double)-glyphslot->bitmap_left,
(double)+glyphslot->bitmap_top);
}
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinate of the control box needs to be negated. Moreover, device
* offsets are position of glyph origin relative to top left while xMin
* and yMax are offsets of top left relative to origin. Another negation.
*/
cairo_surface_set_device_offset (&(*surface)->base,
floor (-(double) cbox.xMin / 64.0),
floor (+(double) cbox.yMax / 64.0));
return CAIRO_STATUS_SUCCESS;
}
@ -1562,7 +1322,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
if (antialias) {
cairo_subpixel_order_t subpixel_order;
int lcd_filter;
/* disable hinting if requested */
if (FcPatternGetBool (pattern,
@ -1598,25 +1357,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
}
if (FcPatternGetInteger (pattern,
FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
{
switch (lcd_filter) {
case FC_LCD_NONE:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
break;
case FC_LCD_DEFAULT:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
break;
case FC_LCD_LIGHT:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
break;
case FC_LCD_LEGACY:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
break;
}
}
#ifdef FC_HINT_STYLE
if (FcPatternGetInteger (pattern,
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
@ -1717,12 +1457,6 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
options->base.hint_style = CAIRO_HINT_STYLE_NONE;
if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
options->base.lcd_filter = other->base.lcd_filter;
if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
load_flags |= FT_LOAD_NO_HINTING;
@ -1746,11 +1480,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
load_target = FT_LOAD_TARGET_LCD;
load_target |= FT_LOAD_TARGET_LCD;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
load_target = FT_LOAD_TARGET_LCD_V;
load_target |= FT_LOAD_TARGET_LCD_V;
break;
}
}
@ -2483,6 +2217,7 @@ _cairo_ft_index_to_ucs4(void *abstract_font,
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
NULL,
_cairo_ft_scaled_font_create_toy,
_cairo_ft_scaled_font_fini,
_cairo_ft_scaled_glyph_init,
@ -2589,6 +2324,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_font_face_destroy,
NULL, /* direct implementation */
_cairo_ft_font_face_scaled_font_create
};
@ -2693,34 +2429,6 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
}
}
if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
{
if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
{
int lcd_filter;
switch (options->lcd_filter) {
case CAIRO_LCD_FILTER_NONE:
lcd_filter = FT_LCD_FILTER_NONE;
break;
case CAIRO_LCD_FILTER_DEFAULT:
case CAIRO_LCD_FILTER_INTRA_PIXEL:
lcd_filter = FT_LCD_FILTER_LEGACY;
break;
case CAIRO_LCD_FILTER_FIR3:
lcd_filter = FT_LCD_FILTER_LIGHT;
break;
default:
case CAIRO_LCD_FILTER_FIR5:
lcd_filter = FT_LCD_FILTER_DEFAULT;
break;
}
if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
}
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
{
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
@ -2861,10 +2569,14 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_scaled_font_lock_face().
* as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
* to the FT_Face alive in a font-cache and the exact lifetime of the reference
* depends highly upon the exact usage pattern and is subject to external
* factors. You must not call FT_Done_Face() before the last reference to the
* #cairo_font_face_t has been dropped.
*
* As an example, here is how one might correctly couple the lifetime of
* the FreeType face object to the #cairo_font_face_t:
* As an example, below is how one might correctly couple the lifetime of
* the FreeType face object to the #cairo_font_face_t.
*
* <informalexample><programlisting>
* static const cairo_user_data_key_t key;

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

@ -511,6 +511,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -522,6 +524,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
if (src->backend == surface->base.backend)
{
*clone_offset_x = 0;
*clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
@ -539,6 +543,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
_cairo_glitz_surface_create_similar (surface, content,
image_src->width,
image_src->height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (clone->base.status)
return clone->base.status;
@ -802,8 +808,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
gradient->n_stops, 1);
if (src->base.status)
{
if (src->base.status) {
glitz_buffer_destroy (buffer);
free (data);
return src->base.status;
@ -1276,8 +1281,13 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
_cairo_glitz_surface_create_similar (&dst->base,
CAIRO_CONTENT_ALPHA,
2, 1);
if (mask->base.status)
{
if (mask == NULL) {
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
if (src_pattern == &tmp_src_pattern.base)
_cairo_pattern_fini (&tmp_src_pattern.base);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (mask->base.status) {
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
if (src_pattern == &tmp_src_pattern.base)
_cairo_pattern_fini (&tmp_src_pattern.base);
@ -1385,8 +1395,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_CONTENT_ALPHA,
width, height);
if (mask->base.status)
{
if (mask->base.status) {
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
free (data);
cairo_surface_destroy (&image->base);
@ -2011,7 +2020,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
if (scaled_font->surface_private == NULL)
{
@ -2244,6 +2253,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (!glyph_private || !glyph_private->area)
{
int glyph_width, glyph_height;
int clone_offset_x, clone_offset_y;
image = &scaled_glyphs[i]->surface->base;
glyph_width = scaled_glyphs[i]->surface->width;
@ -2255,11 +2265,16 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
0,
glyph_width,
glyph_height,
&clone_offset_x,
&clone_offset_y,
(cairo_surface_t **)
&clone);
if (status)
goto UNLOCK;
assert (clone_offset_x == 0);
assert (clone_offset_y == 0);
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
x1 = _cairo_lround (glyphs[i].x - x_offset);
@ -2371,6 +2386,13 @@ _cairo_glitz_surface_is_similar (void *surface_a,
glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
/* XXX Disable caching of glitz surfaces by the solid pattern cache.
* Until glitz has a mechanism for releasing resources on connection
* closure, we will attempt to access invalid pointers when evicting
* old surfaces from the solid pattern cache.
*/
return FALSE;
return drawable_a == drawable_b;
}

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

@ -60,7 +60,7 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
static void
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
static void
static cairo_status_t
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
@ -314,6 +314,8 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
* _cairo_gstate_is_redirected
* @gstate: a #cairo_gstate_t
*
* This space left intentionally blank.
*
* Return value: %TRUE if the gstate is redirected to a target
* different than the original, %FALSE otherwise.
**/
@ -372,6 +374,8 @@ _cairo_gstate_get_original_target (cairo_gstate_t *gstate)
* _cairo_gstate_get_clip:
* @gstate: a #cairo_gstate_t
*
* This space left intentionally blank.
*
* Return value: a pointer to the gstate's #cairo_clip_t structure.
*/
cairo_clip_t *
@ -945,6 +949,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
cairo_bool_t *inside_ret)
{
cairo_status_t status;
cairo_box_t limit;
cairo_traps_t traps;
if (gstate->stroke_style.line_width <= 0.0) {
@ -954,7 +959,13 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
_cairo_gstate_user_to_backend (gstate, &x, &y);
limit.p1.x = _cairo_fixed_from_double (x) - 1;
limit.p1.y = _cairo_fixed_from_double (y) - 1;
limit.p2.x = limit.p1.x + 2;
limit.p2.y = limit.p1.y + 2;
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &limit);
status = _cairo_path_fixed_stroke_to_traps (path,
&gstate->stroke_style,
@ -1011,11 +1022,18 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
cairo_bool_t *inside_ret)
{
cairo_status_t status;
cairo_box_t limit;
cairo_traps_t traps;
_cairo_gstate_user_to_backend (gstate, &x, &y);
limit.p1.x = _cairo_fixed_from_double (x) - 1;
limit.p1.y = _cairo_fixed_from_double (y) - 1;
limit.p2.x = limit.p1.x + 2;
limit.p2.y = limit.p1.y + 2;
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &limit);
status = _cairo_path_fixed_fill_to_traps (path,
gstate->fill_rule,
@ -1461,16 +1479,16 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
}
cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags)
{
cairo_status_t status;
@ -1482,7 +1500,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
cluster_flags);
}
cairo_status_t
@ -1522,12 +1540,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return cairo_scaled_font_status (gstate->scaled_font);
}
cairo_bool_t
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
{
return cairo_surface_has_show_text_glyphs (gstate->target);
}
cairo_status_t
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
const char *utf8,
@ -1536,7 +1548,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward)
cairo_text_cluster_flags_t cluster_flags)
{
cairo_status_t status;
cairo_pattern_union_t source_pattern;
@ -1562,10 +1574,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs, &num_glyphs);
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
glyphs, num_glyphs,
transformed_glyphs,
&num_glyphs);
if (!num_glyphs)
if (status || num_glyphs == 0)
goto CLEANUP_GLYPHS;
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
@ -1586,7 +1600,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
* fast rasterizer in cairo, we may want to readjust this.
*
* Needless to say, do this only if show_text_glyphs is not available. */
if (_cairo_gstate_has_show_text_glyphs (gstate) ||
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
status = _cairo_surface_show_text_glyphs (gstate->target,
gstate->op,
@ -1594,18 +1608,16 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
utf8, utf8_len,
transformed_glyphs, num_glyphs,
clusters, num_clusters,
backward,
cluster_flags,
gstate->scaled_font);
} else {
cairo_path_fixed_t path;
_cairo_path_fixed_init (&path);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
&path);
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (gstate->target,
@ -1649,15 +1661,18 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
if (transformed_glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs, NULL);
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
glyphs, num_glyphs,
transformed_glyphs,
NULL);
if (status)
goto CLEANUP_GLYPHS;
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
path);
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
cairo_glyph_free (transformed_glyphs);
@ -1697,7 +1712,7 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
* This also uses information from the scaled font and the surface to
* cull/drop glyphs that will not be visible.
**/
static void
static cairo_status_t
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
@ -1710,20 +1725,24 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
cairo_matrix_t *device_transform = &gstate->target->device_transform;
cairo_bool_t drop = FALSE;
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
cairo_status_t status;
if (num_transformed_glyphs != NULL) {
cairo_rectangle_int_t surface_extents;
double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
drop = TRUE;
status = _cairo_gstate_int_clip_extents (gstate, &surface_extents);
if (_cairo_status_is_error (status))
return status;
if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
drop = FALSE; /* unbounded surface */
else {
} else {
if (surface_extents.width == 0 || surface_extents.height == 0) {
/* No visible area. Don't draw anything */
*num_transformed_glyphs = 0;
return;
return CAIRO_STATUS_SUCCESS;
}
/* XXX We currently drop any glyphs that has its position outside
* of the surface boundaries by a safety margin depending on the
@ -1803,4 +1822,6 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
}
*num_transformed_glyphs = j;
}
return CAIRO_STATUS_SUCCESS;
}

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

@ -78,6 +78,13 @@ _cairo_hull_init (cairo_hull_t *hull,
}
}
static inline cairo_int64_t
_slope_length (cairo_slope_t *slope)
{
return _cairo_int64_add (_cairo_int32x32_64_mul (slope->dx, slope->dx),
_cairo_int32x32_64_mul (slope->dy, slope->dy));
}
static int
_cairo_hull_vertex_compare (const void *av, const void *bv)
{
@ -87,21 +94,21 @@ _cairo_hull_vertex_compare (const void *av, const void *bv)
ret = _cairo_slope_compare (&a->slope, &b->slope);
/* In the case of two vertices with identical slope from the
extremal point discard the nearer point. */
/*
* In the case of two vertices with identical slope from the
* extremal point discard the nearer point.
*/
if (ret == 0) {
cairo_fixed_48_16_t a_dist, b_dist;
a_dist = ((cairo_fixed_48_16_t) a->slope.dx * a->slope.dx +
(cairo_fixed_48_16_t) a->slope.dy * a->slope.dy);
b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx +
(cairo_fixed_48_16_t) b->slope.dy * b->slope.dy);
int cmp;
cmp = _cairo_int64_cmp (_slope_length (&a->slope),
_slope_length (&b->slope));
/*
* Use the point's ids to ensure a total ordering.
* a well-defined ordering, and avoid setting discard on
* both points.
* Use the points' ids to ensure a well-defined ordering,
* and avoid setting discard on both points.
*/
if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) {
if (cmp < 0 || (cmp == 0 && a->id < b->id)) {
a->discard = 1;
ret = -1;
} else {

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

@ -60,6 +60,10 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
case PIXMAN_g4: case PIXMAN_g1:
case PIXMAN_yuy2: case PIXMAN_yv12:
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
case PIXMAN_x2b10g10r10:
case PIXMAN_a2b10g10r10:
#endif
default:
return CAIRO_FORMAT_INVALID;
}
@ -81,6 +85,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_a2b2g2r2:
case PIXMAN_a1r1g1b1:
case PIXMAN_a1b1g1r1:
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
case PIXMAN_a2b10g10r10:
#endif
return CAIRO_CONTENT_COLOR_ALPHA;
case PIXMAN_x8r8g8b8:
case PIXMAN_x8b8g8r8:
@ -103,6 +110,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_g1:
case PIXMAN_yuy2:
case PIXMAN_yv12:
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
case PIXMAN_x2b10g10r10:
#endif
return CAIRO_CONTENT_COLOR;
case PIXMAN_a8:
case PIXMAN_a1:
@ -144,7 +154,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return &surface->base;
}
cairo_int_status_t
cairo_bool_t
_pixman_format_from_masks (cairo_format_masks_t *masks,
pixman_format_code_t *format_ret)
{
@ -166,13 +176,13 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
} else if (masks->alpha_mask) {
format_type = PIXMAN_TYPE_A;
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
return FALSE;
}
format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
if (! pixman_format_supported_destination (format))
return CAIRO_INT_STATUS_UNSUPPORTED;
return FALSE;
/* Sanity check that we got out of PIXMAN_FORMAT exactly what we
* expected. This avoid any problems from something bizarre like
@ -185,11 +195,11 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
masks->green_mask != format_masks.green_mask ||
masks->blue_mask != format_masks.blue_mask)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
return FALSE;
}
*format_ret = format;
return CAIRO_STATUS_SUCCESS;
return TRUE;
}
/* A mask consisting of N bits set to 1. */
@ -253,11 +263,9 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
int height,
int stride)
{
cairo_int_status_t status;
pixman_format_code_t pixman_format;
status = _pixman_format_from_masks (masks, &pixman_format);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
if (! _pixman_format_from_masks (masks, &pixman_format)) {
fprintf (stderr,
"Error: Cairo %s does not yet support the requested image format:\n"
"\tDepth: %d\n"
@ -265,8 +273,11 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
"\tRed mask: 0x%08lx\n"
"\tGreen mask: 0x%08lx\n"
"\tBlue mask: 0x%08lx\n"
#ifdef PACKAGE_BUGGREPORT
"Please file an enhancement request (quoting the above) at:\n"
PACKAGE_BUGREPORT "\n",
PACKAGE_BUGREPORT"\n"
#endif
,
cairo_version_string (),
masks->bpp, masks->alpha_mask,
masks->red_mask, masks->green_mask, masks->blue_mask);
@ -473,6 +484,7 @@ cairo_image_surface_create_for_data (unsigned char *data,
int stride)
{
pixman_format_code_t pixman_format;
int minstride;
if (! CAIRO_FORMAT_VALID (format))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
@ -480,6 +492,17 @@ cairo_image_surface_create_for_data (unsigned char *data,
if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
minstride = cairo_format_stride_for_width (format, width);
if (stride < 0) {
if (stride > -minstride) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
}
} else {
if (stride < minstride) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
}
}
pixman_format = _cairo_format_to_pixman_format_code (format);
return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
@ -510,7 +533,8 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data,
* inspection or modification.
*
* Return value: a pointer to the image data of this surface or %NULL
* if @surface is not an image surface.
* if @surface is not an image surface, or if cairo_surface_finish()
* has been called.
*
* Since: 1.2
**/
@ -548,8 +572,6 @@ cairo_image_surface_get_format (cairo_surface_t *surface)
return 0;
}
assert (CAIRO_FORMAT_VALID (image_surface->format));
return image_surface->format;
}
@ -766,11 +788,14 @@ _cairo_image_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_image_surface_t *surface = abstract_surface;
if (src->backend == surface->base.backend) {
*clone_offset_x = *clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;

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

@ -624,6 +624,35 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
return FALSE;
}
/* By pixel exact here, we mean a matrix that is composed only of
* 90 degree rotations, flips, and integer translations and produces a 1:1
* mapping between source and destination pixels. If we transform an image
* with a pixel-exact matrix, filtering is not useful.
*/
cairo_private cairo_bool_t
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
{
cairo_fixed_t x0_fixed, y0_fixed;
if (matrix->xy == 0.0 && matrix->yx == 0.0) {
if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
return FALSE;
if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
return FALSE;
} else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
return FALSE;
if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
return FALSE;
} else
return FALSE;
x0_fixed = _cairo_fixed_from_double (matrix->x0);
y0_fixed = _cairo_fixed_from_double (matrix->y0);
return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
}
/*
A circle in user space is transformed into an ellipse in device space.

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

@ -114,7 +114,7 @@ typedef struct _cairo_command_show_text_glyphs {
unsigned int num_glyphs;
cairo_text_cluster_t *clusters;
int num_clusters;
cairo_bool_t backward;
cairo_text_cluster_flags_t cluster_flags;
cairo_scaled_font_t *scaled_font;
} cairo_command_show_text_glyphs_t;

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

@ -216,32 +216,6 @@ _cairo_meta_surface_release_source_image (void *abstract_surface,
cairo_surface_destroy (&image->base);
}
static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
surface_pattern->surface = _cairo_surface_snapshot (surface);
cairo_surface_destroy (surface);
if (surface_pattern->surface->status)
return surface_pattern->surface->status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_paint (void *abstract_surface,
cairo_operator_t op,
@ -259,7 +233,7 @@ _cairo_meta_surface_paint (void *abstract_surface,
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
status = _cairo_pattern_init_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
@ -300,11 +274,11 @@ _cairo_meta_surface_mask (void *abstract_surface,
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
status = _cairo_pattern_init_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
status = _init_pattern_with_snapshot (&command->mask.base, mask);
status = _cairo_pattern_init_snapshot (&command->mask.base, mask);
if (status)
goto CLEANUP_SOURCE;
@ -346,7 +320,7 @@ _cairo_meta_surface_stroke (void *abstract_surface,
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
status = _cairo_pattern_init_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
@ -401,7 +375,7 @@ _cairo_meta_surface_fill (void *abstract_surface,
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
status = _cairo_pattern_init_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
@ -444,7 +418,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
@ -459,7 +433,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
status = _cairo_pattern_init_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
@ -495,7 +469,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
}
command->backward = backward;
command->cluster_flags = cluster_flags;
command->scaled_font = cairo_scaled_font_reference (scaled_font);
@ -848,7 +822,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
if (has_device_transform) {
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
cairo_matrix_multiply (&dev_ctm_inverse,
&surface->device_transform_inverse,
&target->device_transform_inverse,
&dev_ctm_inverse);
}
@ -952,7 +926,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
dev_glyphs, num_glyphs,
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
command->show_text_glyphs.backward,
command->show_text_glyphs.cluster_flags,
command->show_text_glyphs.scaled_font);
free (dev_glyphs);

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

@ -240,7 +240,7 @@ slim_hidden_def (cairo_text_cluster_free);
* @num_glyphs: number of glyphs
* @clusters: array of cluster mapping information
* @num_clusters: number of clusters in the mapping
* @backward: whether the text to glyphs mapping goes backward
* @cluster_flags: cluster flags
*
* Check that clusters cover the entire glyphs and utf8 arrays,
* and that cluster boundaries are UTF-8 boundaries.
@ -257,7 +257,7 @@ _cairo_validate_text_clusters (const char *utf8,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward)
cairo_text_cluster_flags_t cluster_flags)
{
cairo_status_t status;
unsigned int n_bytes = 0;

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

@ -41,10 +41,15 @@
#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
#define CAIRO_MUTEX_IMPL_PRIVATE_H
#include "cairo.h"
#if HAVE_CONFIG_H
#include "config.h"
#endif
#if HAVE_LOCKDEP
#include <lockdep.h>
#endif
/* A fully qualified no-operation statement */
#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0)
@ -72,6 +77,9 @@
* cairo_mutex_impl_t _cairo_some_mutex;
* </programlisting>
*
* - #define %CAIRO_MUTEX_IMPL_<NAME> 1 with suitable name for your platform. You
* can later use this symbol in cairo-system.c.
*
* - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
* proper statement to lock/unlock the mutex object passed in.
* You can (and should) assume that the mutex is already
@ -147,16 +155,13 @@
* poke around cairo-mutex-private.h for possible solutions.
*/
#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
#error "Do not include cairo-mutex-impl-private.h directly. Include cairo-mutex-type-private.h instead."
#endif
#if CAIRO_NO_MUTEX
/* No mutexes */
typedef int cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_NO 1
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
@ -168,18 +173,30 @@
typedef pthread_mutex_t cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_PTHREAD 1
#if HAVE_LOCKDEP
/* expose all mutexes to the validator */
# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL)
#endif
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
#if HAVE_LOCKDEP
# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex))
# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex))
#endif
# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
#if ! HAVE_LOCKDEP
# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
#endif
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#elif HAVE_WINDOWS_H /*******************************************************/
#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/
# include <windows.h>
typedef CRITICAL_SECTION cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_WIN32 1
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
@ -194,6 +211,7 @@
typedef HMTX cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_OS2 1
# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
@ -204,6 +222,7 @@
typedef BLocker* cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_BEOS 1
# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()

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

@ -31,24 +31,28 @@
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
*/
#ifndef CAIRO_FEATURES_H
/* This block is to just make this header file standalone */
#define CAIRO_MUTEX_DECLARE(mutex)
#endif
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock);
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock);
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex);
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
#if CAIRO_HAS_FT_FONT
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
#endif
#if CAIRO_HAS_XLIB_SURFACE
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex);
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
#endif
#if !defined (CAIRO_HAS_ATOMIC_OPS) || defined (CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER)
CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex);
#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER)
CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex)
#endif
/* Undefine, to err on unintended inclusion */

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

@ -41,10 +41,6 @@
#ifndef CAIRO_MUTEX_PRIVATE_H
#define CAIRO_MUTEX_PRIVATE_H
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "cairo-mutex-type-private.h"
CAIRO_BEGIN_DECLS
@ -62,7 +58,7 @@ cairo_private void _cairo_mutex_finalize (void);
/* Finally, extern the static mutexes and undef */
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex;
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE

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

@ -90,7 +90,6 @@
#endif /* CAIRO_MUTEX_IMPL_INIT */
#ifdef CAIRO_MUTEX_IMPL_FINI
/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
@ -169,6 +168,12 @@ typedef cairo_mutex_impl_t cairo_mutex_t;
#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI
#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
#ifndef CAIRO_MUTEX_IS_LOCKED
# define CAIRO_MUTEX_IS_LOCKED(name) 1
#endif
#ifndef CAIRO_MUTEX_IS_UNLOCKED
# define CAIRO_MUTEX_IS_UNLOCKED(name) 1
#endif
/* Debugging support */

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

@ -35,7 +35,7 @@
#include "cairo-mutex-private.h"
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER;
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
@ -61,7 +61,7 @@ void _cairo_mutex_initialize (void)
_cairo_mutex_initialized = TRUE;
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex)
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex);
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
}
@ -75,7 +75,7 @@ void _cairo_mutex_finalize (void)
_cairo_mutex_initialized = FALSE;
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex)
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex);
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
}

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

@ -1,12 +0,0 @@
/* Generated by configure. Do not edit */
#ifndef CAIRO_NO_FEATURES_H
#define CAIRO_NO_FEATURES_H
#include <cairo-features.h>
/* This is a dummy header, to trick gtk-doc only */
#define CAIRO_HAS_WIN32_FONT 1
#define CAIRO_HAS_WIN32_SURFACE 1
#endif

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

@ -38,6 +38,9 @@
#ifndef CAIRO_OS2_PRIVATE_H
#define CAIRO_OS2_PRIVATE_H
#include "cairo-os2.h"
#include "cairoint.h"
#define INCL_DOS
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
@ -49,9 +52,6 @@
# include <os2emx.h>
#endif
#include "cairo-os2.h"
#include "cairoint.h"
typedef struct _cairo_os2_surface
{
cairo_surface_t base;

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

@ -232,6 +232,12 @@ void _buffer_free (void *buffer)
#endif
}
/* XXX
* The cairo_os2_ini() and cairo_os2_fini() functions should be removed and
* the LibMain code moved to cairo-system.c. It should also call
* cairo_debug_reset_static_data() instead of duplicating its logic...
*/
#ifdef BUILD_CAIRO_DLL
/* The main DLL entry for DLL initialization and uninitialization */
/* Only include this code if we're about to build a DLL. */
@ -1202,6 +1208,8 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface,
* cairo_os2_surface_get_manual_window_refresh:
* @surface: the cairo surface to query the refresh mode from
*
* This space left intentionally blank.
*
* Return value: current refresh mode of the surface (true by default)
*
* Since: 1.4

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

@ -161,6 +161,9 @@ _cairo_memory_stream_copy (cairo_output_stream_t *base,
cairo_private int
_cairo_memory_stream_length (cairo_output_stream_t *stream);
cairo_private cairo_output_stream_t *
_cairo_null_stream_create (void);
/* cairo-base85-stream.c */
cairo_private cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
@ -169,4 +172,5 @@ _cairo_base85_stream_create (cairo_output_stream_t *output);
cairo_private cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output);
#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */

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

@ -116,6 +116,9 @@ closure_write (cairo_output_stream_t *stream,
cairo_output_stream_with_closure_t *stream_with_closure =
(cairo_output_stream_with_closure_t *) stream;
if (stream_with_closure->write_func == NULL)
return CAIRO_STATUS_SUCCESS;
return stream_with_closure->write_func (stream_with_closure->closure,
data, length);
}
@ -583,6 +586,9 @@ _cairo_output_stream_create_for_filename (const char *filename)
stdio_stream_t *stream;
FILE *file;
if (filename == NULL)
return _cairo_null_stream_create ();
file = fopen (filename, "wb");
if (file == NULL) {
switch (errno) {
@ -676,3 +682,26 @@ _cairo_memory_stream_length (cairo_output_stream_t *base)
return _cairo_array_num_elements (&stream->array);
}
static cairo_status_t
null_write (cairo_output_stream_t *base,
const unsigned char *data, unsigned int length)
{
return CAIRO_STATUS_SUCCESS;
}
cairo_output_stream_t *
_cairo_null_stream_create (void)
{
cairo_output_stream_t *stream;
stream = malloc (sizeof *stream);
if (stream == NULL) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
_cairo_output_stream_init (stream, null_write, NULL);
return stream;
}

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

@ -65,7 +65,7 @@ struct _cairo_paginated_surface_backend {
* before the mode is changed to RENDER.
*/
cairo_warn cairo_int_status_t
(*set_bounding_box) (void *surface,
(*set_bounding_box) (void *surface,
cairo_box_t *bbox);
/* Optional. Indicates whether the page requires fallback images.
@ -73,8 +73,11 @@ struct _cairo_paginated_surface_backend {
* mode is changed to RENDER.
*/
cairo_warn cairo_int_status_t
(*set_fallback_images_required)(void *surface,
cairo_bool_t fallbacks_required);
(*set_fallback_images_required) (void *surface,
cairo_bool_t fallbacks_required);
cairo_bool_t
(*supports_fine_grained_fallbacks) (void *surface);
};
/* A #cairo_paginated_surface_t provides a very convenient wrapper that

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

@ -108,6 +108,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
return &surface->base;
FAIL_CLEANUP_SURFACE:
cairo_surface_destroy (target);
free (surface);
FAIL:
return _cairo_surface_create_in_error (status);
@ -299,8 +300,10 @@ _paint_page (cairo_paginated_surface_t *surface)
if (analysis->status)
return _cairo_surface_set_error (surface->target, analysis->status);
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_ANALYZE);
status = _cairo_meta_surface_replay_and_create_regions (surface->meta,
analysis);
if (status || analysis->status) {
if (status == CAIRO_STATUS_SUCCESS)
status = analysis->status;
@ -325,43 +328,31 @@ _paint_page (cairo_paginated_surface_t *surface)
goto FAIL;
}
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
/* Finer grained fallbacks are currently only supported for some
* surface types */
switch (surface->target->type) {
case CAIRO_SURFACE_TYPE_PDF:
case CAIRO_SURFACE_TYPE_PS:
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
has_supported = _cairo_analysis_surface_has_supported (analysis);
has_page_fallback = FALSE;
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
break;
case CAIRO_SURFACE_TYPE_IMAGE:
case CAIRO_SURFACE_TYPE_XLIB:
case CAIRO_SURFACE_TYPE_XCB:
case CAIRO_SURFACE_TYPE_GLITZ:
case CAIRO_SURFACE_TYPE_QUARTZ:
case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
case CAIRO_SURFACE_TYPE_WIN32:
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_DIRECTFB:
case CAIRO_SURFACE_TYPE_SVG:
case CAIRO_SURFACE_TYPE_OS2:
default:
if (_cairo_analysis_surface_has_unsupported (analysis)) {
has_supported = FALSE;
has_page_fallback = TRUE;
} else {
has_supported = TRUE;
has_page_fallback = FALSE;
}
has_finegrained_fallback = FALSE;
break;
if (surface->backend->supports_fine_grained_fallbacks != NULL &&
surface->backend->supports_fine_grained_fallbacks (surface->target))
{
has_supported = _cairo_analysis_surface_has_supported (analysis);
has_page_fallback = FALSE;
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
}
else
{
if (_cairo_analysis_surface_has_unsupported (analysis)) {
has_supported = FALSE;
has_page_fallback = TRUE;
} else {
has_supported = TRUE;
has_page_fallback = FALSE;
}
has_finegrained_fallback = FALSE;
}
if (has_supported) {
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_RENDER);
status = _cairo_meta_surface_replay_region (surface->meta,
surface->target,
CAIRO_META_REGION_NATIVE);
@ -370,10 +361,12 @@ _paint_page (cairo_paginated_surface_t *surface)
goto FAIL;
}
if (has_page_fallback)
{
if (has_page_fallback) {
cairo_box_int_t box;
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_FALLBACK);
box.p1.x = 0;
box.p1.y = 0;
box.p2.x = surface->width;
@ -383,13 +376,13 @@ _paint_page (cairo_paginated_surface_t *surface)
goto FAIL;
}
if (has_finegrained_fallback)
{
if (has_finegrained_fallback) {
cairo_region_t *region;
cairo_box_int_t *boxes;
int num_boxes, i;
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_FALLBACK);
/* Reset clip region before drawing the fall back images */
status = _cairo_surface_intersect_clip_path (surface->target,
@ -622,7 +615,7 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_paginated_surface_t *surface = abstract_surface;
@ -644,14 +637,12 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
* show_glyphs functions, (which would get less testing and likely
* lead to bugs).
*/
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
cluster_flags,
scaled_font);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
return status;
}

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

@ -215,8 +215,24 @@ _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
cairo_traps_t *traps)
{
if (_cairo_path_fixed_is_box (path, NULL)) {
return _cairo_traps_tessellate_convex_quad (traps,
path->buf_head.base.points);
cairo_point_t *p = path->buf_head.base.points;
cairo_point_t *top_left, *bot_right;
top_left = &p[0];
bot_right = &p[2];
if (top_left->x > bot_right->x || top_left->y > bot_right->y) {
int n;
/* not a simple cairo_rectangle() */
for (n = 0; n < 4; n++) {
if (p[n].x <= top_left->x && p[n].y <= top_left->y)
top_left = &p[n];
if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
bot_right = &p[n];
}
}
return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
}
return CAIRO_INT_STATUS_UNSUPPORTED;

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

@ -829,7 +829,6 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
static cairo_status_t
_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
double mag, remain, step_length = 0;
double slope_dx, slope_dy;
@ -838,17 +837,19 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
cairo_slope_t dev_slope;
cairo_bool_t fully_in_bounds = TRUE;
cairo_line_t segment;
cairo_bool_t fully_in_bounds;
cairo_status_t status;
stroker->has_initial_sub_path = stroker->dash_starts_on;
if (p1->x == p2->x && p1->y == p2->y)
return CAIRO_STATUS_SUCCESS;
fully_in_bounds = TRUE;
if (stroker->has_bounds &&
(!_cairo_box_contains_point (&stroker->bounds, p1) ||
!_cairo_box_contains_point (&stroker->bounds, p2)))
(! _cairo_box_contains_point (&stroker->bounds, p1) ||
! _cairo_box_contains_point (&stroker->bounds, p2)))
{
fully_in_bounds = FALSE;
}
@ -858,8 +859,11 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
if (!_compute_normalized_device_slope (&slope_dx, &slope_dy, stroker->ctm_inverse, &mag))
if (! _compute_normalized_device_slope (&slope_dx, &slope_dy,
stroker->ctm_inverse, &mag))
{
return CAIRO_STATUS_SUCCESS;
}
remain = mag;
segment.p1 = *p1;
@ -872,48 +876,57 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
if (fully_in_bounds ||
_cairo_box_intersects_line_segment (&stroker->bounds, &segment))
if (stroker->dash_on &&
(fully_in_bounds ||
(! stroker->has_first_face && stroker->dash_starts_on) ||
_cairo_box_intersects_line_segment (&stroker->bounds, &segment)))
{
if (stroker->dash_on) {
status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, &dev_slope, slope_dx, slope_dy, &sub_start, &sub_end);
status = _cairo_stroker_add_sub_edge (stroker,
&segment.p1, &segment.p2,
&dev_slope,
slope_dx, slope_dy,
&sub_start, &sub_end);
if (status)
return status;
if (stroker->has_current_face) {
/* Join with final face from previous segment */
status = _cairo_stroker_join (stroker,
&stroker->current_face,
&sub_start);
if (status)
return status;
if (stroker->has_current_face) {
/* Join with final face from previous segment */
status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
stroker->has_current_face = FALSE;
if (status)
return status;
} else if (!stroker->has_first_face && stroker->dash_starts_on) {
/* Save sub path's first face in case needed for closing join */
stroker->first_face = sub_start;
stroker->has_first_face = TRUE;
} else {
/* Cap dash start if not connecting to a previous segment */
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
if (status)
return status;
}
if (remain) {
/* Cap dash end if not at end of segment */
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
if (status)
return status;
} else {
stroker->current_face = sub_end;
stroker->has_current_face = TRUE;
}
stroker->has_current_face = FALSE;
} else if (! stroker->has_first_face && stroker->dash_starts_on) {
/* Save sub path's first face in case needed for closing join */
stroker->first_face = sub_start;
stroker->has_first_face = TRUE;
} else {
if (stroker->has_current_face) {
/* Cap final face from previous segment */
status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
if (status)
return status;
stroker->has_current_face = FALSE;
}
/* Cap dash start if not connecting to a previous segment */
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
if (status)
return status;
}
if (remain) {
/* Cap dash end if not at end of segment */
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
if (status)
return status;
} else {
stroker->current_face = sub_end;
stroker->has_current_face = TRUE;
}
} else {
if (stroker->has_current_face) {
/* Cap final face from previous segment */
status = _cairo_stroker_add_trailing_cap (stroker,
&stroker->current_face);
if (status)
return status;
stroker->has_current_face = FALSE;
}
}
@ -921,24 +934,32 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
segment.p1 = segment.p2;
}
if (stroker->dash_on && !stroker->has_current_face) {
if (stroker->dash_on && ! stroker->has_current_face) {
/* This segment ends on a transition to dash_on, compute a new face
* and add cap for the begining of the next dash_on step.
* and add cap for the beginning of the next dash_on step.
*
* Note: this will create a degenerate cap if this is not the last line
* in the path. Whether this behaviour is desirable or not is debatable.
* On one side these degnerate caps can not be reproduced with regular path stroking.
* On the other side Acroread 7 also produces the degenerate caps. */
_compute_face (point, &dev_slope, slope_dx, slope_dy, stroker, &stroker->current_face);
stroker->has_current_face = TRUE;
status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
* On one side these degenerate caps can not be reproduced with regular
* path stroking.
* On the other hand, Acroread 7 also produces the degenerate caps.
*/
_compute_face (point, &dev_slope,
slope_dx, slope_dy,
stroker,
&stroker->current_face);
status = _cairo_stroker_add_leading_cap (stroker,
&stroker->current_face);
if (status)
return status;
stroker->has_current_face = TRUE;
}
stroker->current_point = *point;
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -1257,12 +1278,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
cairo_status_t status;
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
cairo_fixed_t half_line_width = stroker->half_line_width;
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
cairo_point_t *a, *b;
cairo_point_t r[4];
int i;
for (i = 0; i < stroker->num_segments; i++) {
cairo_point_t *a, *b;
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
a = &stroker->segments[i].p1;
b = &stroker->segments[i].p2;
@ -1315,6 +1336,14 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
else if (lengthen_final)
b->x -= half_line_width;
}
if (a->x > b->x) {
cairo_point_t *t;
t = a;
a = b;
b = t;
}
} else {
if (a->y < b->y) {
if (lengthen_initial)
@ -1331,27 +1360,27 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
else if (lengthen_final)
b->y -= half_line_width;
}
if (a->y > b->y) {
cairo_point_t *t;
t = a;
a = b;
b = t;
}
}
/* Form the rectangle by expanding by half the line width in
* either perdendicular direction. */
r[0] = *a;
r[1] = *b;
r[2] = *b;
r[3] = *a;
* either perpendicular direction. */
if (a->y == b->y) {
r[0].y -= half_line_width;
r[1].y -= half_line_width;
r[2].y += half_line_width;
r[3].y += half_line_width;
a->y -= half_line_width;
b->y += half_line_width;
} else {
r[0].x -= half_line_width;
r[1].x -= half_line_width;
r[2].x += half_line_width;
r[3].x += half_line_width;
a->x -= half_line_width;
b->x += half_line_width;
}
status = _cairo_traps_tessellate_convex_quad (stroker->traps, r);
status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
if (status)
return status;
}
@ -1439,7 +1468,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
/* This special-case rectilinear stroker only supports
* miter-joined lines (not curves) and no dashing and a
* translation-only matrix (though it could probably be extended
* to support a matrix with uniform, integer sacling).
* to support a matrix with uniform, integer scaling).
*
* It also only supports horizontal and vertical line_to
* elements. But we don't catch that here, but instead return
@ -1484,11 +1513,10 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
BAIL:
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
if (status)
_cairo_traps_fini (traps);
_cairo_traps_clear (traps);
return status;
}

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

@ -192,6 +192,36 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
cairo_status_t status;
/* We don't bother doing any fancy copy-on-write implementation
* for the pattern's data. It's generally quite tiny. */
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
/* But we do let the surface snapshot stuff be as fancy as it
* would like to be. */
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
surface_pattern->surface = _cairo_surface_snapshot (surface);
cairo_surface_destroy (surface);
if (surface_pattern->surface->status)
return surface_pattern->surface->status;
}
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_pattern_fini (cairo_pattern_t *pattern)
{
@ -784,7 +814,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return pattern->status;
return _cairo_user_data_array_set_data (&pattern->user_data,
key, user_data, destroy);
@ -1217,6 +1247,8 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
pixman_gradient_stop_t pixman_stops_static[2];
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
unsigned int i;
int clone_offset_x, clone_offset_y;
cairo_matrix_t matrix = pattern->base.matrix;
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
@ -1236,11 +1268,46 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
{
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
pixman_point_fixed_t p1, p2;
cairo_fixed_t xdim, ydim;
p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
xdim = linear->p2.x - linear->p1.x;
ydim = linear->p2.y - linear->p1.y;
/*
* Transform the matrix to avoid overflow when converting between
* cairo_fixed_t and pixman_fixed_t (without incurring performance
* loss when the transformation is unnecessary).
*
* XXX: Consider converting out-of-range co-ordinates and transforms.
* Having a function to compute the required transformation to
* "normalize" a given bounding box would be generally useful -
* cf linear patterns, gradient patterns, surface patterns...
*/
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
_cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
{
double sf;
if (xdim > ydim)
sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
else
sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
cairo_matrix_scale (&matrix, sf, sf);
}
else
{
p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
}
pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
pixman_stops,
@ -1284,7 +1351,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
}
attr->x_offset = attr->y_offset = 0;
attr->matrix = pattern->base.matrix;
attr->matrix = matrix;
attr->extend = pattern->base.extend;
attr->filter = CAIRO_FILTER_NEAREST;
attr->acquired = FALSE;
@ -1332,7 +1399,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
return image->base.status;
}
_cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
_cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform);
if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
cairo_surface_destroy (&image->base);
pixman_image_unref (pixman_image);
@ -1366,7 +1433,10 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
pixman_image_unref (pixman_image);
status = _cairo_surface_clone_similar (dst, &image->base,
0, 0, width, height, out);
0, 0, width, height,
&clone_offset_x,
&clone_offset_y,
out);
cairo_surface_destroy (&image->base);
@ -1628,6 +1698,71 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
return FALSE;
}
/**
* _cairo_pattern_analyze_filter:
* @pattern: surface pattern
* @pad_out: location to store necessary padding in the source image, or %NULL
* Returns: the optimized #cairo_filter_t to use with @pattern.
*
* Analyze the filter to determine how much extra needs to be sampled
* from the source image to account for the filter radius and whether
* we can optimize the filter to a simpler value.
*
* XXX: We don't actually have any way of querying the backend for
* the filter radius, so we just guess base on what we know that
* backends do currently (see bug #10508)
*/
static cairo_filter_t
_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern,
double *pad_out)
{
double pad;
cairo_filter_t optimized_filter;
switch (pattern->base.filter) {
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
/* If source pixels map 1:1 onto destination pixels, we do
* not need to filter (and do not want to filter, since it
* will cause blurriness)
*/
if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) {
pad = 0.;
optimized_filter = CAIRO_FILTER_NEAREST;
} else {
/* 0.5 is enough for a bilinear filter. It's possible we
* should defensively use more for CAIRO_FILTER_BEST, but
* without a single example, it's hard to know how much
* more would be defensive...
*/
pad = 0.5;
optimized_filter = pattern->base.filter;
}
break;
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
case CAIRO_FILTER_GAUSSIAN:
default:
pad = 0.;
optimized_filter = pattern->base.filter;
break;
}
if (pad_out)
*pad_out = pad;
return optimized_filter;
}
static double
_pixman_nearest_sample (double d)
{
return ceil (d - .5);
}
static cairo_int_status_t
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
cairo_surface_t *dst,
@ -1640,18 +1775,44 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
{
cairo_int_status_t status;
int tx, ty;
double pad;
attr->acquired = FALSE;
attr->extend = pattern->base.extend;
attr->filter = pattern->base.filter;
attr->filter = _cairo_pattern_analyze_filter (pattern, &pad);
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
&tx, &ty))
{
cairo_matrix_init_identity (&attr->matrix);
attr->x_offset = tx;
attr->y_offset = ty;
attr->filter = CAIRO_FILTER_NEAREST;
}
else if (attr->filter == CAIRO_FILTER_NEAREST)
{
/*
* For NEAREST, we can remove the fractional translation component
* from the transformation - this ensures that the pattern will always
* hit fast-paths in the backends for simple transformations that
* become (almost) identity, without loss of quality.
*/
attr->matrix = pattern->base.matrix;
attr->matrix.x0 = 0;
attr->matrix.y0 = 0;
if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
/* The rounding here is rather peculiar as it needs to match the
* rounding performed on the sample coordinate used by pixman.
*/
attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
} else {
attr->matrix.x0 = pattern->base.matrix.x0;
attr->matrix.y0 = pattern->base.matrix.y0;
}
attr->x_offset = attr->y_offset = 0;
tx = ty = 0;
}
else
{
@ -1734,8 +1895,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
return status;
}
if (_cairo_surface_is_image (dst))
{
if (_cairo_surface_is_image (dst)) {
cairo_image_surface_t *image;
status = _cairo_surface_acquire_source_image (pattern->surface,
@ -1746,60 +1906,73 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
*out = &image->base;
attr->acquired = TRUE;
}
else
{
} else {
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (pattern->surface, &extents);
if (status)
return status;
/* If we're repeating, we just play it safe and clone the entire surface. */
/* If requested width and height are -1, clone the entire surface.
* This is relied on in the svg backend. */
if (attr->extend == CAIRO_EXTEND_REPEAT ||
(width == (unsigned int) -1 && height == (unsigned int) -1)) {
x = extents.x;
y = extents.y;
width = extents.width;
height = extents.height;
} else {
/* If we're repeating, we just play it safe and clone the
* entire surface - i.e. we use the existing extents.
*/
if (attr->extend != CAIRO_EXTEND_REPEAT) {
cairo_rectangle_int_t sampled_area;
/* Otherwise, we first transform the rectangle to the
* coordinate space of the source surface so that we can
* clone only that portion of the surface that will be
* read. */
if (! _cairo_matrix_is_identity (&attr->matrix)) {
* read.
*/
if (_cairo_matrix_is_identity (&attr->matrix)) {
sampled_area.x = x;
sampled_area.y = y;
sampled_area.width = width;
sampled_area.height = height;
} else {
double x1 = x;
double y1 = y;
double x2 = x + width;
double y2 = y + height;
cairo_bool_t is_tight;
_cairo_matrix_transform_bounding_box (&attr->matrix,
&x1, &y1, &x2, &y2,
&is_tight);
NULL);
sampled_area.x = floor (x1 - pad);
sampled_area.y = floor (y1 - pad);
sampled_area.width = ceil (x2 + pad) - sampled_area.x;
sampled_area.height = ceil (y2 + pad) - sampled_area.y;
/* The transform_bounding_box call may have resulted
* in a region larger than the surface, but we never
* want to clone more than the surface itself, (we
* know we're not repeating at this point due to the
* above.
*
* XXX: The one padding here is to account for filter
* radius. It's a workaround right now, until we get a
* proper fix. (see bug #10508)
*/
x = MAX (0, floor (x1) - 1);
y = MAX (0, floor (y1) - 1);
width = MIN (extents.width, ceil (x2) + 1) - x;
height = MIN (extents.height, ceil (y2) + 1) - y;
}
x += tx;
y += ty;
sampled_area.x += tx;
sampled_area.y += ty;
/* Never acquire a larger area than the source itself */
_cairo_rectangle_intersect (&extents, &sampled_area);
}
status = _cairo_surface_clone_similar (dst, pattern->surface,
x, y, width, height, out);
extents.x, extents.y,
extents.width, extents.height,
&x, &y, out);
if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) {
if (_cairo_matrix_is_identity (&attr->matrix)) {
attr->x_offset -= x;
attr->y_offset -= y;
} else {
cairo_matrix_t m;
x -= attr->x_offset;
y -= attr->y_offset;
attr->x_offset = 0;
attr->y_offset = 0;
cairo_matrix_init_translate (&m, -x, -y);
cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
}
}
}
return status;
@ -1820,6 +1993,9 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
* A convenience function to obtain a surface to use as the source for
* drawing on @dst.
*
* Note that this function is only suitable for use when the destination
* surface is pixel based and 1 device unit maps to one pixel.
*
* Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
**/
cairo_int_status_t
@ -2049,15 +2225,20 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_surface_t *surface = surface_pattern->surface;
cairo_matrix_t imatrix;
double x1, y1, x2, y2;
double pad;
status = _cairo_surface_get_extents (surface, &surface_extents);
if (status)
return status;
x1 = surface_extents.x;
y1 = surface_extents.y;
x2 = x1 + surface_extents.width;
y2 = y1 + surface_extents.height;
/* The filter can effectively enlarge the extents of the
* pattern, so extend as necessary.
*/
_cairo_pattern_analyze_filter (surface_pattern, &pad);
x1 = surface_extents.x - pad;
y1 = surface_extents.y - pad;
x2 = surface_extents.x + surface_extents.width + pad;
y2 = surface_extents.y + surface_extents.height + pad;
imatrix = pattern->matrix;
status = cairo_matrix_invert (&imatrix);

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

@ -159,7 +159,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font);
#endif /* CAIRO_PDF_OPERATORS_H */

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

@ -571,6 +571,16 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
for (i = 0; i < num_dashes; i += 2) {
if (dash[i] == 0.0) {
/* Do not modify the dashes in-place, as we may need to also
* replay this stroke to an image fallback.
*/
if (dash == style->dash) {
dash = _cairo_malloc_ab (num_dashes, sizeof (double));
if (dash == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (dash, style->dash, num_dashes * sizeof (double));
}
/* If we're at the front of the list, we first rotate
* two elements from the end of the list to the front
* of the list before folding away the 0.0. Or, if
@ -581,10 +591,10 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
double last_two[2];
if (num_dashes == 2) {
if (dash != style->dash)
free (dash);
free (dash);
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
/* The cases of num_dashes == 0, 1, or 3 elements
* cannot exist, so the rotation of 2 elements
* will always be safe */
@ -1251,7 +1261,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_scaled_font_subsets_glyph_t subset_glyph;
@ -1293,7 +1303,10 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
/* Fallback to using ActualText to map zero or more glyphs to a
* unicode string. */
_cairo_pdf_operators_flush_glyphs (pdf_operators);
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
if (status)
return status;
@ -1316,7 +1329,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
if (status)
return status;
if (backward)
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
cur_glyph--;
else
cur_glyph++;
@ -1338,7 +1351,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
@ -1357,7 +1370,9 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
pdf_operators->is_new_text_object = FALSE;
if (pdf_operators->in_text_object == FALSE) {
_cairo_pdf_operators_begin_text (pdf_operators);
status = _cairo_pdf_operators_begin_text (pdf_operators);
if (status)
return status;
/* Force Tm and Tf to be emitted when starting a new text
* object.*/
@ -1376,7 +1391,10 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
if (pdf_operators->is_new_text_object ||
! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
{
_cairo_pdf_operators_flush_glyphs (pdf_operators);
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
x = glyphs[0].x;
y = glyphs[0].y;
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
@ -1391,25 +1409,25 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
if (num_clusters > 0) {
cur_text = utf8;
if (backward)
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
cur_glyph = glyphs + num_glyphs;
else
cur_glyph = glyphs;
for (i = 0; i < num_clusters; i++) {
if (backward)
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
cur_glyph -= clusters[i].num_glyphs;
status = _cairo_pdf_operators_emit_cluster (pdf_operators,
cur_text,
clusters[i].num_bytes,
cur_glyph,
clusters[i].num_glyphs,
backward,
cluster_flags,
scaled_font);
if (status)
return status;
cur_text += clusters[i].num_bytes;
if (!backward)
if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
cur_glyph += clusters[i].num_glyphs;
}
} else {

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

@ -96,7 +96,7 @@ typedef struct _cairo_pdf_smask_group
int num_glyphs;
cairo_text_cluster_t *clusters;
int num_clusters;
cairo_bool_t backward;
cairo_bool_t cluster_flags;
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;

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

@ -44,10 +44,11 @@
#include "cairo-pdf.h"
#include "cairo-pdf-surface-private.h"
#include "cairo-pdf-operators-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-paginated-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-type3-glyph-surface-private.h"
#include <time.h>
@ -325,7 +326,10 @@ BAIL0:
/**
* cairo_pdf_surface_create_for_stream:
* @write_func: a #cairo_write_func_t to accept the output data
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
* to indicate a no-op @write_func. With a no-op @write_func,
* the surface may be queried or used as a source without
* generating any temporary files.
* @closure: the closure argument for @write_func
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
@ -362,7 +366,10 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
/**
* cairo_pdf_surface_create:
* @filename: a filename for the PDF output (must be writable)
* @filename: a filename for the PDF output (must be writable), %NULL may be
* used to specify no output. This will generate a PDF surface that
* may be queried and used as a source, without generating a
* temporary file.
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
*
@ -1276,8 +1283,8 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
}
static cairo_int_status_t
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_bool_t has_fallbacks)
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_bool_t has_fallbacks)
{
cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
@ -1290,6 +1297,12 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
{
return TRUE;
}
/* Emit alpha channel from the image into the given data, providing
* an id that can be used to reference the resulting SMask object.
*
@ -2609,13 +2622,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
{
cairo_status_t status;
int alpha;
cairo_bool_t is_solid_color = FALSE;
cairo_color_t *solid_color;
cairo_color_t *solid_color = NULL;
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
is_solid_color = TRUE;
solid_color = &solid->color;
}
@ -2624,13 +2635,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
if (gradient->n_stops == 1) {
is_solid_color = TRUE;
if (gradient->n_stops == 1)
solid_color = &gradient->stops[0].color;
}
}
if (is_solid_color) {
if (solid_color != NULL) {
if (surface->current_pattern_is_solid_color == FALSE ||
surface->current_color_red != solid_color->red ||
surface->current_color_green != solid_color->green ||
@ -2960,7 +2969,11 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
"<%02x> ",
i + 1);
}
_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
font_subset->utf8[i + 1]);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"\n");
}
@ -3480,6 +3493,41 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_pdf_surface_t *surface = closure;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status2;
unsigned int i;
cairo_surface_t *type3_surface;
cairo_output_stream_t *null_stream;
null_stream = _cairo_null_stream_create ();
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
null_stream,
_cairo_pdf_emit_imagemask,
surface->font_subsets);
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
_cairo_pdf_surface_add_font,
surface);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
font_subset->glyphs[i]);
if (status)
break;
}
cairo_surface_destroy (type3_surface);
status2 = _cairo_output_stream_destroy (null_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -3512,9 +3560,14 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
_cairo_pdf_group_resources_clear (&surface->resources);
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_pdf_emit_imagemask);
_cairo_pdf_emit_imagemask,
surface->font_subsets);
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
_cairo_pdf_surface_add_font,
surface);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_pdf_surface_open_stream (surface,
@ -3525,18 +3578,11 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
break;
glyphs[i] = surface->pdf_stream.self;
if (i == 0) {
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
surface->output,
&bbox,
&widths[i]);
} else {
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->output,
font_subset->glyphs[i],
&bbox,
&widths[i]);
}
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->output,
font_subset->glyphs[i],
&bbox,
&widths[i]);
if (status)
break;
@ -3642,6 +3688,10 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
"]\n");
free (widths);
_cairo_output_stream_printf (surface->output,
" /Resources\n");
_cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
" /ToUnicode %d 0 R\n",
@ -3713,6 +3763,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
{
cairo_status_t status;
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
_cairo_pdf_surface_analyze_user_font_subset,
surface);
if (status)
goto BAIL;
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
_cairo_pdf_surface_emit_unscaled_font_subset,
surface);
@ -3722,6 +3778,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
_cairo_pdf_surface_emit_scaled_font_subset,
surface);
if (status)
goto BAIL;
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
_cairo_pdf_surface_emit_scaled_font_subset,
surface);
BAIL:
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
@ -3985,7 +4047,7 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
group->utf8, group->utf8_len,
group->glyphs, group->num_glyphs,
group->clusters, group->num_clusters,
group->backward,
group->cluster_flags,
group->scaled_font);
break;
}
@ -4414,19 +4476,21 @@ _cairo_pdf_surface_mask (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_smask_group_t *group;
cairo_status_t status, status2;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
status = _cairo_pdf_surface_analyze_operation (surface, op, source);
if (status != CAIRO_STATUS_SUCCESS &&
status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
return status;
cairo_status_t source_status, mask_status;
status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask);
if (status2 != CAIRO_STATUS_SUCCESS)
return status2;
source_status = _cairo_pdf_surface_analyze_operation (surface, op, source);
if (_cairo_status_is_error (source_status))
return source_status;
return status;
mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask);
if (_cairo_status_is_error (mask_status))
return mask_status;
return _cairo_analysis_surface_merge_status (source_status,
mask_status);
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (status)
@ -4756,7 +4820,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
@ -4858,7 +4922,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
cluster_flags,
scaled_font);
if (status)
return status;
@ -4922,9 +4986,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_show_text_glyphs,
};
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
static const cairo_paginated_surface_backend_t
cairo_pdf_surface_paginated_backend = {
_cairo_pdf_surface_start_page,
_cairo_pdf_surface_set_paginated_mode,
NULL, /* set_bounding_box */
_cairo_pdf_surface_has_fallback_images,
_cairo_pdf_surface_supports_fine_grained_fallbacks,
};

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

@ -524,7 +524,7 @@ read_png (png_rw_ptr read_func,
png_get_IHDR (png, info,
&png_width, &png_height, &depth,
&color_type, &interlace, NULL, NULL);
if (depth != 8 || interlace != PNG_INTERLACE_NONE ||
if (depth != 8 ||
! (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
{

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

@ -36,11 +36,6 @@
#include "cairoint.h"
/* private functions */
static cairo_status_t
_cairo_polygon_grow (cairo_polygon_t *polygon);
void
_cairo_polygon_init (cairo_polygon_t *polygon)
{
@ -57,31 +52,17 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
void
_cairo_polygon_fini (cairo_polygon_t *polygon)
{
if (polygon->edges && polygon->edges != polygon->edges_embedded)
if (polygon->edges != polygon->edges_embedded)
free (polygon->edges);
polygon->edges = NULL;
polygon->edges_size = 0;
polygon->num_edges = 0;
polygon->has_current_point = FALSE;
}
cairo_status_t
_cairo_polygon_status (cairo_polygon_t *polygon)
{
return polygon->status;
}
/* make room for at least one more edge */
static cairo_status_t
static cairo_bool_t
_cairo_polygon_grow (cairo_polygon_t *polygon)
{
cairo_edge_t *new_edges;
int old_size = polygon->edges_size;
int new_size = 2 * old_size;
assert (polygon->num_edges <= polygon->edges_size);
int new_size = 4 * old_size;
if (polygon->edges == polygon->edges_embedded) {
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
@ -92,34 +73,34 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
new_size, sizeof (cairo_edge_t));
}
if (new_edges == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (new_edges == NULL) {
polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return FALSE;
}
polygon->edges = new_edges;
polygon->edges_size = new_size;
return CAIRO_STATUS_SUCCESS;
return TRUE;
}
void
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
static void
_cairo_polygon_add_edge (cairo_polygon_t *polygon,
const cairo_point_t *p1,
const cairo_point_t *p2)
{
cairo_edge_t *edge;
if (polygon->status)
return;
/* drop horizontal edges */
if (p1->y == p2->y)
goto DONE;
if (polygon->num_edges >= polygon->edges_size) {
polygon->status = _cairo_polygon_grow (polygon);
if (polygon->status)
if (polygon->num_edges == polygon->edges_size) {
if (! _cairo_polygon_grow (polygon))
return;
}
edge = &polygon->edges[polygon->num_edges];
edge = &polygon->edges[polygon->num_edges++];
if (p1->y < p2->y) {
edge->edge.p1 = *p1;
edge->edge.p2 = *p2;
@ -130,18 +111,14 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
edge->clockWise = 0;
}
polygon->num_edges++;
DONE:
_cairo_polygon_move_to (polygon, p2);
}
void
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
_cairo_polygon_move_to (cairo_polygon_t *polygon,
const cairo_point_t *point)
{
if (polygon->status)
return;
if (! polygon->has_current_point)
polygon->first_point = *point;
@ -150,24 +127,18 @@ _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
}
void
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
_cairo_polygon_line_to (cairo_polygon_t *polygon,
const cairo_point_t *point)
{
if (polygon->status)
return;
if (polygon->has_current_point) {
if (polygon->has_current_point)
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
} else {
else
_cairo_polygon_move_to (polygon, point);
}
}
void
_cairo_polygon_close (cairo_polygon_t *polygon)
{
if (polygon->status)
return;
if (polygon->has_current_point) {
_cairo_polygon_add_edge (polygon,
&polygon->current_point,

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

@ -72,10 +72,7 @@ typedef struct cairo_ps_surface {
cairo_bool_t use_string_datasource;
cairo_bool_t current_pattern_is_solid_color;
double current_color_red;
double current_color_green;
double current_color_blue;
double current_color_alpha;
cairo_color_t current_color;
int num_pages;

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

@ -40,6 +40,19 @@
* Adrian Johnson <ajohnson@redneon.com>
*/
/*
* Design of the PS output:
*
* The PS output is harmonised with the PDF operations using PS procedures
* to emulate the PDF operators.
*
* This has a number of advantages:
* 1. A large chunk of code is shared between the PDF and PS backends.
* See cairo-pdf-operators.
* 2. Using gs to do PS -> PDF and PDF -> PS will always work well.
*/
#define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */
#include "cairoint.h"
#include "cairo-ps.h"
@ -173,6 +186,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/S { stroke } bind def\n"
"/f { fill } bind def\n"
"/f* { eofill } bind def\n"
"/B { fill stroke } bind def\n"
"/B* { eofill stroke } bind def\n"
"/n { newpath } bind def\n"
"/W { clip } bind def\n"
"/W* { eoclip } bind def\n"
@ -196,12 +211,12 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
" cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
"/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
" { cairo_selectfont } if } bind def\n"
" { pop cairo_selectfont } if } bind def\n"
"/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
" /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
" /cairo_font where { cairo_selectfont } if } bind def\n"
" /cairo_font where { pop cairo_selectfont } if } bind def\n"
"/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
" cairo_store_point /cairo_font where { cairo_selectfont } if } bind def\n"
" cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n"
"/g { setgray } bind def\n"
"/rg { setrgbcolor } bind def\n"
"/d1 { setcachedevice } bind def\n");
@ -426,6 +441,32 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_ps_surface_t *surface = closure;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
unsigned int i;
cairo_surface_t *type3_surface;
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask,
surface->font_subsets);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
font_subset->glyphs[i]);
if (status)
break;
}
cairo_surface_destroy (type3_surface);
return status;
}
static cairo_status_t
_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -439,6 +480,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
cairo_surface_t *type3_surface;
double width;
if (font_subset->num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
#if DEBUG_PS
_cairo_output_stream_printf (surface->final_stream,
"%% _cairo_ps_surface_emit_type3_font_subset\n");
@ -453,9 +497,10 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask);
_cairo_ps_emit_imagemask,
surface->font_subsets);
for (i = 1; i < font_subset->num_glyphs; i++) {
for (i = 0; i < font_subset->num_glyphs; i++) {
if (font_subset->glyph_names != NULL) {
_cairo_output_stream_printf (surface->final_stream,
"Encoding %d /%s put\n",
@ -472,20 +517,13 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
for (i = 0; i < font_subset->num_glyphs; i++) {
_cairo_output_stream_printf (surface->final_stream,
" { %% %d\n", i);
if (i == 0) {
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
surface->final_stream,
&bbox,
&width);
} else {
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->final_stream,
font_subset->glyphs[i],
&bbox,
&width);
}
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->final_stream,
font_subset->glyphs[i],
&bbox,
&width);
if (status)
return status;
break;
_cairo_output_stream_printf (surface->final_stream,
" }\n");
@ -506,13 +544,16 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
}
}
cairo_surface_destroy (type3_surface);
if (status)
return status;
_cairo_output_stream_printf (surface->final_stream,
"] def\n"
"/FontBBox [%f %f %f %f] def\n"
"/BuildChar {\n"
" exch /Glyphs get\n"
" exch get exec\n"
" exch get\n"
" 10 dict begin exec end\n"
"} bind def\n"
"currentdict\n"
"end\n"
@ -586,6 +627,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
"%% _cairo_ps_surface_emit_font_subsets\n");
#endif
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
_cairo_ps_surface_analyze_user_font_subset,
surface);
if (status)
goto BAIL;
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
_cairo_ps_surface_emit_unscaled_font_subset,
surface);
@ -595,7 +642,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
_cairo_ps_surface_emit_scaled_font_subset,
surface);
if (status)
goto BAIL;
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
_cairo_ps_surface_emit_scaled_font_subset,
surface);
BAIL:
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
surface->font_subsets = NULL;
@ -734,7 +786,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
/**
* cairo_ps_surface_create:
* @filename: a filename for the PS output (must be writable)
* @filename: a filename for the PS output (must be writable), %NULL may be
* used to specify no output. This will generate a PS surface that
* may be queried and used as a source, without generating a
* temporary file.
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
*
@ -774,7 +829,10 @@ cairo_ps_surface_create (const char *filename,
/**
* cairo_ps_surface_create_for_stream:
* @write_func: a #cairo_write_func_t to accept the output data
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
* to indicate a no-op @write_func. With a no-op @write_func,
* the surface may be queried or used as a source without
* generating any temporary files.
* @closure: the closure argument for @write_func
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
@ -1422,12 +1480,25 @@ static cairo_bool_t
_gradient_pattern_supported (cairo_ps_surface_t *surface,
cairo_pattern_t *pattern)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
uint16_t alpha;
cairo_extend_t extend;
unsigned int i;
if (surface->ps_level == CAIRO_PS_LEVEL_2)
return FALSE;
surface->ps_level_used = CAIRO_PS_LEVEL_3;
if (gradient->n_stops == 0)
return TRUE;
/* Alpha gradients are only supported (by flattening the alpha)
* if there is no variation in the alpha across the gradient. */
alpha = gradient->stops[0].color.alpha_short;
for (i = 0; i < gradient->n_stops; i++) {
if (gradient->stops[i].color.alpha_short != alpha)
return FALSE;
}
extend = cairo_pattern_get_extend (pattern);
/* Radial gradients are currently only supported when one circle
@ -1454,6 +1525,8 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface,
}
}
surface->ps_level_used = CAIRO_PS_LEVEL_3;
return TRUE;
}
@ -1504,7 +1577,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
* surface. If the analysis surface determines that there is
* anything drawn under this operation, a fallback image will be
* used. Otherwise the operation will be replayed during the
* render stage and we blend the transarency into the white
* render stage and we blend the transparency into the white
* background to convert the pattern to opaque.
*/
@ -2089,21 +2162,19 @@ _cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface,
double *green,
double *blue)
{
*red = color->red;
*red = color->red;
*green = color->green;
*blue = color->blue;
*blue = color->blue;
if (!CAIRO_COLOR_IS_OPAQUE(color)) {
if (! CAIRO_COLOR_IS_OPAQUE (color)) {
*red *= color->alpha;
*green *= color->alpha;
*blue *= color->alpha;
if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
*red = ((color->red_short >> 8) + one_minus_alpha) / 255.0;
*green = ((color->green_short >> 8) + one_minus_alpha) / 255.0;
*blue = ((color->blue_short >> 8) + one_minus_alpha) / 255.0;
} else {
*red = (color->red_short >> 8) / 255.0;
*green = (color->green_short >> 8) / 255.0;
*blue = (color->blue_short >> 8) / 255.0;
double one_minus_alpha = 1. - color->alpha;
*red += one_minus_alpha;
*green += one_minus_alpha;
*blue += one_minus_alpha;
}
}
}
@ -2826,10 +2897,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
if (surface->current_pattern_is_solid_color == FALSE ||
surface->current_color_red != solid->color.red ||
surface->current_color_green != solid->color.green ||
surface->current_color_blue != solid->color.blue ||
surface->current_color_alpha != solid->color.alpha)
! _cairo_color_equal (&surface->current_color, &solid->color))
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
@ -2838,10 +2906,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
surface->current_pattern_is_solid_color = TRUE;
surface->current_color_red = solid->color.red;
surface->current_color_green = solid->color.green;
surface->current_color_blue = solid->color.blue;
surface->current_color_alpha = solid->color.alpha;
surface->current_color = solid->color;
}
return CAIRO_STATUS_SUCCESS;
@ -3223,6 +3288,12 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
return _cairo_output_stream_get_status (surface->stream);
}
static cairo_bool_t
_cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface)
{
return TRUE;
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
CAIRO_SURFACE_TYPE_PS,
_cairo_ps_surface_create_similar,
@ -3261,4 +3332,6 @@ static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backen
_cairo_ps_surface_start_page,
_cairo_ps_surface_set_paginated_mode,
_cairo_ps_surface_set_bounding_box,
NULL, /* _cairo_ps_surface_has_fallback_images, */
_cairo_ps_surface_supports_fine_grained_fallbacks,
};

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

@ -225,6 +225,7 @@ FINISH:
static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
CAIRO_FONT_TYPE_QUARTZ,
_cairo_quartz_font_face_destroy,
NULL, /* direct implementation */
_cairo_quartz_font_face_scaled_font_create
};
@ -277,24 +278,27 @@ _cairo_quartz_scaled_to_face (void *abstract_font)
}
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)
_cairo_quartz_font_get_implementation (cairo_toy_font_face_t *toy_face,
cairo_scaled_font_t **font_face_out)
{
static cairo_user_data_key_t impl_font_face_key;
cairo_font_face_t *face;
cairo_status_t status;
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;
face = cairo_font_face_get_user_data (&toy_face->base,
&impl_font_face_key);
if (face) {
*font_face_out = face;
return CAIRO_STATUS_SUCCESS;
}
quartz_font_ensure_symbols();
if (!_cairo_quartz_font_symbols_present)
if (! _cairo_quartz_font_symbols_present)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* handle CSS-ish faces */
@ -345,7 +349,7 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
if (!cgFont) {
/* Give up */
return CAIRO_STATUS_NO_MEMORY;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
face = cairo_quartz_font_face_create_for_cgfont (cgFont);
@ -354,6 +358,35 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
if (face->status)
return face->status;
status = cairo_font_face_set_user_data (&toy_face->base,
&impl_font_face_key,
face,
(cairo_destroy_func_t) cairo_font_face_destroy);
if (status) {
cairo_font_face_destroy (face);
return status;
}
*font_face_out = face;
return CAIRO_STATUS_SUCCESS;
}
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)
{
cairo_font_face_t *face;
cairo_scaled_font_t *scaled_font;
cairo_status_t status;
status = _cairo_quartz_font_get_implementation (toy_face, &face);
if (status)
return status;
status = _cairo_quartz_font_face_scaled_font_create (face,
font_matrix, ctm,
options,
@ -363,7 +396,6 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
return status;
*font_out = scaled_font;
return CAIRO_STATUS_SUCCESS;
}
@ -743,6 +775,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
CAIRO_FONT_TYPE_QUARTZ,
_cairo_quartz_font_get_implementation,
_cairo_quartz_font_create_toy,
_cairo_quartz_font_fini,
_cairo_quartz_font_scaled_glyph_init,

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

@ -36,99 +36,13 @@
#include "cairoint.h"
#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
#include "cairo-quartz-image.h"
#endif
#include "cairo-quartz-private.h"
#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
CGImageRef
_cairo_quartz_create_cgimage (cairo_format_t format,
unsigned int width,
unsigned int height,
unsigned int stride,
void *data,
cairo_bool_t interpolate,
CGColorSpaceRef colorSpaceOverride,
CGDataProviderReleaseDataCallback releaseCallback,
void *releaseInfo)
{
CGImageRef image = NULL;
CGDataProviderRef dataProvider = NULL;
CGColorSpaceRef colorSpace = colorSpaceOverride;
CGBitmapInfo bitinfo;
int bitsPerComponent, bitsPerPixel;
switch (format) {
case CAIRO_FORMAT_ARGB32:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
case CAIRO_FORMAT_RGB24:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
/* XXX -- should use CGImageMaskCreate! */
case CAIRO_FORMAT_A8:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceGray();
bitinfo = kCGImageAlphaNone;
bitsPerComponent = 8;
bitsPerPixel = 8;
break;
case CAIRO_FORMAT_A1:
default:
return NULL;
}
dataProvider = CGDataProviderCreateWithData (releaseInfo,
data,
height * stride,
releaseCallback);
if (!dataProvider) {
// manually release
if (releaseCallback)
releaseCallback (releaseInfo, data, height * stride);
goto FINISH;
}
image = CGImageCreate (width, height,
bitsPerComponent,
bitsPerPixel,
stride,
colorSpace,
bitinfo,
dataProvider,
NULL,
interpolate,
kCGRenderingIntentDefault);
FINISH:
CGDataProviderRelease (dataProvider);
if (colorSpace != colorSpaceOverride)
CGColorSpaceRelease (colorSpace);
return image;
}
#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
static void
DataProviderReleaseCallback (void *info, const void *data, size_t size)
{
@ -370,5 +284,3 @@ cairo_quartz_image_surface_get_image (cairo_surface_t *asurface)
return (cairo_surface_t*) surface->imageSurface;
}
#endif /* CAIRO_HAS_QUARTZ_IMAGE_SURFACE */

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

@ -40,7 +40,7 @@
#include "cairoint.h"
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#if CAIRO_HAS_QUARTZ_SURFACE
#include "cairo-quartz.h"
typedef struct cairo_quartz_surface {
@ -95,11 +95,10 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
CGFontRef
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
#else
# error Cairo was not compiled with support for the quartz backend
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
#if CAIRO_HAS_CGFONT_FONT
CGFontRef
_cairo_cgfont_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
#endif /* CAIRO_HAS_CGFONT_FONT */
#endif /* CAIRO_QUARTZ_PRIVATE_H */

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

@ -160,6 +160,87 @@ static void quartz_ensure_symbols(void)
_cairo_quartz_symbol_lookup_done = TRUE;
}
CGImageRef
_cairo_quartz_create_cgimage (cairo_format_t format,
unsigned int width,
unsigned int height,
unsigned int stride,
void *data,
cairo_bool_t interpolate,
CGColorSpaceRef colorSpaceOverride,
CGDataProviderReleaseDataCallback releaseCallback,
void *releaseInfo)
{
CGImageRef image = NULL;
CGDataProviderRef dataProvider = NULL;
CGColorSpaceRef colorSpace = colorSpaceOverride;
CGBitmapInfo bitinfo;
int bitsPerComponent, bitsPerPixel;
switch (format) {
case CAIRO_FORMAT_ARGB32:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
case CAIRO_FORMAT_RGB24:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceRGB();
bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
bitsPerComponent = 8;
bitsPerPixel = 32;
break;
/* XXX -- should use CGImageMaskCreate! */
case CAIRO_FORMAT_A8:
if (colorSpace == NULL)
colorSpace = CGColorSpaceCreateDeviceGray();
bitinfo = kCGImageAlphaNone;
bitsPerComponent = 8;
bitsPerPixel = 8;
break;
case CAIRO_FORMAT_A1:
default:
return NULL;
}
dataProvider = CGDataProviderCreateWithData (releaseInfo,
data,
height * stride,
releaseCallback);
if (!dataProvider) {
// manually release
if (releaseCallback)
releaseCallback (releaseInfo, data, height * stride);
goto FINISH;
}
image = CGImageCreate (width, height,
bitsPerComponent,
bitsPerPixel,
stride,
colorSpace,
bitinfo,
dataProvider,
NULL,
interpolate,
kCGRenderingIntentDefault);
FINISH:
CGDataProviderRelease (dataProvider);
if (colorSpace != colorSpaceOverride)
CGColorSpaceRelease (colorSpace);
return image;
}
static inline cairo_bool_t
_cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) {
if (cgc == NULL)
@ -745,10 +826,13 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
*image_out = NULL;
} else {
cairo_image_surface_t *isurf_snap = NULL;
isurf_snap = _cairo_surface_snapshot (isurf);
isurf_snap = (cairo_image_surface_t*) _cairo_surface_snapshot ((cairo_surface_t*) isurf);
if (isurf_snap == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (isurf_snap->base.type != CAIRO_SURFACE_TYPE_IMAGE)
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
image = _cairo_quartz_create_cgimage (isurf_snap->format,
isurf_snap->width,
isurf_snap->height,
@ -1481,8 +1565,8 @@ _cairo_quartz_surface_create_similar (void *abstract_surface,
// verify width and height of surface
if (!_cairo_quartz_verify_surface_size(width, height)) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
return _cairo_surface_create_in_error (_cairo_error
(CAIRO_STATUS_NO_MEMORY));
}
return cairo_quartz_surface_create (format, width, height);
@ -1495,6 +1579,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_quartz_surface_t *new_surface = NULL;
@ -1513,6 +1599,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
*clone_out = (cairo_surface_t*)
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
width, height);
*clone_offset_x = 0;
*clone_offset_y = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -1523,6 +1611,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
*clone_out = (cairo_surface_t*)
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
qsurf->extents.width, qsurf->extents.height);
*clone_offset_x = 0;
*clone_offset_y = 0;
return CAIRO_STATUS_SUCCESS;
}
}
@ -1561,7 +1651,9 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
CGImageRelease (quartz_image);
FINISH:
FINISH:
*clone_offset_x = src_x;
*clone_offset_y = src_y;
*clone_out = (cairo_surface_t*) new_surface;
return CAIRO_STATUS_SUCCESS;

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

@ -57,12 +57,12 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
cairo_public CGContextRef
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
#if CAIRO_HAS_QUARTZ_FONT
/*
* Quartz font support
*/
#ifdef CAIRO_HAS_QUARTZ_FONT
cairo_public cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font);

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

@ -37,14 +37,8 @@
#ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H
#define CAIRO_REFRENCE_COUNT_PRIVATE_H
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "cairo-atomic-private.h"
CAIRO_BEGIN_DECLS
/* Encapsulate operations on the object's reference count */
typedef struct {
cairo_atomic_int_t ref_count;
@ -65,6 +59,4 @@ typedef struct {
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0)
CAIRO_END_DECLS
#endif

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

@ -37,11 +37,13 @@
#ifndef CAIRO_REGION_PRIVATE_H
#define CAIRO_REGION_PRIVATE_H
#include <pixman.h>
#include "cairo-compiler-private.h"
#include "cairo-types-private.h"
#include <pixman.h>
CAIRO_BEGIN_DECLS
/* #cairo_region_t is defined in cairoint.h */
struct _cairo_region {
@ -109,4 +111,6 @@ cairo_private pixman_region_overlap_t
_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box);
CAIRO_END_DECLS
#endif /* CAIRO_REGION_PRIVATE_H */

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

@ -281,6 +281,41 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure);
/**
* _cairo_scaled_font_subsets_foreach_user:
* @font_subsets: a #cairo_scaled_font_subsets_t
* @font_subset_callback: a function to be called for each font subset
* @closure: closure data for the callback function
*
* Iterate over each unique scaled font subset as created by calls to
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
* unique pairs of (font_id, subset_id) as returned by
* _cairo_scaled_font_subsets_map_glyph().
*
* For each subset, @font_subset_callback will be called and will be
* provided with both a #cairo_scaled_font_subset_t object containing
* all the glyphs in the subset as well as the value of @closure.
*
* The #cairo_scaled_font_subset_t object contains the scaled_font,
* the font_id, and the subset_id corresponding to all glyphs
* belonging to the subset. In addition, it contains an array providing
* a mapping between subset glyph indices and the original scaled font
* glyph indices.
*
* The index of the array corresponds to subset_glyph_index values
* returned by _cairo_scaled_font_subsets_map_glyph() while the
* values of the array correspond to the scaled_font_glyph_index
* values passed as input to the same function.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* %CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure);
/**
* _cairo_scaled_font_subset_create_glyph_names:
* @font_subsets: a #cairo_scaled_font_subsets_t

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

@ -57,11 +57,18 @@ typedef enum {
CAIRO_SUBSETS_COMPOSITE
} cairo_subsets_type_t;
typedef enum {
CAIRO_SUBSETS_FOREACH_UNSCALED,
CAIRO_SUBSETS_FOREACH_SCALED,
CAIRO_SUBSETS_FOREACH_USER
} cairo_subsets_foreach_type_t;
typedef struct _cairo_sub_font {
cairo_hash_entry_t base;
cairo_bool_t is_scaled;
cairo_bool_t is_composite;
cairo_bool_t is_user;
cairo_scaled_font_subsets_t *parent;
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
@ -126,7 +133,7 @@ typedef struct _cairo_string_entry {
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph);
@ -265,6 +272,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
sub_font->is_scaled = is_scaled;
sub_font->is_composite = is_composite;
sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face);
_cairo_sub_font_init_key (sub_font, scaled_font);
sub_font->parent = parent;
@ -282,12 +290,15 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
}
sub_font->next = NULL;
/* Reserve first glyph in subset for the .notdef glyph */
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
if (status) {
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
free (sub_font);
return status;
/* Reserve first glyph in subset for the .notdef glyph except for
* Type 3 fonts */
if (! _cairo_font_face_is_user (scaled_font->font_face)) {
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
if (status) {
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
free (sub_font);
return status;
}
}
*sub_font_out = sub_font;
@ -437,12 +448,13 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
(cairo_hash_entry_t **) &sub_font_glyph))
{
cairo_scaled_glyph_t *scaled_glyph;
if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
{
cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
@ -450,25 +462,33 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
sub_font->current_subset++;
sub_font->num_glyphs_in_current_subset = 0;
/* Reserve first glyph in subset for the .notdef glyph */
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
if (status)
return status;
/* Reserve first glyph in subset for the .notdef glyph
* except for Type 3 fonts */
if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) {
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
if (status)
return status;
}
}
_cairo_scaled_font_freeze_cache (sub_font->scaled_font);
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (status)
if (status) {
_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
return status;
}
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset,
scaled_glyph->metrics.x_advance,
scaled_glyph->metrics.y_advance);
_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
if (sub_font_glyph == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -641,7 +661,7 @@ cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
@ -691,13 +711,16 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
* _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
* empty glyphs in this case so we can put the glyph in a unscaled
* subset. */
if (scaled_font_glyph_index == 0) {
if (scaled_font_glyph_index == 0 ||
_cairo_font_face_is_user (scaled_font->font_face)) {
status = CAIRO_STATUS_SUCCESS;
} else {
_cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_scaled_glyph_lookup (scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
_cairo_scaled_font_thaw_cache (scaled_font);
}
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@ -744,6 +767,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
subset_glyph->is_scaled,
subset_glyph->is_composite,
&sub_font);
if (status) {
cairo_scaled_font_destroy (unscaled_font);
return status;
@ -805,19 +829,32 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
}
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
scaled_font_glyph_index,
utf8, utf8_len,
subset_glyph);
subset_glyph);
}
static cairo_status_t
_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure,
cairo_bool_t is_scaled)
cairo_subsets_foreach_type_t type)
{
cairo_sub_font_collection_t collection;
cairo_sub_font_t *sub_font;
cairo_bool_t is_scaled, is_user;
is_scaled = FALSE;
is_user = FALSE;
if (type == CAIRO_SUBSETS_FOREACH_USER)
is_user = TRUE;
if (type == CAIRO_SUBSETS_FOREACH_SCALED ||
type == CAIRO_SUBSETS_FOREACH_USER)
{
is_scaled = TRUE;
}
if (is_scaled)
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
@ -848,7 +885,9 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
sub_font = font_subsets->unscaled_sub_fonts_list;
while (sub_font) {
_cairo_sub_font_collect (sub_font, &collection);
if (sub_font->is_user == is_user)
_cairo_sub_font_collect (sub_font, &collection);
sub_font = sub_font->next;
}
free (collection.utf8);
@ -865,7 +904,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
font_subset_callback,
closure,
TRUE);
CAIRO_SUBSETS_FOREACH_SCALED);
}
cairo_status_t
@ -876,7 +915,18 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *fo
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
font_subset_callback,
closure,
FALSE);
CAIRO_SUBSETS_FOREACH_UNSCALED);
}
cairo_status_t
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure)
{
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
font_subset_callback,
closure,
CAIRO_SUBSETS_FOREACH_USER);
}
static cairo_bool_t
@ -937,23 +987,27 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
goto CLEANUP_HASH;
}
subset->glyph_names[0] = strdup (".notdef");
if (subset->glyph_names[0] == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_HASH;
i = 0;
if (! _cairo_font_face_is_user (subset->scaled_font->font_face)) {
subset->glyph_names[0] = strdup (".notdef");
if (subset->glyph_names[0] == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_HASH;
}
status = create_string_entry (subset->glyph_names[0], &entry);
if (status)
goto CLEANUP_HASH;
status = _cairo_hash_table_insert (names, &entry->base);
if (status) {
free (entry);
goto CLEANUP_HASH;
}
i++;
}
status = create_string_entry (subset->glyph_names[0], &entry);
if (status)
goto CLEANUP_HASH;
status = _cairo_hash_table_insert (names, &entry->base);
if (status) {
free (entry);
goto CLEANUP_HASH;
}
for (i = 1; i < subset->num_glyphs; i++) {
for (; i < subset->num_glyphs; i++) {
utf8 = subset->utf8[i];
utf16 = NULL;
utf16_len = 0;

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

@ -145,6 +145,9 @@
* and note that glyph origin = device-space origin.
*/
static void
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font);
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
@ -377,11 +380,11 @@ _cairo_scaled_font_map_destroy (void)
font_map->num_holdovers--;
/* release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
/* This releases the font_map lock to avoid the possibility of a
* recursive deadlock when the scaled font destroy closure gets
* called
*/
_cairo_scaled_font_fini (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
free (scaled_font);
}
@ -407,22 +410,26 @@ _cairo_scaled_font_map_destroy (void)
*
* The reason we have to create a fake scaled font instead of just using
* scaled_font is for lifecycle management: we need to (or rather,
* other code needs to) reference the scaked_font in the hash.
* other code needs to) reference the scaled_font in the hash table.
* We can't do that on the input scaled_font as it may be freed by
* font backend upon error.
*/
void
cairo_status_t
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
cairo_scaled_font_t *placeholder_scaled_font;
assert (CAIRO_MUTEX_IS_LOCKED (_cairo_scaled_font_map_mutex));
status = scaled_font->status;
if (status)
return status;
placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t));
if (!placeholder_scaled_font) {
status = CAIRO_STATUS_NO_MEMORY;
goto FREE;
}
if (placeholder_scaled_font == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* full initialization is wasteful, but who cares... */
status = _cairo_scaled_font_init (placeholder_scaled_font,
@ -432,32 +439,26 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t
&scaled_font->options,
NULL);
if (status)
goto FINI;
goto FREE_PLACEHOLDER;
placeholder_scaled_font->placeholder = TRUE;
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
&placeholder_scaled_font->hash_entry);
if (status)
goto UNLOCK_KEY;
goto FINI_PLACEHOLDER;
goto UNLOCK;
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
UNLOCK_KEY:
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
return CAIRO_STATUS_SUCCESS;
FINI:
_cairo_scaled_font_fini (placeholder_scaled_font);
FREE:
FINI_PLACEHOLDER:
_cairo_scaled_font_fini_internal (placeholder_scaled_font);
FREE_PLACEHOLDER:
free (placeholder_scaled_font);
status = _cairo_scaled_font_set_error (scaled_font, status);
UNLOCK:
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
return _cairo_scaled_font_set_error (scaled_font, status);
}
void
@ -473,33 +474,36 @@ _cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t
(cairo_hash_entry_t**) &placeholder_scaled_font);
assert (found);
assert (placeholder_scaled_font->placeholder);
assert (CAIRO_MUTEX_IS_LOCKED (placeholder_scaled_font->mutex));
_cairo_hash_table_remove (cairo_scaled_font_map->hash_table,
&scaled_font->hash_entry);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
cairo_scaled_font_destroy (placeholder_scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
static void
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *scaled_font)
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font)
{
/* reference the place holder so it doesn't go away */
cairo_scaled_font_reference (scaled_font);
cairo_scaled_font_reference (placeholder_scaled_font);
/* now unlock the fontmap mutex so creation has a chance to finish */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
/* wait on placeholder mutex until we are awaken */
CAIRO_MUTEX_LOCK (scaled_font->mutex);
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
/* ok, creation done. just clean up and back out */
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
cairo_scaled_font_destroy (placeholder_scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
cairo_scaled_font_destroy (scaled_font);
}
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
@ -569,11 +573,11 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
sizeof(cairo_matrix_t)) == 0 &&
memcmp ((unsigned char *)(&key_a->ctm.xx),
(unsigned char *)(&key_b->ctm.xx),
sizeof(double) * 4) == 0 &&
sizeof(cairo_matrix_t)) == 0 &&
cairo_font_options_equal (&key_a->options, &key_b->options));
}
/* XXX: This 256 number is arbitary---we've never done any measurement
/* XXX: This 256 number is arbitrary---we've never done any measurement
* of this. In fact, having a per-font glyph caches each managed
* separately is probably not what we want anyway. Would probably be
* much better to have a single cache for glyphs with random
@ -656,6 +660,10 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
void
_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
{
/* ensure we do not modify an error object */
assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_cache_freeze (scaled_font->glyphs);
}
@ -663,11 +671,14 @@ void
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
{
_cairo_cache_thaw (scaled_font->glyphs);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
void
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
{
assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
_cairo_cache_destroy (scaled_font->glyphs);
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
_cairo_scaled_glyph_destroy,
@ -701,8 +712,8 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
static void
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
{
scaled_font->finished = TRUE;
@ -724,6 +735,16 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
_cairo_user_data_array_fini (&scaled_font->user_data);
}
void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
/* Release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called. */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini_internal (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
/**
* cairo_scaled_font_create:
* @font_face: a #cairo_font_face_t
@ -735,8 +756,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
* @ctm: user to device transformation matrix with which the font will
* be used.
* @options: options to use when getting metrics for the font and
* rendering with it. A %NULL pointer will be interpreted as
* meaning the default options.
* rendering with it.
*
* Creates a #cairo_scaled_font_t object from a font face and matrices that
* describe the size of the font and the environment in which it will
@ -752,6 +772,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_font_options_t *options)
{
cairo_status_t status;
cairo_font_face_t *impl_face;
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
@ -765,11 +786,19 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
/* Note that degenerate ctm or font_matrix *are* allowed.
* We want to support a font size of 0. */
if (font_face->backend->get_implementation != NULL) {
/* indirect implementation, lookup the face that is used for the key */
status = font_face->backend->get_implementation (font_face, &impl_face);
if (status)
return _cairo_scaled_font_create_in_error (status);
} else
impl_face = font_face;
font_map = _cairo_scaled_font_map_lock ();
if (font_map == NULL)
return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_scaled_font_init_key (&key, font_face,
_cairo_scaled_font_init_key (&key, impl_face,
font_matrix, ctm, options);
scaled_font = font_map->mru_scaled_font;
if (scaled_font != NULL &&
@ -876,7 +905,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
/* We can't call _cairo_scaled_font_destroy here since it expects
* that the font has already been successfully inserted into the
* hash table. */
_cairo_scaled_font_fini (scaled_font);
_cairo_scaled_font_fini_internal (scaled_font);
free (scaled_font);
return _cairo_scaled_font_create_in_error (status);
}
@ -980,6 +1009,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
cairo_scaled_font_t *lru = NULL;
cairo_scaled_font_map_t *font_map;
assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex));
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return;
@ -1020,7 +1051,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_map_unlock ();
/* If we pulled an item from the holdovers array, (while the font
* map lock was held, of course), then there is no way that anyone
@ -1029,7 +1060,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* as we never want to call into any backend function with a lock
* held. */
if (lru) {
_cairo_scaled_font_fini (lru);
_cairo_scaled_font_fini_internal (lru);
free (lru);
}
}
@ -1103,12 +1134,19 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return scaled_font->status;
return _cairo_user_data_array_set_data (&scaled_font->user_data,
key, user_data, destroy);
}
static cairo_bool_t
_cairo_scaled_font_is_frozen (cairo_scaled_font_t *scaled_font)
{
return CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex) &&
scaled_font->glyphs->freeze_count > 0;
}
/* Public font API follows. */
/**
@ -1122,6 +1160,15 @@ void
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents)
{
if (scaled_font->status) {
extents->ascent = 0.0;
extents->descent = 0.0;
extents->height = 0.0;
extents->max_x_advance = 0.0;
extents->max_y_advance = 0.0;
return;
}
*extents = scaled_font->extents;
}
slim_hidden_def (cairo_scaled_font_extents);
@ -1169,8 +1216,10 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
&glyphs, &num_glyphs,
NULL, NULL,
NULL);
if (status)
if (status) {
status = _cairo_scaled_font_set_error (scaled_font, status);
goto ZERO_EXTENTS;
}
cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
free (glyphs);
@ -1241,7 +1290,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
return;
}
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
@ -1310,7 +1358,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
UNLOCK:
_cairo_scaled_font_thaw_cache (scaled_font);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
slim_hidden_def (cairo_scaled_font_glyph_extents);
@ -1325,8 +1372,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* @num_glyphs: pointer to number of glyphs
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
* @num_clusters: pointer to number of clusters, or %NULL
* @backward: pointer to whether the text to glyphs mapping goes backward, or
* %NULL
* @cluster_flags: pointer to location to store cluster flags corresponding to the
* output @clusters, or %NULL
*
* Converts UTF-8 text to an array of glyphs, optionally with cluster
* mapping, that can be used to render later using @scaled_font.
@ -1336,11 +1383,12 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* entries available there. If the provided glyph array is too short for
* the conversion, a new glyph array is allocated using cairo_glyph_allocate()
* and placed in @glyphs. Upon return, @num_glyphs always contains the
* number of generated glyphs. If the value @glyphs points at has changed
* number of generated glyphs. If the value @glyphs points to has changed
* after the call, the user is responsible for freeing the allocated glyph
* array using cairo_glyph_free().
* array using cairo_glyph_free(). This may happen even if the provided
* array was large enough.
*
* If @clusters is not %NULL, @num_clusters and @backward should not be %NULL,
* If @clusters is not %NULL, @num_clusters and @cluster_flags should not be %NULL,
* and cluster mapping will be computed.
* The semantics of how cluster array allocation works is similar to the glyph
* array. That is,
@ -1351,7 +1399,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* and placed in @clusters. Upon return, @num_clusters always contains the
* number of generated clusters. If the value @clusters points at has changed
* after the call, the user is responsible for freeing the allocated cluster
* array using cairo_text_cluster_free().
* array using cairo_text_cluster_free(). This may happen even if the provided
* array was large enough.
*
* In the simplest case, @glyphs and @clusters can point to %NULL initially
* and a suitable array will be allocated. In code:
@ -1362,21 +1411,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* int num_glyphs;
* cairo_text_cluster_t *clusters = NULL;
* int num_clusters;
* cairo_bool_t backward;
* cairo_text_cluster_flags_t cluster_flags;
*
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
* x, y,
* utf8, utf8_len,
* &amp;glyphs, &amp;num_glyphs,
* &amp;clusters, &amp;num_clusters,
* &amp;backward);
* &amp;clusters, &amp;num_clusters, &amp;cluster_flags);
*
* if (status == CAIRO_STATUS_SUCCESS) {
* cairo_show_text_glyphs (cr,
* utf8, utf8_len,
* *glyphs, *num_glyphs,
* *clusters, *num_clusters,
* *backward);
* *clusters, *num_clusters, *cluster_flags);
*
* cairo_glyph_free (*glyphs);
* cairo_text_cluster_free (*clusters);
@ -1414,21 +1461,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* cairo_text_cluster_t stack_clusters[40];
* cairo_text_cluster_t *clusters = stack_clusters;
* int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]);
* cairo_bool_t backward;
* cairo_text_cluster_flags_t cluster_flags;
*
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
* x, y,
* utf8, utf8_len,
* &amp;glyphs, &amp;num_glyphs,
* &amp;clusters, &amp;num_clusters,
* &amp;backward);
* &amp;clusters, &amp;num_clusters, &amp;cluster_flags);
*
* if (status == CAIRO_STATUS_SUCCESS) {
* cairo_show_text_glyphs (cr,
* utf8, utf8_len,
* *glyphs, *num_glyphs,
* *clusters, *num_clusters,
* *backward);
* *clusters, *num_clusters, *cluster_flags);
*
* if (glyphs != stack_glyphs)
* cairo_glyph_free (*glyphs);
@ -1437,7 +1482,7 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
* }
* </programlisting></informalexample>
*
* For details of how @clusters, @num_clusters, and @backward map input
* For details of how @clusters, @num_clusters, and @cluster_flags map input
* UTF-8 text to the output glyphs see cairo_show_text_glyphs().
*
* The output values can be readily passed to cairo_show_text_glyphs()
@ -1461,7 +1506,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
cairo_text_cluster_flags_t *cluster_flags)
{
int i;
int num_chars = 0;
@ -1488,9 +1533,9 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
utf8_len = 0;
/* No NULLs for non-NULLs! */
if ((utf8_len && utf8 == NULL) ||
(clusters && num_clusters == NULL) ||
(clusters && backward == NULL)) {
if ((utf8_len && utf8 == NULL) ||
(clusters && num_clusters == NULL) ||
(clusters && cluster_flags == NULL)) {
status = CAIRO_STATUS_NULL_POINTER;
goto BAIL;
}
@ -1511,12 +1556,12 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
num_clusters = NULL;
}
if (backward) {
*backward = FALSE;
if (cluster_flags) {
*cluster_flags = FALSE;
}
if (!clusters && backward) {
backward = NULL;
if (!clusters && cluster_flags) {
cluster_flags = NULL;
}
/* Apart from that, no negatives */
@ -1537,7 +1582,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
goto BAIL;
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
orig_glyphs = *glyphs;
@ -1549,7 +1593,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
cluster_flags);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
@ -1583,7 +1627,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
status = _cairo_validate_text_clusters (utf8, utf8_len,
*glyphs, *num_glyphs,
*clusters, *num_clusters,
*backward);
*cluster_flags);
}
}
@ -1643,7 +1687,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
DONE: /* error that should be logged on scaled_font happened */
_cairo_scaled_font_thaw_cache (scaled_font);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
if (status) {
*num_glyphs = 0;
@ -1692,6 +1735,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
if (scaled_font->status)
return scaled_font->status;
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
int left, top;
@ -1703,7 +1748,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
return _cairo_scaled_font_set_error (scaled_font, status);
break;
/* XXX glyph images are snapped to pixel locations */
x = _cairo_lround (glyphs[i].x);
@ -1719,6 +1764,11 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
if (top < min.y) min.y = top;
if (bottom > max.y) max.y = bottom;
}
_cairo_scaled_font_thaw_cache (scaled_font);
if (status)
return _cairo_scaled_font_set_error (scaled_font, status);
if (min.x < max.x && min.y < max.y) {
extents->x = min.x;
extents->width = max.x - min.x;
@ -1728,6 +1778,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
extents->x = extents->y = 0;
extents->width = extents->height = 0;
}
return CAIRO_STATUS_SUCCESS;
}
@ -1784,7 +1835,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
_cairo_cache_freeze (scaled_font->glyphs);
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
int x, y;
@ -1904,7 +1955,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_fini (&mask_pattern.base);
CLEANUP_MASK:
_cairo_cache_thaw (scaled_font->glyphs);
_cairo_scaled_font_thaw_cache (scaled_font);
_cairo_pattern_fini (&white_pattern.base);
@ -2256,9 +2307,19 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
* @index: the glyph to create
* @info: a #cairo_scaled_glyph_info_t marking which portions of
* the glyph should be filled in.
* @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph
* @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph
* is returned.
*
* If the desired info is not available, (for example, when trying to
* get INFO_PATH with a bitmapped font), this function will return
* %CAIRO_INT_STATUS_UNSUPPORTED.
*
* Note: This function must be called with the scaled font frozen, and it must
* remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled
* font was not frozen, then there is no guarantee that the glyph would not be
* evicted before you tried to access it.) See
* _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache().
*
* Returns: a glyph with the requested portions filled in. Glyph
* lookup is cached and glyph will be automatically freed along
* with the scaled_font so no explicit free is required.
@ -2266,12 +2327,6 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
* %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
* %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
* %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
*
* If the desired info is not available, (for example, when trying to
* get INFO_PATH with a bitmapped font), this function will return
* %CAIRO_INT_STATUS_UNSUPPORTED.
*
* Note: This function must be called with scaled_font->mutex held.
**/
cairo_int_status_t
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
@ -2287,6 +2342,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
if (scaled_font->status)
return scaled_font->status;
assert (_cairo_scaled_font_is_frozen (scaled_font));
key.hash = index;
/*
* Check cache for glyph

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

@ -322,16 +322,20 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
/*
* Find links along each chain
*/
elt = NULL;
next = list->chains;
for (i = list->max_level; --i >= 0; )
{
for (; (elt = next[i]); next = elt->next)
if (elt != next[i])
{
int cmp = list->compare (list, ELT_DATA(elt), data);
if (unique && 0 == cmp)
return ELT_DATA(elt);
if (cmp > 0)
break;
for (; (elt = next[i]); next = elt->next)
{
int cmp = list->compare (list, ELT_DATA(elt), data);
if (unique && 0 == cmp)
return ELT_DATA(elt);
if (cmp > 0)
break;
}
}
update[i] = next;
if (next != list->chains)

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

@ -37,7 +37,9 @@
#include "cairoint.h"
void
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
_cairo_slope_init (cairo_slope_t *slope,
const cairo_point_t *a,
const cairo_point_t *b)
{
slope->dx = b->x - a->x;
slope->dy = b->y - a->y;
@ -62,17 +64,15 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
> 0 => a more positive than b
*/
int
_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b)
_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b)
{
cairo_fixed_48_16_t diff;
cairo_int64_t ady_bdx = _cairo_int32x32_64_mul (a->dy, b->dx);
cairo_int64_t bdy_adx = _cairo_int32x32_64_mul (b->dy, a->dx);
int cmp;
diff = ((cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx
- (cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx);
if (diff > 0)
return 1;
if (diff < 0)
return -1;
cmp = _cairo_int64_cmp (ady_bdx, bdy_adx);
if (cmp)
return cmp;
/* special-case zero vectors. the intended logic here is:
* zero vectors all compare equal, and more positive than any

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

@ -124,6 +124,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out);
#endif

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

@ -527,16 +527,14 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_rectangle_int_t extents;
cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
if (_cairo_operator_bounded_by_mask (op) && traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
has_trap_region = FALSE;
} else if (status) {
@ -697,14 +695,9 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
if (status)
return status;
box.p1.x = _cairo_fixed_from_int (extents.x);
box.p1.y = _cairo_fixed_from_int (extents.y);
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
_cairo_box_from_rectangle (&box, &extents);
status = _cairo_traps_init_box (&traps, &box);
if (status)
return status;
_cairo_traps_init_box (&traps, &box);
status = _clip_and_composite_trapezoids (source,
op,
@ -821,13 +814,12 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
if (status)
return status;
box.p1.x = _cairo_fixed_from_int (extents.x);
box.p1.y = _cairo_fixed_from_int (extents.y);
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
if (extents.width == 0 || extents.height == 0)
return CAIRO_STATUS_SUCCESS;
_cairo_box_from_rectangle (&box, &extents);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &box);
status = _cairo_path_fixed_stroke_to_traps (path,
@ -835,10 +827,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
ctm, ctm_inverse,
tolerance,
&traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
if (status)
goto FAIL;
status = _clip_and_composite_trapezoids (source,
op,
@ -847,6 +837,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
surface->clip,
antialias);
FAIL:
_cairo_traps_fini (&traps);
return status;
@ -883,13 +874,12 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
if (status)
return status;
box.p1.x = _cairo_fixed_from_int (extents.x);
box.p1.y = _cairo_fixed_from_int (extents.y);
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
if (extents.width == 0 || extents.height == 0)
return CAIRO_STATUS_SUCCESS;
_cairo_box_from_rectangle (&box, &extents);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &box);
status = _cairo_path_fixed_fill_to_traps (path,
@ -998,6 +988,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t glyph_extents;
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
@ -1259,6 +1250,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_status_t status;
@ -1288,9 +1281,11 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
status = cairo_status (cr);
cairo_destroy (cr);
if (status == CAIRO_STATUS_SUCCESS)
if (status == CAIRO_STATUS_SUCCESS) {
*clone_offset_x = src_x;
*clone_offset_y = src_y;
*clone_out = new_surface;
else
} else
cairo_surface_destroy (new_surface);
return status;

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

@ -73,7 +73,6 @@ const cairo_surface_t name = { \
FALSE, /* has_font_options */ \
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \
} /* font_options */ \
@ -239,12 +238,8 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
if (other->backend->create_similar) {
surface = other->backend->create_similar (other, content, width, height);
/* It's not an error if the backend didn't create a valid
* surface---it may just not be supported. */
if (surface && surface->status) {
cairo_surface_destroy (surface);
surface = NULL;
}
if (surface != NULL && surface->status)
return surface;
}
if (surface == NULL)
@ -584,7 +579,7 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return surface->status;
return _cairo_user_data_array_set_data (&surface->user_data,
key, user_data, destroy);
@ -611,11 +606,11 @@ _cairo_surface_set_font_options (cairo_surface_t *surface,
{
cairo_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface,
CAIRO_STATUS_SURFACE_FINISHED);
@ -709,6 +704,9 @@ slim_hidden_def (cairo_surface_flush);
void
cairo_surface_mark_dirty (cairo_surface_t *surface)
{
if (surface->status)
return;
assert (! surface->is_snapshot);
cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
@ -739,11 +737,11 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
{
cairo_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
@ -797,11 +795,11 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
{
cairo_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
@ -812,10 +810,10 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
surface->device_transform.xy = 0.0;
surface->device_transform.yx = 0.0;
surface->device_transform_inverse.xx = 1.0 / sx;
surface->device_transform_inverse.yy = 1.0 / sy;
surface->device_transform_inverse.xy = 0.0;
surface->device_transform_inverse.yx = 0.0;
surface->device_transform_inverse = surface->device_transform;
status = cairo_matrix_invert (&surface->device_transform_inverse);
/* should always be invertible unless given pathological input */
assert (status == CAIRO_STATUS_SUCCESS);
}
/**
@ -843,11 +841,11 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
{
cairo_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
@ -856,8 +854,10 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
surface->device_transform.x0 = x_offset;
surface->device_transform.y0 = y_offset;
surface->device_transform_inverse.x0 = - x_offset;
surface->device_transform_inverse.y0 = - y_offset;
surface->device_transform_inverse = surface->device_transform;
status = cairo_matrix_invert (&surface->device_transform_inverse);
/* should always be invertible unless given pathological input */
assert (status == CAIRO_STATUS_SUCCESS);
}
slim_hidden_def (cairo_surface_set_device_offset);
@ -924,11 +924,11 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
{
cairo_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
@ -990,11 +990,11 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
assert (!surface->finished);
if (surface->status)
return surface->status;
assert (!surface->finished);
if (surface->backend->acquire_source_image == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1059,11 +1059,11 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
assert (!surface->finished);
if (surface->status)
return surface->status;
assert (!surface->finished);
if (surface->backend->acquire_dest_image == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1128,6 +1128,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -1141,8 +1143,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
if (surface->backend->clone_similar) {
status = surface->backend->clone_similar (surface, src, src_x, src_y,
width, height, clone_out);
status = surface->backend->clone_similar (surface, src,
src_x, src_y,
width, height,
clone_offset_x,
clone_offset_y,
clone_out);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* If we failed, try again with an image surface */
@ -1152,6 +1158,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
surface->backend->clone_similar (surface, &image->base,
src_x, src_y,
width, height,
clone_offset_x,
clone_offset_y,
clone_out);
_cairo_surface_release_source_image (src, image, image_extra);
@ -1162,8 +1170,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* If we're still unsupported, hit our fallback path to get a clone */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
status =
_cairo_surface_fallback_clone_similar (surface, src, src_x, src_y,
width, height, clone_out);
_cairo_surface_fallback_clone_similar (surface, src,
src_x, src_y,
width, height,
clone_offset_x,
clone_offset_y,
clone_out);
/* We should never get UNSUPPORTED here, so if we have an error, bail. */
if (status)
@ -1172,8 +1184,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* Update the clone's device_transform (which the underlying surface
* backend knows nothing about) */
if (*clone_out != src) {
(*clone_out)->device_transform = src->device_transform;
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
(*clone_out)->device_transform = src->device_transform;
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
}
return status;
@ -1256,8 +1268,6 @@ _cairo_surface_composite (cairo_operator_t op,
{
cairo_int_status_t status;
assert (! dst->is_snapshot);
if (mask) {
/* These operators aren't interpreted the same way by the backends;
* they are implemented in terms of other operators in cairo-gstate.c
@ -1268,6 +1278,8 @@ _cairo_surface_composite (cairo_operator_t op,
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
@ -1317,11 +1329,11 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
{
cairo_rectangle_int_t rect;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
@ -1359,11 +1371,11 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
cairo_status_t status;
int i;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
num_boxes = _cairo_region_num_boxes (region);
if (num_boxes == 0)
@ -1431,11 +1443,11 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
{
cairo_int_status_t status;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
@ -1462,11 +1474,11 @@ _cairo_surface_paint (cairo_surface_t *surface,
cairo_status_t status;
cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
@ -1495,11 +1507,11 @@ _cairo_surface_mask (cairo_surface_t *surface,
cairo_pattern_t *dev_source;
cairo_pattern_t *dev_mask;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
goto FINISH;
@ -1607,11 +1619,11 @@ _cairo_surface_stroke (cairo_surface_t *surface,
cairo_matrix_t dev_ctm = *ctm;
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
@ -1651,11 +1663,11 @@ _cairo_surface_fill (cairo_surface_t *surface,
cairo_status_t status;
cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
@ -1695,8 +1707,6 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
{
cairo_int_status_t status;
assert (! dst->is_snapshot);
/* These operators aren't interpreted the same way by the backends;
* they are implemented in terms of other operators in cairo-gstate.c
*/
@ -1705,6 +1715,8 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
@ -1748,11 +1760,11 @@ cairo_surface_copy_page (cairo_surface_t *surface)
{
cairo_status_t status_ignored;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status_ignored = _cairo_surface_set_error (surface,
CAIRO_STATUS_SURFACE_FINISHED);
@ -1785,11 +1797,11 @@ cairo_surface_show_page (cairo_surface_t *surface)
{
cairo_status_t status_ignored;
assert (! surface->is_snapshot);
if (surface->status)
return;
assert (! surface->is_snapshot);
if (surface->finished) {
status_ignored = _cairo_surface_set_error (surface,
CAIRO_STATUS_SURFACE_FINISHED);
@ -1809,10 +1821,12 @@ slim_hidden_def (cairo_surface_show_page);
* _cairo_surface_get_current_clip_serial:
* @surface: the #cairo_surface_t to return the serial number for
*
* This space left intentionally blank.
*
* Returns: the serial number associated with the current
* clip in the surface. All gstate functions must
* verify that the correct clip is set in the surface before
* invoking any surface drawing function
* invoking any surface drawing function.
*/
unsigned int
_cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
@ -1904,9 +1918,6 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface,
if (surface->status)
return surface->status;
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
assert (surface->backend->set_clip_region != NULL);
surface->current_clip_serial = serial;
@ -2163,9 +2174,6 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
* function to avoid computing UTF-8 text and cluster mapping if the
* target surface does not use it.
*
* There is a convenience function for this that takes a #cairo_t,
* namely cairo_has_show_text_glyphs().
*
* Return value: %TRUE if @surface supports
* cairo_show_text_glyphs(), %FALSE otherwise
*
@ -2217,18 +2225,18 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
assert (! surface->is_snapshot);
if (!num_glyphs && !utf8_len)
return CAIRO_STATUS_SUCCESS;
@ -2259,8 +2267,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
@ -2272,8 +2278,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
status = surface->backend->show_text_glyphs (surface, op, dev_source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
clusters, num_clusters, cluster_flags,
dev_scaled_font);
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
@ -2311,8 +2316,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
status = surface->backend->show_text_glyphs (surface, op, dev_source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
clusters, num_clusters, cluster_flags,
dev_scaled_font);
}
}
@ -2322,8 +2326,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
glyphs, num_glyphs,
dev_scaled_font);
CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex);
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
@ -2353,11 +2355,11 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status;
assert (! dst->is_snapshot);
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
@ -2477,11 +2479,11 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
* non-repeating sources and masks. Other sources and masks can be ignored.
*/
@ -2555,11 +2557,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
* non-repeating sources and masks. Other sources and masks can be ignored.
*/

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

@ -42,12 +42,13 @@
#define _BSD_SOURCE /* for snprintf() */
#include "cairoint.h"
#include "cairo-svg.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-svg-surface-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-paginated-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-output-stream-private.h"
typedef struct cairo_svg_page cairo_svg_page_t;
@ -154,7 +155,10 @@ static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backe
/**
* cairo_svg_surface_create_for_stream:
* @write_func: a #cairo_write_func_t to accept the output data
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
* to indicate a no-op @write_func. With a no-op @write_func,
* the surface may be queried or used as a source without
* generating any temporary files.
* @closure: the closure argument for @write_func
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
@ -189,7 +193,10 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write_func,
/**
* cairo_svg_surface_create:
* @filename: a filename for the SVG output (must be writable)
* @filename: a filename for the SVG output (must be writable), %NULL may be
* used to specify no output. This will generate a SVG surface that
* may be queried and used as a source, without generating a
* temporary file.
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
*
@ -366,8 +373,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
if (content == CAIRO_CONTENT_COLOR) {
_cairo_output_stream_printf (surface->xml_node,
"<rect width=\"%f\" height=\"%f\" "
"style=\"opacity: 1; stroke: none; "
"fill: rgb(0,0,0);\"/>\n",
"style=\"opacity:1;stroke:none;"
"fill:rgb(0,0,0);\"/>\n",
width, height);
status = _cairo_output_stream_get_status (surface->xml_node);
if (status)
@ -631,7 +638,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document,
return status;
_cairo_output_stream_printf (document->xml_node_glyphs,
"<path style=\"stroke: none;\" ");
"<path style=\"stroke:none;\" ");
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
if (status)
@ -706,8 +713,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
_cairo_output_stream_printf (document->xml_node_glyphs,
"<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n",
font_id,
subset_glyph_index);
font_id,
subset_glyph_index);
status = _cairo_svg_document_emit_outline_glyph_data (document,
scaled_font,
@ -732,6 +739,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
unsigned int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
_cairo_scaled_font_freeze_cache (font_subset->scaled_font);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_svg_document_emit_glyph (document,
font_subset->scaled_font,
@ -740,6 +748,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
if (status)
break;
}
_cairo_scaled_font_thaw_cache (font_subset->scaled_font);
return status;
}
@ -752,14 +761,48 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
if (status)
goto FAIL;
status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
FAIL:
_cairo_scaled_font_subsets_destroy (document->font_subsets);
document->font_subsets = NULL;
return status;
}
static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
static char const *
_cairo_svg_surface_operators[] = {
"clear",
"src", "src-over", "src-in",
"src-out", "src-atop",
"dst", "dst-over", "dst-in",
"dst-out", "dst-atop",
"xor", "plus",
"color-dodge", /* FIXME: saturate ? */
};
static cairo_bool_t
_cairo_svg_surface_analyze_operator (cairo_svg_surface_t *surface,
cairo_operator_t op)
{
/* guard against newly added operators */
if (op >= ARRAY_LENGTH (_cairo_svg_surface_operators))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* allow operators being NULL if they are unsupported */
if (_cairo_svg_surface_operators[op] == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
@ -768,8 +811,11 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
{
cairo_svg_document_t *document = surface->document;
if (cairo_svg_force_fallbacks)
return FALSE;
if (surface->force_fallbacks &&
surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* SVG doesn't support extend reflect for image pattern */
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
@ -777,7 +823,7 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (document->svg_version >= CAIRO_SVG_VERSION_1_2)
return CAIRO_STATUS_SUCCESS;
return _cairo_svg_surface_analyze_operator (surface, op);
if (op == CAIRO_OPERATOR_OVER)
return CAIRO_STATUS_SUCCESS;
@ -960,31 +1006,49 @@ _cairo_surface_base64_encode (cairo_surface_t *surface,
return status;
}
static void
_cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op)
{
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 &&
op != CAIRO_OPERATOR_OVER) {
_cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op]);
if (!_cairo_operator_bounded_by_source (op))
_cairo_output_stream_printf (output, " clip-to-self=\"true\"");
}
}
static void
_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op)
{
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 &&
op != CAIRO_OPERATOR_OVER) {
_cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op]);
if (!_cairo_operator_bounded_by_source (op))
_cairo_output_stream_printf (output, "clip-to-self:true;");
}
}
static cairo_status_t
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *svg_surface,
cairo_operator_t op,
cairo_surface_pattern_t *pattern,
int pattern_id,
const cairo_matrix_t *parent_matrix,
const char *extra_attributes)
{
cairo_surface_t *surface;
cairo_surface_attributes_t surface_attr;
cairo_rectangle_int_t extents;
cairo_status_t status;
cairo_matrix_t p2u;
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
(cairo_surface_t *)svg_surface,
0, 0, (unsigned int)-1, (unsigned int)-1,
&surface, &surface_attr);
status = _cairo_surface_get_extents (pattern->surface, &extents);
if (status)
return status;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
goto FAIL;
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
@ -1005,25 +1069,23 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
" <image width=\"%d\" height=\"%d\"",
extents.width, extents.height);
if (pattern_id == invalid_pattern_id)
if (pattern_id == invalid_pattern_id) {
_cairo_svg_surface_emit_operator (output, svg_surface, op);
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
}
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
_cairo_output_stream_printf (output, " xlink:href=\"");
status = _cairo_surface_base64_encode (surface, output);
status = _cairo_surface_base64_encode (pattern->surface, output);
_cairo_output_stream_printf (output, "\"/>\n");
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);
return status;
}
@ -1159,6 +1221,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
static cairo_status_t
_cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_surface_pattern_t *pattern,
int pattern_id,
const cairo_matrix_t *parent_matrix,
@ -1197,8 +1260,10 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
"<use xlink:href=\"#surface%d\"",
id);
if (pattern_id == invalid_pattern_id)
if (pattern_id == invalid_pattern_id) {
_cairo_svg_surface_emit_operator (output, surface, op);
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
}
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@ -1214,6 +1279,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
static cairo_status_t
_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_surface_pattern_t *pattern,
int pattern_id,
const cairo_matrix_t *parent_matrix,
@ -1221,36 +1287,14 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
{
if (_cairo_surface_is_meta (pattern->surface)) {
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern,
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern,
pattern_id, parent_matrix, extra_attributes);
}
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern,
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern,
pattern_id, parent_matrix, extra_attributes);
}
static void
_cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op)
{
char const *op_str[] = {
"clear",
"src", "src-over", "src-in",
"src-out", "src-atop",
"dst", "dst-over", "dst-in",
"dst-out", "dst-atop",
"xor", "plus",
"color-dodge" /* FIXME: saturate ? */
};
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2)
_cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]);
}
static cairo_status_t
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
cairo_solid_pattern_t *pattern,
@ -1258,8 +1302,8 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
cairo_bool_t is_stroke)
{
_cairo_output_stream_printf (style, is_stroke ?
"stroke: rgb(%f%%,%f%%,%f%%); stroke-opacity: %f;":
"fill: rgb(%f%%,%f%%,%f%%); fill-opacity: %f;",
"stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;":
"fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;",
pattern->color.red * 100.0,
pattern->color.green * 100.0,
pattern->color.blue * 100.0,
@ -1281,13 +1325,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,
surface, CAIRO_OPERATOR_SOURCE, pattern,
pattern_id, parent_matrix, NULL);
if (status)
return status;
_cairo_output_stream_printf (style,
"%s: url(#pattern%d);",
"%s:url(#pattern%d);",
is_stroke ? "stroke" : "fill",
pattern_id);
@ -1312,8 +1356,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
if (pattern->n_stops == 1) {
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
pattern->stops[0].offset,
pattern->stops[0].color.red * 100.0,
pattern->stops[0].color.green * 100.0,
@ -1359,8 +1403,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
offset = start_offset + (1 - start_offset ) * stops[i].offset;
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
@ -1411,8 +1455,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
_cairo_output_stream_printf (output,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
offset_color_start.red * 100.0,
offset_color_start.green * 100.0,
offset_color_start.blue * 100.0,
@ -1420,8 +1464,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
for (i = offset_index; i < n_stops; i++) {
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
stops[i].offset + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
@ -1431,8 +1475,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
for (i = 0; i < offset_index; i++) {
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
1.0 + stops[i].offset + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
@ -1442,8 +1486,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
_cairo_output_stream_printf (output,
"<stop offset=\"1\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
offset_color_stop.red * 100.0,
offset_color_stop.green * 100.0,
offset_color_stop.blue * 100.0,
@ -1517,7 +1561,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
"</linearGradient>\n");
_cairo_output_stream_printf (style,
"%s: url(#linear%d);",
"%s:url(#linear%d);",
is_stroke ? "stroke" : "fill",
document->linear_pattern_id);
@ -1588,13 +1632,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"0\" style=\""
"stop-color: rgb(0%%,0%%,0%%); "
"stop-opacity: 0;\"/>\n");
"stop-color:rgb(0%%,0%%,0%%);"
"stop-opacity:0;\"/>\n");
else {
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity %f;\"/>\n",
pattern->base.stops[0].color.red * 100.0,
pattern->base.stops[0].color.green * 100.0,
pattern->base.stops[0].color.blue * 100.0,
@ -1602,8 +1646,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
if (n_stops > 1)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
"stop-color:rgb(%f%%,%f%%,%f%%);"
"stop-opacity:%f;\"/>\n",
pattern->base.stops[n_stops - 1].color.red * 100.0,
pattern->base.stops[n_stops - 1].color.green * 100.0,
pattern->base.stops[n_stops - 1].color.blue * 100.0,
@ -1675,13 +1719,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
if (extend == CAIRO_EXTEND_NONE) {
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"0\" style=\""
"stop-color: rgb(0%%,0%%,0%%); "
"stop-opacity: 0;\"/>\n");
"stop-color:rgb(0%%,0%%,0%%);"
"stop-opacity:0;\"/>\n");
if (r0 != 0.0)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(0%%,0%%,0%%); "
"stop-opacity: 0;\"/>\n",
"stop-color:rgb(0%%,0%%,0%%);"
"stop-opacity:0;\"/>\n",
r0 / r1);
}
status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
@ -1694,15 +1738,15 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
if (pattern->base.base.extend == CAIRO_EXTEND_NONE)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"1.0\" style=\""
"stop-color: rgb(0%%,0%%,0%%); "
"stop-opacity: 0;\"/>\n");
"stop-color:rgb(0%%,0%%,0%%);"
"stop-opacity:0;\"/>\n");
}
_cairo_output_stream_printf (document->xml_node_defs,
"</radialGradient>\n");
_cairo_output_stream_printf (style,
"%s: url(#radial%d);",
"%s:url(#radial%d);",
is_stroke ? "stroke" : "fill",
document->radial_pattern_id);
@ -1747,10 +1791,10 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
cairo_matrix_t *parent_matrix)
{
_cairo_output_stream_printf (output,
"fill-rule: %s; ",
"fill-rule:%s;",
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
"evenodd" : "nonzero");
_cairo_svg_surface_emit_operator (output, surface, op);
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix);
}
@ -1795,9 +1839,9 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
}
_cairo_output_stream_printf (output,
"stroke-width: %f; "
"stroke-linecap: %s; "
"stroke-linejoin: %s; ",
"stroke-width:%f;"
"stroke-linecap:%s;"
"stroke-linejoin:%s;",
stroke_style->line_width,
line_cap,
line_join);
@ -1806,27 +1850,27 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
if (status)
return status;
_cairo_svg_surface_emit_operator (output, surface, op);
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
if (stroke_style->num_dashes > 0) {
_cairo_output_stream_printf (output, "stroke-dasharray: ");
_cairo_output_stream_printf (output, "stroke-dasharray:");
for (i = 0; i < stroke_style->num_dashes; i++) {
_cairo_output_stream_printf (output, "%f",
stroke_style->dash[i]);
if (i + 1 < stroke_style->num_dashes)
_cairo_output_stream_printf (output, ",");
else
_cairo_output_stream_printf (output, "; ");
_cairo_output_stream_printf (output, ";");
}
if (stroke_style->dash_offset != 0.0) {
_cairo_output_stream_printf (output,
"stroke-dashoffset: %f; ",
"stroke-dashoffset:%f;",
stroke_style->dash_offset);
}
}
_cairo_output_stream_printf (output,
"stroke-miterlimit: %f; ",
"stroke-miterlimit:%f;",
stroke_style->miter_limit);
return CAIRO_STATUS_SUCCESS;
@ -1931,6 +1975,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask_source,
const char *extra_attributes)
{
cairo_status_t status;
@ -1938,23 +1983,24 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
return _cairo_svg_surface_emit_composite_pattern (output,
surface,
(cairo_surface_pattern_t *) source,
invalid_pattern_id,
NULL,
extra_attributes);
surface,
op,
(cairo_surface_pattern_t *) source,
invalid_pattern_id,
mask_source ? &mask_source->matrix :NULL,
extra_attributes);
_cairo_output_stream_printf (output,
"<rect x=\"0\" y=\"0\" "
"width=\"%f\" height=\"%f\" "
"style=\"",
surface->width, surface->height);
_cairo_svg_surface_emit_operator (output, surface, op);
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL);
if (status)
return status;
_cairo_output_stream_printf (output, " stroke: none;\"");
_cairo_output_stream_printf (output, "stroke:none;\"");
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@ -1975,15 +2021,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_svg_surface_analyze_operation (surface, op, source);
/* XXX: It would be nice to be able to assert this condition
* here. But, we actually allow one 'cheat' that is used when
* painting the final image-based fallbacks. The final fallbacks
* do have alpha which we support by blending with white. This is
* possible only because there is nothing between the fallback
* images and the paper, nor is anything painted above. */
/*
assert (_cairo_svg_surface_operation_supported (surface, op, source));
*/
/* Emulation of clear and source operators, when no clipping region
* is defined. We just delete existing content of surface root node,
@ -1992,11 +2030,8 @@ _cairo_svg_surface_paint (void *abstract_surface,
* above always return FALSE. In order to make it work, we need a way
* to know if there's an active clipping path.
* Optimization of CLEAR works because of a test in paginated surface,
* and an optimiszation in meta surface. */
if (surface->clip_level == 0 &&
(op == CAIRO_OPERATOR_CLEAR ||
op == CAIRO_OPERATOR_SOURCE))
{
* and an optimization in meta surface. */
if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) {
status = _cairo_output_stream_destroy (surface->xml_node);
if (status) {
surface->xml_node = NULL;
@ -2015,16 +2050,17 @@ _cairo_svg_surface_paint (void *abstract_surface,
_cairo_output_stream_printf (surface->xml_node,
"<rect "
"width=\"%f\" height=\"%f\" "
"style=\"opacity: 1; "
"stroke: none; "
"fill: rgb(0,0,0);\"/>\n",
"style=\"opacity:1;"
"stroke:none;"
"fill:rgb(0,0,0);\"/>\n",
surface->width, surface->height);
}
return CAIRO_STATUS_SUCCESS;
}
}
return _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL);
return _cairo_svg_surface_emit_paint (surface->xml_node,
surface, op, source, 0, NULL);
}
static cairo_int_status_t
@ -2041,10 +2077,23 @@ _cairo_svg_surface_mask (void *abstract_surface,
cairo_bool_t discard_filter = FALSE;
unsigned int mask_id;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_svg_surface_analyze_operation (surface, op, source);
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
cairo_status_t source_status, mask_status;
source_status = _cairo_svg_surface_analyze_operation (surface, op, source);
if (_cairo_status_is_error (source_status))
return source_status;
mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask);
if (_cairo_status_is_error (mask_status))
return mask_status;
return _cairo_analysis_surface_merge_status (source_status,
mask_status);
}
assert (_cairo_svg_surface_operation_supported (surface, op, source));
assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask));
if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask;
@ -2070,7 +2119,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
"%s",
mask_id,
discard_filter ? "" : " <g filter=\"url(#alpha)\">\n");
status = _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL);
status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL);
if (status) {
cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream);
return status;
@ -2089,7 +2138,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"",
mask_id);
status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer);
status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, buffer);
if (status)
return status;
@ -2115,7 +2164,7 @@ _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; ");
_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, ctm_inverse);
if (status)
@ -2169,6 +2218,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
if (status)
return status;
_cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op);
_cairo_output_stream_printf (surface->xml_node, "\">\n");
for (i = 0; i < num_glyphs; i++) {
@ -2418,6 +2469,28 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
if (document->finished)
return CAIRO_STATUS_SUCCESS;
/*
* Should we add DOCTYPE?
*
* Google says no.
*
* http://tech.groups.yahoo.com/group/svg-developers/message/48562:
* There's a bunch of issues, but just to pick a few:
* - they'll give false positives.
* - they'll give false negatives.
* - they're namespace-unaware.
* - they don't wildcard.
* So when they say OK they really haven't checked anything, when
* they say NOT OK they might be on crack, and like all
* namespace-unaware things they're a dead branch of the XML tree.
*
* http://jwatt.org/svg/authoring/:
* Unfortunately the SVG DTDs are a source of so many issues that the
* SVG WG has decided not to write one for the upcoming SVG 1.2
* standard. In fact SVG WG members are even telling people not to use
* a DOCTYPE declaration in SVG 1.0 and 1.1 documents.
*/
_cairo_output_stream_printf (output,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<svg xmlns=\"http://www.w3.org/2000/svg\" "
@ -2506,15 +2579,33 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
}
static void
_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t paginated_mode)
_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t paginated_mode)
{
cairo_svg_surface_t *surface = abstract_surface;
surface->paginated_mode = paginated_mode;
}
static cairo_bool_t
_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) {
status = _cairo_svg_surface_analyze_operator (surface,
CAIRO_OPERATOR_SOURCE);
}
return status == CAIRO_STATUS_SUCCESS;
}
static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = {
NULL /*_cairo_svg_surface_start_page*/,
_cairo_svg_surface_set_paginated_mode
_cairo_svg_surface_set_paginated_mode,
NULL, /* _cairo_svg_surface_set_bounding_box */
NULL, /* _cairo_svg_surface_set_fallback_images_required */
_cairo_svg_surface_supports_fine_grained_fallbacks,
};

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

@ -1,7 +1,7 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2007 Adrian Johnson
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -28,12 +28,30 @@
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Adrian Johnson.
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Adrian Johnson <ajohnson@redneon.com>
* Owen Taylor <otaylor@redhat.com>
* Stuart Parmenter <stuart@mozilla.com>
* Vladimir Vukicevic <vladimir@pobox.com>
*/
/* This file should include code that is system-specific, not
* feature-specific. For example, the DLL initialization/finalization
* code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c).
* Same about possible ELF-specific code.
*
* And no other function should live here.
*/
#include "cairoint.h"
#if CAIRO_MUTEX_IMPL_WIN32
#if !CAIRO_WIN32_STATIC_BUILD
#define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features such as ETO_PDY */
#if !defined(WINVER) || (WINVER < 0x0500)
@ -43,56 +61,37 @@
# define _WIN32_WINNT 0x0500
#endif
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-paginated-private.h"
#include "cairo-win32-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include <windows.h>
#include <io.h>
/* tmpfile() replacment for Windows.
*
* On Windows tmpfile() creates the file in the root directory. This
* may fail due to unsufficient privileges.
*/
FILE *
_cairo_win32_tmpfile (void)
/* declare to avoid "no previous prototype for 'DllMain'" warning */
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
DWORD path_len;
WCHAR path_name[MAX_PATH + 1];
WCHAR file_name[MAX_PATH + 1];
HANDLE handle;
int fd;
FILE *fp;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
CAIRO_MUTEX_INITIALIZE ();
break;
path_len = GetTempPathW (MAX_PATH, path_name);
if (path_len <= 0 || path_len >= MAX_PATH)
return NULL;
if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
return NULL;
handle = CreateFileW (file_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
DeleteFileW (file_name);
return NULL;
case DLL_PROCESS_DETACH:
CAIRO_MUTEX_FINALIZE ();
break;
}
fd = _open_osfhandle((intptr_t) handle, 0);
if (fd < 0) {
CloseHandle (handle);
return NULL;
}
fp = fdopen(fd, "w+b");
if (fp == NULL) {
_close(fd);
return NULL;
}
return fp;
return TRUE;
}
#endif
#endif

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

@ -41,13 +41,6 @@
/* private functions */
static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps);
static void
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
static int
_compare_point_fixed_by_y (const void *av, const void *bv);
@ -83,15 +76,21 @@ _cairo_traps_get_limit (cairo_traps_t *traps,
return traps->has_limits;
}
void
_cairo_traps_clear (cairo_traps_t *traps)
{
traps->status = CAIRO_STATUS_SUCCESS;
traps->num_traps = 0;
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
}
void
_cairo_traps_fini (cairo_traps_t *traps)
{
if (traps->traps && traps->traps != traps->traps_embedded)
if (traps->traps != traps->traps_embedded)
free (traps->traps);
traps->traps = NULL;
traps->traps_size = 0;
traps->num_traps = 0;
}
/**
@ -103,9 +102,9 @@ _cairo_traps_fini (cairo_traps_t *traps)
* Initializes a #cairo_traps_t to contain a single rectangular
* trapezoid.
**/
cairo_status_t
void
_cairo_traps_init_box (cairo_traps_t *traps,
cairo_box_t *box)
const cairo_box_t *box)
{
_cairo_traps_init (traps);
@ -123,25 +122,41 @@ _cairo_traps_init_box (cairo_traps_t *traps,
traps->traps[0].right.p2 = box->p2;
traps->extents = *box;
return traps->status;
}
cairo_status_t
_cairo_traps_status (cairo_traps_t *traps)
/* make room for at least one more trap */
static cairo_bool_t
_cairo_traps_grow (cairo_traps_t *traps)
{
return traps->status;
cairo_trapezoid_t *new_traps;
int new_size = 2 * MAX (traps->traps_size, 16);
if (traps->traps == traps->traps_embedded) {
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
if (new_traps != NULL)
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
} else {
new_traps = _cairo_realloc_ab (traps->traps,
new_size, sizeof (cairo_trapezoid_t));
}
if (new_traps == NULL) {
traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return FALSE;
}
traps->traps = new_traps;
traps->traps_size = new_size;
return TRUE;
}
static void
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
void
_cairo_traps_add_trap (cairo_traps_t *traps,
cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right)
{
cairo_trapezoid_t *trap;
if (traps->status)
return;
/* Note: With the goofy trapezoid specification, (where an
* arbitrary two points on the lines can specified for the left
* and right edges), these limit checks would not work in
@ -170,6 +185,10 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
return;
}
/* And reject if the trapezoid is entirely above or below */
if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
return;
/* Otherwise, clip the trapezoid to the limits. We only clip
* where an edge is entirely outside the limits. If we wanted
* to be more clever, we could handle cases where a trapezoid
@ -182,28 +201,34 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
if (bottom > traps->limits.p2.y)
bottom = traps->limits.p2.y;
if (left->p1.x < traps->limits.p1.x &&
left->p2.x < traps->limits.p1.x)
if (left->p1.x <= traps->limits.p1.x &&
left->p2.x <= traps->limits.p1.x)
{
left->p1.x = traps->limits.p1.x;
left->p2.x = traps->limits.p1.x;
}
if (right->p1.x > traps->limits.p2.x &&
right->p2.x > traps->limits.p2.x)
if (right->p1.x >= traps->limits.p2.x &&
right->p2.x >= traps->limits.p2.x)
{
right->p1.x = traps->limits.p2.x;
right->p2.x = traps->limits.p2.x;
}
}
if (top >= bottom) {
/* Trivial discards for empty trapezoids that are likely to be produced
* by our tessellators (most notably convex_quad when given a simple
* rectangle).
*/
if (top >= bottom)
return;
/* cheap colinearity check */
if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y &&
right->p2.x <= left->p2.x && right->p2.y == left->p2.y)
return;
}
if (traps->num_traps >= traps->traps_size) {
traps->status = _cairo_traps_grow (traps);
if (traps->status)
if (traps->num_traps == traps->traps_size) {
if (! _cairo_traps_grow (traps))
return;
}
@ -238,51 +263,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
traps->num_traps++;
}
void
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2)
{
cairo_line_t left;
cairo_line_t right;
if (traps->status)
return;
left.p1 = left_p1;
left.p2 = left_p2;
right.p1 = right_p1;
right.p2 = right_p2;
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
}
/* make room for at least one more trap */
static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps)
{
cairo_trapezoid_t *new_traps;
int new_size = 2 * MAX (traps->traps_size, 16);
if (traps->traps == traps->traps_embedded) {
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
if (new_traps)
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
} else {
new_traps = _cairo_realloc_ab (traps->traps,
new_size, sizeof (cairo_trapezoid_t));
}
if (new_traps == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
traps->traps = new_traps;
traps->traps_size = new_size;
return CAIRO_STATUS_SUCCESS;
}
static int
_compare_point_fixed_by_y (const void *av, const void *bv)
{
@ -371,7 +351,8 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
* quadrilateral. We would not benefit from having any distinct
* implementation of triangle vs. quadrilateral tessellation here. */
cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
const cairo_point_t t[3])
{
cairo_point_t quad[4];
@ -384,12 +365,33 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
}
cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
const cairo_point_t *top_left,
const cairo_point_t *bottom_right)
{
cairo_line_t left;
cairo_line_t right;
left.p1.x = left.p2.x = top_left->x;
left.p1.y = right.p1.y = top_left->y;
right.p1.x = right.p2.x = bottom_right->x;
left.p2.y = right.p2.y = bottom_right->y;
_cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
return traps->status;
}
cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
const cairo_point_t q[4])
{
int a, b, c, d;
int i;
cairo_slope_t ab, ad;
cairo_bool_t b_left_of_d;
cairo_line_t left;
cairo_line_t right;
/* Choose a as a point with minimal y */
a = 0;
@ -454,15 +456,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
* | / \| \ \ c.y d.y cd ad
* d d d
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[b], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[c].y,
q[b], q[c], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[c].y, q[d].y,
q[c], q[d], q[a], q[d]);
left.p1 = q[a]; left.p2 = q[b];
right.p1 = q[a]; right.p2 = q[d];
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
left.p1 = q[b]; left.p2 = q[c];
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
left.p1 = q[c]; left.p2 = q[d];
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
} else {
/* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
*
@ -474,15 +474,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
* / / |/ \ | c.y d.y ad cd
* d d d
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[d], q[a], q[b]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[c].y,
q[a], q[d], q[b], q[c]);
_cairo_traps_add_trap_from_points (traps,
q[c].y, q[d].y,
q[a], q[d], q[c], q[d]);
left.p1 = q[a]; left.p2 = q[d];
right.p1 = q[a]; right.p2 = q[b];
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
right.p1 = q[b]; right.p2 = q[c];
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
right.p1 = q[c]; right.p2 = q[d];
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
}
} else {
if (b_left_of_d) {
@ -496,15 +494,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
* // \ / \| d.y c.y bc dc
* c c c
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[b], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[d].y,
q[b], q[c], q[a], q[d]);
_cairo_traps_add_trap_from_points (traps,
q[d].y, q[c].y,
q[b], q[c], q[d], q[c]);
left.p1 = q[a]; left.p2 = q[b];
right.p1 = q[a]; right.p2 = q[d];
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
left.p1 = q[b]; left.p2 = q[c];
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
right.p1 = q[d]; right.p2 = q[c];
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
} else {
/* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
*
@ -516,15 +512,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
* |/ \ / \\ d.y c.y dc bc
* c c c
*/
_cairo_traps_add_trap_from_points (traps,
q[a].y, q[b].y,
q[a], q[d], q[a], q[b]);
_cairo_traps_add_trap_from_points (traps,
q[b].y, q[d].y,
q[a], q[d], q[b], q[c]);
_cairo_traps_add_trap_from_points (traps,
q[d].y, q[c].y,
q[d], q[c], q[b], q[c]);
left.p1 = q[a]; left.p2 = q[d];
right.p1 = q[a]; right.p2 = q[b];
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
right.p1 = q[b]; right.p2 = q[c];
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
left.p1 = q[d]; left.p2 = q[c];
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
}
}
@ -581,8 +575,21 @@ _cairo_traps_extents (const cairo_traps_t *traps,
if (traps->num_traps == 0) {
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
} else
} else {
*extents = traps->extents;
if (traps->has_limits) {
/* clip the traps to the imposed limits */
if (extents->p1.x < traps->limits.p1.x)
extents->p1.x = traps->limits.p1.x;
if (extents->p2.x > traps->limits.p2.x)
extents->p2.x = traps->limits.p2.x;
if (extents->p1.y < traps->limits.p1.y)
extents->p1.y = traps->limits.p1.y;
if (extents->p2.y > traps->limits.p2.y)
extents->p2.y = traps->limits.p2.y;
}
}
}
/**

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

@ -1220,6 +1220,12 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
goto fail;
num_segments = be16_to_cpu (map->segCountX2)/2;
/* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of
* uint16_t each num_segments long. */
if (size < (8 + 4*num_segments)*sizeof(uint16_t))
return CAIRO_INT_STATUS_UNSUPPORTED;
end_code = map->endCount;
start_code = &(end_code[num_segments + 1]);
delta = &(start_code[num_segments]);
@ -1246,13 +1252,17 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
uint16_t g_id_be = cpu_to_be16 (index);
int j;
if (range_size > 0)
if (range_size > 0) {
if ((char*)glyph_ids + 2*range_size > (char*)map + size)
return CAIRO_INT_STATUS_UNSUPPORTED;
for (j = 0; j < range_size; j++) {
if (glyph_ids[j] == g_id_be) {
*ucs4 = be16_to_cpu (start_code[i]) + j;
goto found;
}
}
}
}
}

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

@ -444,18 +444,21 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
"2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1);
_cairo_scaled_font_freeze_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE1,
&data);
if (status)
goto fail;
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
if (font->scaled_font_subset->glyph_names != NULL) {
@ -474,6 +477,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
}
fail:
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
_cairo_array_fini (&data);
return status;
}
@ -823,6 +827,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
goto fail1;
}
_cairo_scaled_font_freeze_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_init (&charstring, sizeof (unsigned char));
status = _cairo_array_grow_by (&charstring, 32);
@ -840,6 +845,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
if (status)
goto fail2;
}
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
type2_subset->widths[i] = font->widths[i];
@ -854,6 +860,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
return cairo_type1_font_destroy (font);
fail2:
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
_cairo_array_fini (&charstring);
_cairo_type2_charstrings_fini (type2_subset);
fail1:

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

@ -61,7 +61,6 @@
#include <ctype.h>
typedef struct _cairo_type1_font_subset {
cairo_scaled_font_subset_t *scaled_font_subset;
struct {
@ -76,7 +75,6 @@ typedef struct _cairo_type1_font_subset {
unsigned long header_size;
unsigned long data_size;
unsigned long trailer_size;
} base;
FT_Face face;
@ -115,15 +113,14 @@ typedef struct _cairo_type1_font_subset {
static cairo_status_t
_cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
cairo_type1_font_subset_t **subset_return,
cairo_bool_t hex_encode)
_cairo_type1_font_subset_init (cairo_type1_font_subset_t *font,
cairo_unscaled_font_t *unscaled_font,
cairo_bool_t hex_encode)
{
cairo_ft_unscaled_font_t *ft_unscaled_font;
cairo_status_t status;
FT_Face face;
PS_FontInfoRec font_info;
cairo_type1_font_subset_t *font;
int i, j;
ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
@ -145,12 +142,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
}
#endif
font = calloc (sizeof (cairo_type1_font_subset_t), 1);
if (font == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
memset (font, 0, sizeof (font));
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
font->base.num_glyphs = face->num_glyphs;
font->base.x_min = face->bbox.xMin;
@ -189,8 +181,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
*subset_return = font;
return CAIRO_STATUS_SUCCESS;
fail3:
@ -198,7 +188,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
free (font->base.base_font);
fail2:
_cairo_unscaled_font_destroy (unscaled_font);
free (font);
fail1:
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
@ -1225,10 +1214,15 @@ cairo_type1_font_subset_generate (void *abstract_font,
goto fail;
}
if (font->face->stream->read) {
ret = font->face->stream->read (font->face->stream, 0,
(unsigned char *) font->type1_data,
font->type1_length);
if (font->face->stream->read != NULL) {
/* Note that read() may be implemented as a macro, thanks POSIX!, so we
* need to wrap the following usage in parentheses in order to
* disambiguate it for the pre-processor - using the verbose function
* pointer dereference for clarity.
*/
ret = (* font->face->stream->read) (font->face->stream, 0,
(unsigned char *) font->type1_data,
font->type1_length);
if (ret != font->type1_length) {
status = _cairo_error (CAIRO_STATUS_READ_ERROR);
goto fail;
@ -1261,9 +1255,8 @@ cairo_type1_font_subset_generate (void *abstract_font,
}
static void
cairo_type1_font_subset_destroy (void *abstract_font)
_cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
{
cairo_type1_font_subset_t *font = abstract_font;
unsigned int i;
/* If the subset generation failed, some of the pointers below may
@ -1282,17 +1275,15 @@ cairo_type1_font_subset_destroy (void *abstract_font)
if (font->base.base_font)
free (font->base.base_font);
free (font->glyphs);
free (font);
}
cairo_status_t
_cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset,
cairo_bool_t hex_encode)
{
cairo_type1_font_subset_t *font = NULL; /* hide compiler warning */
cairo_type1_font_subset_t font;
cairo_status_t status;
unsigned long parent_glyph, length;
unsigned int i;
@ -1308,21 +1299,21 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode);
status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
if (status)
return status;
for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
parent_glyph = scaled_font_subset->glyphs[i];
cairo_type1_font_subset_use_glyph (font, parent_glyph);
cairo_type1_font_subset_use_glyph (&font, parent_glyph);
}
status = cairo_type1_font_subset_generate (font, name);
status = cairo_type1_font_subset_generate (&font, name);
if (status)
goto fail1;
if (font->base.base_font) {
type1_subset->base_font = strdup (font->base.base_font);
if (font.base.base_font) {
type1_subset->base_font = strdup (font.base.base_font);
} else {
snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
scaled_font_subset->font_id, scaled_font_subset->subset_id);
@ -1331,37 +1322,38 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
if (type1_subset->base_font == NULL)
goto fail1;
type1_subset->widths = calloc (sizeof (int), font->num_glyphs);
type1_subset->widths = calloc (sizeof (int), font.num_glyphs);
if (type1_subset->widths == NULL)
goto fail2;
for (i = 0; i < font->base.num_glyphs; i++) {
if (font->glyphs[i].subset_index < 0)
for (i = 0; i < font.base.num_glyphs; i++) {
if (font.glyphs[i].subset_index < 0)
continue;
type1_subset->widths[font->glyphs[i].subset_index] =
font->glyphs[i].width;
type1_subset->widths[font.glyphs[i].subset_index] =
font.glyphs[i].width;
}
type1_subset->x_min = font->base.x_min;
type1_subset->y_min = font->base.y_min;
type1_subset->x_max = font->base.x_max;
type1_subset->y_max = font->base.y_max;
type1_subset->ascent = font->base.ascent;
type1_subset->descent = font->base.descent;
type1_subset->x_min = font.base.x_min;
type1_subset->y_min = font.base.y_min;
type1_subset->x_max = font.base.x_max;
type1_subset->y_max = font.base.y_max;
type1_subset->ascent = font.base.ascent;
type1_subset->descent = font.base.descent;
length = font->base.header_size + font->base.data_size +
font->base.trailer_size;
length = font.base.header_size +
font.base.data_size +
font.base.trailer_size;
type1_subset->data = malloc (length);
if (type1_subset->data == NULL)
goto fail3;
memcpy (type1_subset->data,
_cairo_array_index (&font->contents, 0), length);
_cairo_array_index (&font.contents, 0), length);
type1_subset->header_length = font->base.header_size;
type1_subset->data_length = font->base.data_size;
type1_subset->trailer_length = font->base.trailer_size;
type1_subset->header_length = font.base.header_size;
type1_subset->data_length = font.base.data_size;
type1_subset->trailer_length = font.base.trailer_size;
cairo_type1_font_subset_destroy (font);
_cairo_type1_font_subset_fini (&font);
return CAIRO_STATUS_SUCCESS;
@ -1370,7 +1362,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
fail2:
free (type1_subset->base_font);
fail1:
cairo_type1_font_subset_destroy (font);
_cairo_type1_font_subset_fini (&font);
return status;
}

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

@ -60,13 +60,17 @@ typedef struct cairo_type3_glyph_surface {
cairo_private cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image);
cairo_type3_glyph_surface_emit_image_t emit_image,
cairo_scaled_font_subsets_t *font_subsets);
cairo_private void
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
cairo_pdf_operators_use_font_subset_t use_font_subset,
void *closure);
cairo_private cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
cairo_box_t *bbox,
double *width);
_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
unsigned long glyph_index);
cairo_private cairo_status_t
_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,

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

@ -41,13 +41,15 @@
#include "cairo-type3-glyph-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-analysis-surface-private.h"
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image)
cairo_type3_glyph_surface_emit_image_t emit_image,
cairo_scaled_font_subsets_t *font_subsets)
{
cairo_type3_glyph_surface_t *surface;
cairo_matrix_t invert_y_axis;
@ -74,7 +76,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->stream,
&surface->cairo_to_pdf,
NULL);
font_subsets);
return &surface->base;
}
@ -263,10 +265,37 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
{
/* XXX: Some refactoring is required before we can add font
* subsets in the middle of emitting all the subsets. */
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_int_status_t status;
cairo_scaled_font_t *font;
cairo_matrix_t new_ctm, ctm_inverse;
int i;
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
for (i = 0; i < num_glyphs; i++)
cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
/* We require the matrix to be invertable. */
ctm_inverse = scaled_font->ctm;
status = cairo_matrix_invert (&ctm_inverse);
if (status)
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
cairo_matrix_multiply (&new_ctm, &scaled_font->ctm, &ctm_inverse);
font = cairo_scaled_font_create (scaled_font->font_face,
&scaled_font->font_matrix,
&new_ctm,
&scaled_font->options);
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
font);
cairo_scaled_font_destroy (font);
return status;
}
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
@ -316,7 +345,7 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
cairo_status_t status;
cairo_image_surface_t *image;
cairo_matrix_t mat;
double width, height, x, y;
double x, y;
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
@ -332,14 +361,10 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) -
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) -
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
mat.xx = width;
mat.xx = image->width;
mat.xy = 0;
mat.yx = 0;
mat.yy = height;
mat.yy = image->height;
mat.x0 = x;
mat.y0 = y;
cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
@ -348,20 +373,65 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
}
cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
cairo_box_t *bbox,
double *width)
void
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
cairo_pdf_operators_use_font_subset_t use_font_subset,
void *closure)
{
bbox->p1.x = 0;
bbox->p1.y = 0;
bbox->p2.x = 0;
bbox->p2.y = 0;
*width = 0.0;
_cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n");
cairo_type3_glyph_surface_t *surface = abstract_surface;
return CAIRO_STATUS_SUCCESS;
_cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
use_font_subset,
closure);
}
cairo_status_t
_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
unsigned long glyph_index)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status, status2;
cairo_output_stream_t *null_stream;
null_stream = _cairo_null_stream_create ();
_cairo_type3_glyph_surface_set_stream (surface, null_stream);
_cairo_scaled_font_freeze_cache (surface->scaled_font);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
&scaled_glyph);
if (_cairo_status_is_error (status))
goto cleanup;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = CAIRO_STATUS_SUCCESS;
goto cleanup;
}
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
if (status)
goto cleanup;
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
status = CAIRO_STATUS_SUCCESS;
cleanup:
_cairo_scaled_font_thaw_cache (surface->scaled_font);
status2 = _cairo_output_stream_destroy (null_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
return status;
}
cairo_status_t
@ -379,23 +449,24 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
cairo_matrix_t font_matrix_inverse;
_cairo_type3_glyph_surface_set_stream (surface, stream);
_cairo_scaled_font_freeze_cache (surface->scaled_font);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
&scaled_glyph);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
return status;
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
if (status == CAIRO_STATUS_SUCCESS)
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
if (_cairo_status_is_error (status)) {
_cairo_scaled_font_thaw_cache (surface->scaled_font);
return status;
}
x_advance = scaled_glyph->metrics.x_advance;
@ -429,7 +500,12 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_output_stream_printf (surface->stream, "q\n");
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
&surface->base);
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_printf (surface->stream, "Q\n");
_cairo_type3_glyph_surface_set_stream (surface, stream);
@ -437,13 +513,15 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_memory_stream_copy (mem_stream, stream);
status2 = _cairo_output_stream_destroy (mem_stream);
if (status2)
return status2;
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
_cairo_scaled_font_thaw_cache (surface->scaled_font);
return status;
}

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

@ -39,8 +39,6 @@
#ifndef CAIRO_TYPES_PRIVATE_H
#define CAIRO_TYPES_PRIVATE_H
/* This is the only header file not including cairoint.h. It only contains
* typedefs.*/
#include "cairo.h"
#include "cairo-fixed-type-private.h"
@ -118,7 +116,6 @@ struct _cairo_array {
struct _cairo_font_options {
cairo_antialias_t antialias;
cairo_subpixel_order_t subpixel_order;
cairo_lcd_filter_t lcd_filter;
cairo_hint_style_t hint_style;
cairo_hint_metrics_t hint_metrics;
};
@ -134,6 +131,24 @@ struct _cairo_cache {
int freeze_count;
};
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this
madness). I'm still working on a cleaner API, but in the meantime,
at least this does prevent precision loss in color when changing
alpha. */
struct _cairo_color {
double red;
double green;
double blue;
double alpha;
unsigned short red_short;
unsigned short green_short;
unsigned short blue_short;
unsigned short alpha_short;
};
typedef enum _cairo_paginated_mode {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */

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

@ -230,7 +230,7 @@ _cairo_utf8_get_char_validated (const char *p,
}
/**
* _cairo_utf8_to_utf32:
* _cairo_utf8_to_ucs4:
* @str: an UTF-8 string
* @len: length of @str in bytes, or -1 if it is nul-terminated.
* If @len is supplied and the string has an embedded nul
@ -247,7 +247,7 @@ _cairo_utf8_get_char_validated (const char *p,
*
* Return value: %CAIRO_STATUS_SUCCESS if the entire string was
* successfully converted. %CAIRO_STATUS_INVALID_STRING if an
* an invalid sequence was found.
* invalid sequence was found.
**/
cairo_status_t
_cairo_utf8_to_ucs4 (const char *str,
@ -302,6 +302,8 @@ _cairo_utf8_to_ucs4 (const char *str,
* @utf8: buffer to write utf8 string into. Must have at least 4 bytes
* space available. Or %NULL.
*
* This space left intentionally blank.
*
* Return value: Number of bytes in the utf8 string or 0 if an invalid
* unicode character
**/

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

@ -96,8 +96,6 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
return cr;
}
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend;
static cairo_int_status_t
_cairo_user_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
@ -153,9 +151,14 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
cairo_surface_destroy (null_surface);
status = analysis_surface->status;
if (status)
return status;
_cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
_cairo_analysis_surface_set_ctm (analysis_surface,
&scaled_font->extent_scale);
status = _cairo_meta_surface_replay (meta_surface,
analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
@ -271,16 +274,16 @@ _cairo_user_ucs4_to_index (void *abstract_font,
}
static cairo_int_status_t
_cairo_user_text_to_glyphs (void *abstract_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
_cairo_user_text_to_glyphs (void *abstract_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags)
{
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -290,18 +293,22 @@ _cairo_user_text_to_glyphs (void *abstract_font,
if (face->scaled_font_methods.text_to_glyphs) {
int i;
cairo_glyph_t *orig_glyphs = *glyphs;
int orig_num_glyphs = *num_glyphs;
status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
clusters, num_clusters, cluster_flags);
if (status != CAIRO_STATUS_SUCCESS)
return status;
if (*num_glyphs < 0) {
if (orig_glyphs != *glyphs) {
cairo_glyph_free (*glyphs);
*glyphs = orig_glyphs;
}
*num_glyphs = orig_num_glyphs;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -322,16 +329,79 @@ _cairo_user_text_to_glyphs (void *abstract_font,
return status;
}
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend = {
static cairo_status_t
_cairo_user_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 **scaled_font);
static cairo_status_t
_cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face_out)
{
static cairo_user_data_key_t twin_font_face_key;
cairo_font_face_t *face;
cairo_status_t status;
face = cairo_font_face_get_user_data (&toy_face->base,
&twin_font_face_key);
if (!face) {
face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base),
cairo_toy_font_face_get_weight (&toy_face->base));
status = cairo_font_face_set_user_data (&toy_face->base,
&twin_font_face_key,
face,
(cairo_destroy_func_t) cairo_font_face_destroy);
if (status) {
cairo_font_face_destroy (face);
return status;
}
}
*font_face_out = face;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_user_scaled_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 *font_options,
cairo_scaled_font_t **font)
{
cairo_font_face_t *face;
cairo_status_t status;
status = _cairo_user_scaled_font_get_implementation (toy_face, &face);
if (status)
return status;
status = _cairo_user_font_face_scaled_font_create (face,
font_matrix,
ctm,
font_options,
font);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
CAIRO_FONT_TYPE_USER,
NULL, /* create_toy */
_cairo_user_scaled_font_get_implementation,
_cairo_user_scaled_font_create_toy, /* create_toy */
NULL, /* scaled_font_fini */
_cairo_user_scaled_glyph_init,
_cairo_user_text_to_glyphs,
_cairo_user_ucs4_to_index,
NULL, /* show_glyphs */
NULL, /* load_truetype_table */
NULL, /* map_glyphs_to_unicode */
NULL /* index_to_ucs4 */
};
/* #cairo_user_font_face_t */
@ -352,12 +422,12 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
if (user_scaled_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_scaled_font_init (&user_scaled_font->base,
&font_face->base,
font_matrix, ctm, options,
&cairo_user_scaled_font_backend);
&_cairo_user_scaled_font_backend);
if (status) {
free (user_scaled_font);
@ -397,29 +467,31 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
}
}
if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) {
cairo_t *cr;
if (status == CAIRO_STATUS_SUCCESS &&
font_face->scaled_font_methods.init != NULL)
{
/* Lock the scaled_font mutex such that user doesn't accidentally try
* to use it just yet. */
CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
/* Give away fontmap lock such that user-font can use other fonts */
_cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
if (status == CAIRO_STATUS_SUCCESS) {
cairo_t *cr;
cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
cr,
&font_extents);
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
cr,
&font_extents);
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
cairo_destroy (cr);
cairo_destroy (cr);
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
}
CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
}
@ -427,7 +499,6 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
if (status != CAIRO_STATUS_SUCCESS) {
_cairo_scaled_font_fini (&user_scaled_font->base);
free (user_scaled_font);
@ -448,6 +519,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
CAIRO_FONT_TYPE_USER,
NULL, /* destroy */
NULL, /* direct implementation */
_cairo_user_font_face_scaled_font_create
};
@ -497,6 +569,7 @@ cairo_user_font_face_create (void)
return &font_face->base;
}
slim_hidden_def(cairo_user_font_face_create);
/* User-font method setters */
@ -520,17 +593,24 @@ void
cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_init_func_t init_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
user_font_face = (cairo_user_font_face_t *) font_face;
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.init = init_func;
}
slim_hidden_def(cairo_user_font_face_set_init_func);
/**
* cairo_user_font_face_set_render_glyph_func:
@ -555,17 +635,24 @@ void
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
user_font_face = (cairo_user_font_face_t *) font_face;
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
}
slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
/**
* cairo_user_font_face_set_text_to_glyphs_func:
@ -586,11 +673,17 @@ void
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
user_font_face = (cairo_user_font_face_t *) font_face;
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
@ -617,17 +710,23 @@ void
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
user_font_face = (cairo_user_font_face_t *) font_face;
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
}
slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
/* User-font method getters */
@ -638,18 +737,24 @@ cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t
* Gets the scaled-font initialization function of a user-font.
*
* Return value: The init callback of @font_face
* or %NULL if none set.
* or %NULL if none set or an error has occurred.
*
* Since: 1.8
**/
cairo_user_scaled_font_init_func_t
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return NULL;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
user_font_face = (cairo_user_font_face_t *) font_face;
return user_font_face->scaled_font_methods.init;
}
@ -660,18 +765,24 @@ cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
* Gets the glyph rendering function of a user-font.
*
* Return value: The render_glyph callback of @font_face
* or %NULL if none set.
* or %NULL if none set or an error has occurred.
*
* Since: 1.8
**/
cairo_user_scaled_font_render_glyph_func_t
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return NULL;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
user_font_face = (cairo_user_font_face_t *) font_face;
return user_font_face->scaled_font_methods.render_glyph;
}
@ -682,18 +793,24 @@ cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
* Gets the text-to-glyphs conversion function of a user-font.
*
* Return value: The text_to_glyphs callback of @font_face
* or %NULL if none set.
* or %NULL if none set or an error occurred.
*
* Since: 1.8
**/
cairo_user_scaled_font_text_to_glyphs_func_t
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return NULL;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
user_font_face = (cairo_user_font_face_t *) font_face;
return user_font_face->scaled_font_methods.text_to_glyphs;
}
@ -704,17 +821,23 @@ cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
* Gets the unicode-to-glyph conversion function of a user-font.
*
* Return value: The unicode_to_glyph callback of @font_face
* or %NULL if none set.
* or %NULL if none set or an error occurred.
*
* Since: 1.8
**/
cairo_user_scaled_font_unicode_to_glyph_func_t
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
cairo_user_font_face_t *user_font_face;
if (font_face->status)
return NULL;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
user_font_face = (cairo_user_font_face_t *) font_face;
return user_font_face->scaled_font_methods.unicode_to_glyph;
}

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

@ -47,7 +47,7 @@
* as a pair of 32-bit ints
*/
#define I cairo_private
#define I cairo_private cairo_const
#if !HAVE_UINT64_T
@ -61,8 +61,10 @@ cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift);
cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift);
cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift);
int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b);
int I _cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b);
int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b);
cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a);
#define _cairo_uint64_is_zero(a) ((a).hi == 0 && (a).lo == 0)
#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0)
cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a);
@ -75,7 +77,9 @@ cairo_int64_t I _cairo_int32_to_int64(int32_t i);
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
int I _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b);
int I _cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b);
#define _cairo_int64_is_zero(a) _cairo_uint64_is_zero (a)
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b)
@ -96,6 +100,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b))
#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b)))
#define _cairo_uint64_lt(a,b) ((a) < (b))
#define _cairo_uint64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
#define _cairo_uint64_is_zero(a) ((a) == 0)
#define _cairo_uint64_eq(a,b) ((a) == (b))
#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a)))
#define _cairo_uint64_negative(a) ((int64_t) (a) < 0)
@ -111,6 +117,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_int64_mul(a,b) ((a) * (b))
#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b))
#define _cairo_int64_lt(a,b) ((a) < (b))
#define _cairo_int64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
#define _cairo_int64_is_zero(a) ((a) == 0)
#define _cairo_int64_eq(a,b) ((a) == (b))
#define _cairo_int64_lsl(a,b) ((a) << (b))
#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b)))
@ -165,7 +173,9 @@ cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift);
cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift);
cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift);
int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b);
int I _cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b);
int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b);
#define _cairo_uint128_is_zero(a) (_cairo_uint64_is_zero ((a).hi) && _cairo_uint64_is_zero ((a).lo))
cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
@ -181,10 +191,13 @@ cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
#define _cairo_int64x32_128_mul(a, b) _cairo_int64x64_128_mul(a, _cairo_int32_to_int64(b))
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
int I _cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b);
#define _cairo_int128_is_zero(a) _cairo_uint128_is_zero (a)
#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b)
#define _cairo_int128_negate(a) _cairo_uint128_negate(a)
#define _cairo_int128_negative(a) (_cairo_uint128_negative(a))
@ -204,6 +217,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b))
#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b)))
#define _cairo_uint128_lt(a,b) ((a) < (b))
#define _cairo_uint128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
#define _cairo_uint128_is_zero(a) ((a) == 0)
#define _cairo_uint128_eq(a,b) ((a) == (b))
#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a)))
#define _cairo_uint128_negative(a) ((int128_t) (a) < 0)
@ -221,6 +236,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
#define _cairo_int128_mul(a,b) ((a) * (b))
#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b))
#define _cairo_int128_lt(a,b) ((a) < (b))
#define _cairo_int128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
#define _cairo_int128_is_zero(a) ((a) == 0)
#define _cairo_int128_eq(a,b) ((a) == (b))
#define _cairo_int128_lsl(a,b) ((a) << (b))
#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b)))

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

@ -37,6 +37,8 @@
#ifndef CAIRO_WIDEINT_TYPE_H
#define CAIRO_WIDEINT_TYPE_H
#include "cairo.h"
#if HAVE_CONFIG_H
#include "config.h"
#endif

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

@ -235,6 +235,32 @@ _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b)
return _cairo_uint64_lt (a, b);
}
int
_cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b)
{
if (a.hi < b.hi)
return -1;
else if (a.hi > b.hi)
return 1;
else if (a.lo < b.lo)
return -1;
else if (a.lo > b.lo)
return 1;
else
return 0;
}
int
_cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b)
{
if (_cairo_int64_negative (a) && !_cairo_int64_negative (b))
return -1;
if (!_cairo_int64_negative (a) && _cairo_int64_negative (b))
return 1;
return _cairo_uint64_cmp (a, b);
}
cairo_uint64_t
_cairo_uint64_not (cairo_uint64_t a)
{
@ -569,6 +595,28 @@ _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b)
return _cairo_uint128_lt (a, b);
}
int
_cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b)
{
int cmp;
cmp = _cairo_uint64_cmp (a.hi, b.hi);
if (cmp)
return cmp;
return _cairo_uint64_cmp (a.lo, b.lo);
}
int
_cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b)
{
if (_cairo_int128_negative (a) && !_cairo_int128_negative (b))
return -1;
if (!_cairo_int128_negative (a) && _cairo_int128_negative (b))
return 1;
return _cairo_uint128_cmp (a, b);
}
int
_cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
{

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

@ -640,21 +640,25 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
goto FAIL2;
goto FAIL3;
}
*num_glyphs = n16;
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
if (!*glyphs) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL2;
goto FAIL3;
}
x_pos = x;
y_pos = y;
mat = scaled_font->base.ctm;
status = cairo_matrix_invert (&mat);
assert (status == CAIRO_STATUS_SUCCESS);
_cairo_scaled_font_freeze_cache (&scaled_font->base);
for (i = 0; i < n16; i++) {
cairo_scaled_glyph_t *scaled_glyph;
@ -668,7 +672,8 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
&scaled_glyph);
if (status) {
free (*glyphs);
goto FAIL2;
*glyphs = NULL;
break;
}
x = scaled_glyph->x_advance;
@ -678,8 +683,10 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
y_pos += y;
}
cairo_win32_scaled_font_done_font (&scaled_font->base);
_cairo_scaled_font_thaw_cache (&scaled_font->base);
FAIL3:
cairo_win32_scaled_font_done_font (&scaled_font->base);
FAIL2:
free (glyph_indices);
FAIL1:
@ -1829,6 +1836,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
CAIRO_FONT_TYPE_WIN32,
NULL,
_cairo_win32_scaled_font_create_toy,
_cairo_win32_scaled_font_fini,
_cairo_win32_scaled_font_glyph_init,
@ -1898,6 +1906,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
CAIRO_FONT_TYPE_WIN32,
_cairo_win32_font_face_destroy,
NULL, /* direct implementation */
_cairo_win32_font_face_scaled_font_create
};

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

@ -490,7 +490,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
{
cairo_status_t status;
cairo_extend_t extend;
cairo_surface_t *pat_surface;
cairo_surface_attributes_t pat_attr;
cairo_image_surface_t *image;
void *image_extra;
@ -516,25 +515,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
background_color = CAIRO_COLOR_BLACK;
extend = cairo_pattern_get_extend (&pattern->base);
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
(cairo_surface_t *)surface,
0, 0, -1, -1,
&pat_surface, &pat_attr);
status = _cairo_surface_acquire_source_image (pattern->surface,
&image, &image_extra);
if (status)
return status;
status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
if (status)
goto FINISH;
if (image->base.status) {
status = image->base.status;
goto FINISH2;
goto CLEANUP_IMAGE;
}
if (image->width == 0 || image->height == 0) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH2;
goto CLEANUP_IMAGE;
}
if (image->format != CAIRO_FORMAT_RGB24) {
@ -545,7 +539,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
image->height);
if (opaque_surface->status) {
status = opaque_surface->status;
goto FINISH3;
goto CLEANUP_OPAQUE_IMAGE;
}
_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
@ -557,7 +551,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
image->width, image->height);
if (status) {
_cairo_pattern_fini (&opaque_pattern.base);
goto FINISH3;
goto CLEANUP_OPAQUE_IMAGE;
}
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
@ -571,7 +565,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
image->height);
if (status) {
_cairo_pattern_fini (&opaque_pattern.base);
goto FINISH3;
goto CLEANUP_OPAQUE_IMAGE;
}
_cairo_pattern_fini (&opaque_pattern.base);
@ -602,8 +596,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
SaveDC (surface->dc);
_cairo_matrix_to_win32_xform (&m, &xform);
if (!SetWorldTransform (surface->dc, &xform))
return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
if (! SetWorldTransform (surface->dc, &xform)) {
status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
goto CLEANUP_OPAQUE_IMAGE;
}
oldmode = SetStretchBltMode(surface->dc, HALFTONE);
@ -635,19 +631,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
&bi,
DIB_RGB_COLORS,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
{
status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
goto CLEANUP_OPAQUE_IMAGE;
}
}
}
SetStretchBltMode(surface->dc, oldmode);
RestoreDC (surface->dc, -1);
FINISH3:
CLEANUP_OPAQUE_IMAGE:
if (opaque_image != image)
cairo_surface_destroy (opaque_surface);
FINISH2:
_cairo_surface_release_source_image (pat_surface, image, image_extra);
FINISH:
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
CLEANUP_IMAGE:
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
return status;
}
@ -1525,6 +1522,12 @@ _cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
surface->paginated_mode = paginated_mode;
}
static cairo_bool_t
_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface)
{
return TRUE;
}
/**
* cairo_win32_printing_surface_create:
* @hdc: the DC to create a surface for
@ -1645,4 +1648,6 @@ static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_bac
_cairo_win32_printing_surface_start_page,
_cairo_win32_printing_surface_set_paginated_mode,
NULL, /* set_bounding_box */
NULL, /* _cairo_win32_printing_surface_has_fallback_images, */
_cairo_win32_printing_surface_supports_fine_grained_fallbacks,
};

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

@ -160,6 +160,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out);
static inline void

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

@ -435,6 +435,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_content_t src_content;
@ -444,10 +446,16 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
src_content = cairo_surface_get_content(src);
new_surface =
_cairo_win32_surface_create_similar_internal (abstract_surface, src_content, width, height, FALSE);
_cairo_win32_surface_create_similar_internal (abstract_surface,
src_content,
width, height,
FALSE);
if (new_surface == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (cairo_surface_status(new_surface))
return cairo_surface_status(new_surface);
status = new_surface->status;
if (status)
return status;
_cairo_pattern_init_for_surface (&pattern, src);
@ -462,9 +470,11 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
_cairo_pattern_fini (&pattern.base);
if (status == CAIRO_STATUS_SUCCESS)
if (status == CAIRO_STATUS_SUCCESS) {
*clone_offset_x = src_x;
*clone_offset_y = src_y;
*clone_out = new_surface;
else
} else
cairo_surface_destroy (new_surface);
return status;
@ -512,8 +522,10 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
local =
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
(surface, content, width, height, TRUE);
if (local == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (local->base.status)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return local->base.status;
status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -2005,34 +2017,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
*/
#if !defined(CAIRO_WIN32_STATIC_BUILD)
/* declare to avoid "no previous prototype for 'DllMain'" warning */
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
CAIRO_MUTEX_INITIALIZE ();
break;
case DLL_PROCESS_DETACH:
CAIRO_MUTEX_FINALIZE ();
break;
}
return TRUE;
}
#endif
cairo_int_status_t
_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
{

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

@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
cairo_public cairo_surface_t *
cairo_win32_surface_get_image (cairo_surface_t *surface);
#if CAIRO_HAS_WIN32_FONT
/*
* Win32 font support
*/
cairo_public cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
@ -95,6 +101,8 @@ cairo_public void
cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
cairo_matrix_t *device_to_logical);
#endif /* CAIRO_HAS_WIN32_FONT */
CAIRO_END_DECLS
#else /* CAIRO_HAS_WIN32_SURFACE */

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

@ -197,7 +197,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
xrender_format,
width, height);
if (surface->base.status)
return surface;
return &surface->base;
surface->owns_pixmap = TRUE;
@ -695,6 +695,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -704,6 +706,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src;
if (_cairo_xcb_surface_same_screen(surface, xcb_src)) {
*clone_offset_x = 0;
*clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
@ -711,19 +715,29 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
cairo_content_t content = _cairo_content_from_format (image_src->format);
cairo_status_t status;
if (surface->base.status)
return surface->base.status;
clone = (cairo_xcb_surface_t *)
_cairo_xcb_surface_create_similar (surface, content,
image_src->width, image_src->height);
_cairo_xcb_surface_create_similar (surface, content, width, height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (clone->base.status)
return clone->base.status;
_draw_image_surface (clone, image_src, src_x, src_y,
width, height, src_x, src_y);
status = _draw_image_surface (clone, image_src,
src_x, src_y,
width, height,
0, 0);
if (status) {
cairo_surface_destroy (&clone->base);
return status;
}
*clone_offset_x = src_x;
*clone_offset_y = src_y;
*clone_out = &clone->base;
return CAIRO_STATUS_SUCCESS;
@ -879,7 +893,9 @@ _surfaces_compatible (cairo_xcb_surface_t *dst,
return FALSE;
/* if Render is supported, match picture formats */
if (src->xrender_format.id != XCB_NONE && src->xrender_format.id == dst->xrender_format.id)
if (src->xrender_format.id != dst->xrender_format.id)
return FALSE;
else if (src->xrender_format.id != XCB_NONE)
return TRUE;
/* Without Render, match visuals instead */
@ -1111,6 +1127,7 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
cairo_int_status_t status;
composite_operation_t operation;
int itx, ity;
cairo_bool_t is_integer_translation;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1200,7 +1217,9 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
*/
_cairo_xcb_surface_ensure_gc (dst);
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
is_integer_translation =
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
assert (is_integer_translation == TRUE);
{
uint32_t mask = XCB_GC_FILL_STYLE | XCB_GC_TILE
| XCB_GC_TILE_STIPPLE_ORIGIN_X
@ -1319,7 +1338,7 @@ _create_a8_picture (cairo_xcb_surface_t *surface,
/* Creates a temporary mask for the trapezoids covering the area
* [@dst_x, @dst_y, @width, @height] of the destination surface.
*/
static xcb_render_picture_t
static cairo_status_t
_create_trapezoid_mask (cairo_xcb_surface_t *dst,
cairo_trapezoid_t *traps,
int num_traps,
@ -1327,7 +1346,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
int dst_y,
int width,
int height,
xcb_render_pictforminfo_t *pict_format)
xcb_render_pictforminfo_t *pict_format,
xcb_render_picture_t *mask_picture_out)
{
xcb_render_color_t transparent = { 0, 0, 0, 0 };
xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff };
@ -1346,10 +1366,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
if (!offset_traps) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return XCB_NONE;
}
if (offset_traps == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < num_traps; i++) {
offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y;
@ -1373,7 +1391,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
xcb_render_free_picture (dst->dpy, solid_picture);
free (offset_traps);
return mask_picture;
*mask_picture_out = mask_picture;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -1460,13 +1479,14 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
* bounds and clip. (xcb_render_add_traps() could be used to make creating
* the mask somewhat cheaper.)
*/
xcb_render_picture_t mask_picture = _create_trapezoid_mask (dst, traps, num_traps,
dst_x, dst_y, width, height,
render_format);
if (!mask_picture) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
xcb_render_picture_t mask_picture = 0; /* silence compiler */
status = _create_trapezoid_mask (dst, traps, num_traps,
dst_x, dst_y, width, height,
render_format,
&mask_picture);
if (status)
goto BAIL;
}
xcb_render_composite (dst->dpy,
_render_operator (op),
@ -1639,6 +1659,12 @@ _cairo_xcb_surface_is_similar (void *surface_a,
cairo_xcb_surface_t *b = surface_b;
xcb_render_pictforminfo_t *xrender_format;
/* XXX: disable caching by the solid pattern cache until we implement
* display notification to avoid issuing xcb calls from the wrong thread
* or accessing the surface after the Display has been closed.
*/
return FALSE;
if (! _cairo_xcb_surface_same_screen (a, b))
return FALSE;
@ -1959,9 +1985,10 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
int height)
{
cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) abstract_surface;
cairo_status_t status_ignored;
if (! _cairo_surface_is_xcb (abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
status_ignored = _cairo_surface_set_error (abstract_surface,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
@ -2305,14 +2332,121 @@ typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t)
(cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int,
const cairo_glyph_t *, int, cairo_scaled_font_t *);
static cairo_bool_t
_cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst,
cairo_scaled_font_t *scaled_font)
{
cairo_xcb_surface_font_private_t *font_private;
font_private = scaled_font->surface_private;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
(font_private != NULL && font_private->dpy != dst->dpy))
{
return FALSE;
}
return TRUE;
}
static cairo_status_t
_cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xcb_surface_t *src,
cairo_surface_attributes_t *attributes,
int *remaining_glyphs)
{
cairo_scaled_glyph_t *scaled_glyph;
int i, o;
unsigned long max_index = 0;
cairo_status_t status;
cairo_glyph_t *output_glyphs;
const cairo_glyph_t *glyphs_chunk;
int glyphs_remaining, chunk_size, max_chunk_size;
cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
/* We make a copy of the glyphs so that we can elide any size-zero
* glyphs to workaround an X server bug, (present in at least Xorg
* 7.1 without EXA). */
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0, o = 0; i < num_glyphs; i++) {
if (glyphs[i].index > max_index)
max_index = glyphs[i].index;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status) {
free (output_glyphs);
return status;
}
/* Don't put any size-zero glyphs into output_glyphs to avoid
* an X server bug which stops rendering glyphs after the
* first size-zero glyph. */
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
output_glyphs[o++] = glyphs[i];
if (scaled_glyph->surface_private == NULL) {
_cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
}
}
}
num_glyphs = o;
_cairo_xcb_surface_ensure_dst_picture (dst);
max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
if (max_index < 256) {
/* XXX: these are all the same size! (28) */
max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
} else if (max_index < 65536) {
max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
} else {
max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
}
/* XXX: I think this is wrong; this is only the header size (2 longs) */
/* but should also include the glyph (1 long) */
/* max_chunk_size /= sz_xGlyphElt; */
max_chunk_size /= 3*sizeof(uint32_t);
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
glyphs_remaining;
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
{
chunk_size = MIN (glyphs_remaining, max_chunk_size);
status = show_glyphs_func (dst, op, src,
attributes->x_offset, attributes->y_offset,
glyphs_chunk, chunk_size, scaled_font);
if (status) {
free (output_glyphs);
return status;
}
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_xcb_surface_t *dst = abstract_dst;
@ -2321,17 +2455,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xcb_surface_t *src = NULL;
cairo_glyph_t *output_glyphs;
const cairo_glyph_t *glyphs_chunk;
int glyphs_remaining, chunk_size, max_chunk_size;
cairo_scaled_glyph_t *scaled_glyph;
cairo_xcb_surface_font_private_t *font_private;
int i, o;
unsigned long max_index = 0;
cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
cairo_solid_pattern_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
@ -2365,29 +2488,16 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
font_private = scaled_font->surface_private;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
(font_private != NULL && font_private->dpy != dst->dpy))
if (! _cairo_xcb_surface_owns_font (dst, scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* We make a copy of the glyphs so that we can elide any size-zero
* glyphs to workaround an X server bug, (present in at least Xorg
* 7.1 without EXA). */
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
* them. We tie into the scaled_font's glyph cache and remove
* glyphs from the X server when they are ejected from the
* scaled_font cache. Because of this we first freeze the
* scaled_font's cache so that we don't cause any of our glyphs to
* be ejected and removed from the X server before we have a
* chance to render them. */
_cairo_scaled_font_freeze_cache (scaled_font);
* scaled_font cache.
*/
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
* the mask (the glyphs). This code below was executed as a side effect
@ -2437,64 +2547,21 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
goto BAIL;
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
for (i = 0, o = 0; i < num_glyphs; i++) {
if (glyphs[i].index > max_index)
max_index = glyphs[i].index;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status != CAIRO_STATUS_SUCCESS)
goto BAIL;
/* Don't put any size-zero glyphs into output_glyphs to avoid
* an X server bug which stops rendering glyphs after the
* first size-zero glyph. */
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
output_glyphs[o++] = glyphs[i];
if (scaled_glyph->surface_private == NULL) {
_cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
}
}
}
num_glyphs = o;
_cairo_scaled_font_freeze_cache (scaled_font);
_cairo_xcb_surface_ensure_dst_picture (dst);
max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
if (max_index < 256) {
/* XXX: these are all the same size! (28) */
max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
} else if (max_index < 65536) {
max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
} else {
max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
}
/* XXX: I think this is wrong; this is only the header size (2 longs) */
/* but should also include the glyph (1 long) */
/* max_chunk_size /= sz_xGlyphElt; */
max_chunk_size /= 3*sizeof(uint32_t);
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
glyphs_remaining;
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
{
chunk_size = MIN (glyphs_remaining, max_chunk_size);
status = show_glyphs_func (dst, op, src,
attributes.x_offset, attributes.y_offset,
glyphs_chunk, chunk_size, scaled_font);
if (status != CAIRO_STATUS_SUCCESS)
break;
}
if (_cairo_xcb_surface_owns_font (dst, scaled_font))
status = _cairo_xcb_surface_emit_glyphs (dst,
glyphs, num_glyphs,
scaled_font,
op,
src,
&attributes,
remaining_glyphs);
else
status = CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_scaled_font_thaw_cache (scaled_font);
BAIL:
_cairo_scaled_font_thaw_cache (scaled_font);
free (output_glyphs);
if (src)
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
if (src_pattern == &solid_pattern.base)

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

@ -150,22 +150,13 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
cairo_bool_t xft_antialias;
int xft_hintstyle;
int xft_rgba;
int xft_lcdfilter;
cairo_antialias_t antialias;
cairo_subpixel_order_t subpixel_order;
cairo_lcd_filter_t lcd_filter;
cairo_hint_style_t hint_style;
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
xft_antialias = TRUE;
if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
/* -1 is an non-existant Fontconfig constant used to differentiate
* the case when no lcdfilter property is available.
*/
xft_lcdfilter = -1;
}
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
xft_hinting = TRUE;
@ -248,24 +239,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
}
switch (xft_lcdfilter) {
case FC_LCD_NONE:
lcd_filter = CAIRO_LCD_FILTER_NONE;
break;
case FC_LCD_DEFAULT:
lcd_filter = CAIRO_LCD_FILTER_FIR5;
break;
case FC_LCD_LIGHT:
lcd_filter = CAIRO_LCD_FILTER_FIR3;
break;
case FC_LCD_LEGACY:
lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
break;
default:
lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
break;
}
if (xft_antialias) {
if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
antialias = CAIRO_ANTIALIAS_GRAY;
@ -278,7 +251,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
cairo_font_options_set_hint_style (&info->font_options, hint_style);
cairo_font_options_set_antialias (&info->font_options, antialias);
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
}

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

@ -147,7 +147,7 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
return NULL;
xrender_format = _cairo_xlib_display_get_xrender_format (
src->screen_info->display,
src->display,
format);
if (xrender_format == NULL)
return NULL;
@ -211,7 +211,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY));
_cairo_xlib_display_notify (src->screen_info->display);
_cairo_xlib_display_notify (src->display);
/* Start by examining the surface's XRenderFormat, or if it
* doesn't have one, then look one up through its visual (in the
@ -259,9 +259,7 @@ static cairo_status_t
_cairo_xlib_surface_finish (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
cairo_xlib_display_t *display = surface->screen_info ?
surface->screen_info->display :
NULL;
cairo_xlib_display_t *display = surface->display;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (surface->owns_pixmap) {
@ -345,7 +343,7 @@ _swap_ximage_2bytes (XImage *ximage)
char *line = ximage->data;
for (j = ximage->height; j; j--) {
uint16_t *p = (uint16_t *)line;
uint16_t *p = (uint16_t *) line;
for (i = ximage->width; i; i--) {
*p = bswap_16 (*p);
p++;
@ -355,6 +353,26 @@ _swap_ximage_2bytes (XImage *ximage)
}
}
static void
_swap_ximage_3bytes (XImage *ximage)
{
int i, j;
char *line = ximage->data;
for (j = ximage->height; j; j--) {
uint8_t *p = (uint8_t *) line;
for (i = ximage->width; i; i--) {
uint8_t tmp;
tmp = p[2];
p[2] = p[0];
p[0] = tmp;
p += 3;
}
line += ximage->bytes_per_line;
}
}
static void
_swap_ximage_4bytes (XImage *ximage)
{
@ -362,7 +380,7 @@ _swap_ximage_4bytes (XImage *ximage)
char *line = ximage->data;
for (j = ximage->height; j; j--) {
uint32_t *p = (uint32_t *)line;
uint32_t *p = (uint32_t *) line;
for (i = ximage->width; i; i--) {
*p = bswap_32 (*p);
p++;
@ -372,6 +390,23 @@ _swap_ximage_4bytes (XImage *ximage)
}
}
static void
_swap_ximage_nibbles (XImage *ximage)
{
int i, j;
char *line = ximage->data;
for (j = ximage->height; j; j--) {
uint8_t *p = (uint8_t *) line;
for (i = (ximage->width + 1) / 2; i; i--) {
*p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
p++;
}
line += ximage->bytes_per_line;
}
}
static void
_swap_ximage_bits (XImage *ximage)
{
@ -404,7 +439,8 @@ _swap_ximage_to_native (XImage *ximage)
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
if (ximage->bits_per_pixel == 1 &&
ximage->bitmap_bit_order != native_byte_order) {
ximage->bitmap_bit_order != native_byte_order)
{
_swap_ximage_bits (ximage);
if (ximage->bitmap_bit_order == ximage->byte_order)
return;
@ -417,25 +453,32 @@ _swap_ximage_to_native (XImage *ximage)
case 1:
unit_bytes = ximage->bitmap_unit / 8;
break;
case 4:
_swap_ximage_nibbles (ximage);
/* fall-through */
case 8:
case 16:
case 20:
case 24:
case 28:
case 30:
case 32:
unit_bytes = ximage->bits_per_pixel / 8;
unit_bytes = (ximage->bits_per_pixel + 7) / 8;
break;
default:
/* This could be hit on some uncommon but possible cases,
* such as bpp=4. These are cases that libpixman can't deal
* with in any case.
*/
/* This could be hit on some rare but possible cases. */
ASSERT_NOT_REACHED;
}
switch (unit_bytes) {
case 1:
return;
break;
case 2:
_swap_ximage_2bytes (ximage);
break;
case 3:
_swap_ximage_3bytes (ximage);
break;
case 4:
_swap_ximage_4bytes (ximage);
break;
@ -678,8 +721,11 @@ _get_image_surface (cairo_xlib_surface_t *surface,
xlib_masks.green_mask = surface->g_mask;
xlib_masks.blue_mask = surface->b_mask;
status = _pixman_format_from_masks (&xlib_masks, &pixman_format);
if (xlib_masks.bpp >= 24 &&status == CAIRO_STATUS_SUCCESS) {
if (_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
xlib_masks.bpp >= 24 &&
ximage->bitmap_unit == 32 &&
ximage->bitmap_pad == 32)
{
image = (cairo_image_surface_t*)
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
pixman_format,
@ -1009,7 +1055,14 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
else
in_pixel = row[x];
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
/* If the incoming image has no alpha channel, then the input
* is opaque and the output should have the maximum alpha value.
* For all other channels, their absence implies 0.
*/
if (image_masks.alpha_mask == 0x0)
a = 0xff;
else
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
@ -1054,7 +1107,7 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
cairo_image_surface_t *image;
cairo_status_t status;
_cairo_xlib_display_notify (surface->screen_info->display);
_cairo_xlib_display_notify (surface->display);
status = _get_image_surface (surface, NULL, &image, NULL);
if (status)
@ -1085,7 +1138,7 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
cairo_image_surface_t *image;
cairo_status_t status;
_cairo_xlib_display_notify (surface->screen_info->display);
_cairo_xlib_display_notify (surface->display);
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
if (status)
@ -1134,18 +1187,22 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_xlib_surface_t *surface = abstract_surface;
cairo_xlib_surface_t *clone;
cairo_status_t status;
_cairo_xlib_display_notify (surface->screen_info->display);
_cairo_xlib_display_notify (surface->display);
if (src->backend == surface->base.backend ) {
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
*clone_offset_x = 0;
*clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
@ -1156,25 +1213,30 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
if (! CAIRO_FORMAT_VALID (image_src->format))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (image_src->width > XLIB_COORD_MAX || image_src->height > XLIB_COORD_MAX)
return CAIRO_STATUS_NO_MEMORY;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar_with_format (surface, image_src->format,
image_src->width, image_src->height);
_cairo_xlib_surface_create_similar_with_format (surface,
image_src->format,
width, height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (clone->base.status)
return clone->base.status;
status = _draw_image_surface (clone, image_src, src_x, src_y,
width, height, src_x, src_y);
status = _draw_image_surface (clone, image_src,
src_x, src_y,
width, height,
0, 0);
if (status) {
cairo_surface_destroy (&clone->base);
return status;
}
*clone_offset_x = src_x;
*clone_offset_y = src_y;
*clone_out = &clone->base;
return CAIRO_STATUS_SUCCESS;
@ -1233,9 +1295,10 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac
status = surface->base.status;
if (status)
goto BAIL;
surface->owns_pixmap = TRUE;
status = _cairo_surface_paint (&image->base, CAIRO_OPERATOR_SOURCE, &solid_pattern->base);
status = _cairo_surface_paint (&image->base,
CAIRO_OPERATOR_SOURCE,
&solid_pattern->base);
if (status)
goto BAIL;
@ -1246,17 +1309,19 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac
if (status)
goto BAIL;
BAIL:
cairo_surface_destroy (&image->base);
if (status && surface) {
XFreePixmap (other->dpy, pixmap);
if (status) {
if (pixmap != None)
XFreePixmap (other->dpy, pixmap);
cairo_surface_destroy (&surface->base);
surface = NULL;
return _cairo_surface_create_in_error (status);
}
return (cairo_surface_t *) surface;
surface->owns_pixmap = TRUE;
return &surface->base;
}
static cairo_status_t
@ -1267,25 +1332,18 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
xtransform.matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
xtransform.matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
xtransform.matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
xtransform.matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
xtransform.matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
xtransform.matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
xtransform.matrix[2][0] = 0;
xtransform.matrix[2][1] = 0;
xtransform.matrix[2][2] = 1 << 16;
/* Casting between pixman_transform_t and XTransform is safe because
* they happen to be the exact same type.
*/
_cairo_matrix_to_pixman_matrix (matrix, (pixman_transform_t *)&xtransform);
if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0)
return CAIRO_STATUS_SUCCESS;
if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform);
surface->xtransform = xtransform;
@ -1379,10 +1437,10 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
_cairo_xlib_surface_set_repeat (surface, 0);
_cairo_xlib_surface_set_repeat (surface, RepeatNone);
break;
case CAIRO_EXTEND_REPEAT:
_cairo_xlib_surface_set_repeat (surface, 1);
_cairo_xlib_surface_set_repeat (surface, RepeatNormal);
break;
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
@ -1414,7 +1472,9 @@ _surfaces_compatible (cairo_xlib_surface_t *dst,
return FALSE;
/* if Render is supported, match picture formats */
if (src->xrender_format != NULL && src->xrender_format == dst->xrender_format)
if (src->xrender_format != dst->xrender_format)
return FALSE;
else if (src->xrender_format != NULL)
return TRUE;
/* Without Render, match visuals instead */
@ -1557,17 +1617,17 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL);
cairo_bool_t needs_alpha_composite;
if (!_cairo_surface_is_xlib (&src->base))
if (! _cairo_surface_is_xlib (&src->base))
return DO_UNSUPPORTED;
needs_alpha_composite =
_operator_needs_alpha_composite (op, _surface_has_alpha (src));
if (!have_mask &&
if (! have_mask &&
is_integer_translation &&
src_attr->extend == CAIRO_EXTEND_NONE &&
!needs_alpha_composite &&
_surfaces_compatible(src, dst))
! needs_alpha_composite &&
_surfaces_compatible (src, dst))
{
return DO_XCOPYAREA;
}
@ -1577,8 +1637,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
src_attr->extend == CAIRO_EXTEND_REPEAT &&
(src->width != 1 || src->height != 1))
{
if (!have_mask &&
!needs_alpha_composite &&
if (! have_mask &&
! needs_alpha_composite &&
_surfaces_compatible (dst, src))
{
return DO_XTILE;
@ -1587,10 +1647,10 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
return DO_UNSUPPORTED;
}
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
return DO_UNSUPPORTED;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return DO_UNSUPPORTED;
return DO_RENDER;
@ -1659,7 +1719,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
int itx, ity;
cairo_bool_t is_integer_translation;
_cairo_xlib_display_notify (dst->screen_info->display);
_cairo_xlib_display_notify (dst->display);
operation = _categorize_composite_operation (dst, op, src_pattern,
mask_pattern != NULL);
@ -1682,7 +1742,10 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
if (mask != NULL && !_cairo_surface_is_xlib (&mask->base)) {
if (mask != NULL &&
(! _cairo_surface_is_xlib (&mask->base) ||
! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)))
{
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@ -1737,12 +1800,18 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
status = _cairo_xlib_surface_ensure_gc (dst);
if (status)
goto BAIL;
is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix,
&itx, &ity);
/* This is a pre-condition for DO_XCOPYAREA. */
assert (is_integer_translation);
XCopyArea (dst->dpy,
src->drawable,
dst->drawable,
dst->gc,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
src_x + src_attr.x_offset + itx,
src_y + src_attr.y_offset + ity,
width, height,
dst_x, dst_y);
break;
@ -1803,7 +1872,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
cairo_rectangle_int_t *rects,
int num_rects)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
cairo_solid_pattern_t solid;
cairo_surface_t *solid_surface = NULL;
cairo_surface_attributes_t attrs;
@ -1815,7 +1884,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
if (status)
return status;
status = _cairo_pattern_acquire_surface (&solid.base, (cairo_surface_t *) surface,
status = _cairo_pattern_acquire_surface (&solid.base, &surface->base,
0, 0,
ARRAY_LENGTH (dither_pattern[0]),
ARRAY_LENGTH (dither_pattern),
@ -1824,7 +1893,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
if (status)
return status;
if (!_cairo_surface_is_xlib (solid_surface)) {
if (! _cairo_surface_is_xlib (solid_surface)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@ -1832,7 +1901,8 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
XSetTSOrigin (surface->dpy, surface->gc,
- (surface->base.device_transform.x0 + attrs.x_offset),
- (surface->base.device_transform.y0 + attrs.y_offset));
XSetTile (surface->dpy, surface->gc, ((cairo_xlib_surface_t *) solid_surface)->drawable);
XSetTile (surface->dpy, surface->gc,
((cairo_xlib_surface_t *) solid_surface)->drawable);
XSetFillStyle (surface->dpy, surface->gc, FillTiled);
for (i = 0; i < num_rects; i++) {
@ -1860,9 +1930,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
XRectangle *xrects = static_xrects;
int i;
_cairo_xlib_display_notify (surface->screen_info->display);
_cairo_xlib_display_notify (surface->display);
if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
if (op == CAIRO_OPERATOR_CLEAR ||
((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) &&
CAIRO_COLOR_IS_OPAQUE (color)))
@ -1918,10 +1988,17 @@ _create_a8_picture (cairo_xlib_surface_t *surface,
Pixmap pixmap;
Picture picture;
XRenderPictFormat *xrender_format;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return None;
xrender_format =
_cairo_xlib_display_get_xrender_format (surface->display,
CAIRO_FORMAT_A8);
if (xrender_format == NULL)
return None;
pixmap = XCreatePixmap (surface->dpy, surface->drawable,
width <= 0 ? 1 : width,
height <= 0 ? 1 : height,
@ -1933,8 +2010,7 @@ _create_a8_picture (cairo_xlib_surface_t *surface,
}
picture = XRenderCreatePicture (surface->dpy, pixmap,
XRenderFindStandardFormat (surface->dpy, PictStandardA8),
mask, &pa);
xrender_format, mask, &pa);
XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color,
0, 0, width, height);
XFreePixmap (surface->dpy, pixmap);
@ -1993,6 +2069,11 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst,
}
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
if (solid_picture == None) {
XRenderFreePicture (dst->dpy, mask_picture);
free (offset_traps);
return None;
}
XRenderCompositeTrapezoids (dst->dpy, PictOpAdd,
solid_picture, mask_picture,
@ -2029,7 +2110,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
int render_src_x, render_src_y;
XRenderPictFormat *pict_format;
_cairo_xlib_display_notify (dst->screen_info->display);
_cairo_xlib_display_notify (dst->display);
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -2045,7 +2126,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
if (status)
return status;
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
operation = _recategorize_composite_operation (dst, op, src,
&attributes, TRUE);
if (operation == DO_UNSUPPORTED) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
@ -2053,13 +2135,17 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
switch (antialias) {
case CAIRO_ANTIALIAS_NONE:
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1);
pict_format =
_cairo_xlib_display_get_xrender_format (dst->display,
CAIRO_FORMAT_A1);
break;
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8);
pict_format =
_cairo_xlib_display_get_xrender_format (dst->display,
CAIRO_FORMAT_A8);
break;
}
@ -2310,7 +2396,7 @@ _cairo_xlib_surface_is_similar (void *surface_a,
_xrender_format_to_content (xrender_format) != content)
{
xrender_format = _cairo_xlib_display_get_xrender_format (
b->screen_info->display,
b->display,
_cairo_format_from_content (content));
}
@ -2486,15 +2572,24 @@ _cairo_xlib_surface_create_internal (Display *dpy,
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
if (!xrender_format) {
if (visual)
if (visual) {
xrender_format = XRenderFindVisualFormat (dpy, visual);
else if (depth == 1)
xrender_format = XRenderFindStandardFormat (dpy, PictStandardA1);
} else if (depth == 1) {
xrender_format =
_cairo_xlib_display_get_xrender_format (display,
CAIRO_FORMAT_A1);
}
}
} else {
xrender_format = NULL;
}
/* we cannot use XRender for this surface, so ensure we don't try */
if (xrender_format == NULL) {
surface->render_major = -1;
surface->render_minor = -1;
}
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
_xrender_format_to_content (xrender_format));
@ -2787,7 +2882,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
if (surface->drawable != drawable) {
if (surface->dst_picture != None) {
status = _cairo_xlib_display_queue_resource (
surface->screen_info->display,
surface->display,
XRenderFreePicture,
surface->dst_picture);
if (status) {
@ -2800,7 +2895,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
if (surface->src_picture != None) {
status = _cairo_xlib_display_queue_resource (
surface->screen_info->display,
surface->display,
XRenderFreePicture,
surface->src_picture);
if (status) {
@ -3019,7 +3114,7 @@ _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display,
scaled_font = font_private->scaled_font;
CAIRO_MUTEX_LOCK (scaled_font->mutex);
font_private = scaled_font->surface_private;
font_private = scaled_font->surface_private;
scaled_font->surface_private = NULL;
_cairo_scaled_font_reset_cache (scaled_font);
@ -3331,7 +3426,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
pscaled_glyph);
if (status != CAIRO_STATUS_SUCCESS)
if (status)
return status;
scaled_glyph = *pscaled_glyph;
@ -3369,7 +3464,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
cairo_surface_t *tmp_surface;
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
if (tmp_surface->status)
status = tmp_surface->status;
if (status)
goto BAIL;
cr = cairo_create (tmp_surface);
@ -3398,7 +3494,8 @@ _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)
status = tmp_surface->status;
if (status)
goto BAIL;
tmp_surface->device_transform = glyph_surface->base.device_transform;
@ -3544,18 +3641,29 @@ typedef union {
/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t));
/* Start a new element for the first glyph,
* or for any glyph that has unexpected position,
* or if current element has too many glyphs
* (Xrender limits each element to 252 glyphs, we limit them to 128)
*
* These same conditions need to be mirrored between
* _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks
*/
#define _start_new_glyph_elt(count, glyph) \
(((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
static cairo_status_t
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
cairo_xlib_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_surface_attributes_t *attributes,
/* info for this chunk */
int num_elts,
int width,
cairo_xlib_font_glyphset_info_t *glyphset_info)
_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
cairo_xlib_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_surface_attributes_t *attributes,
/* info for this chunk */
int num_elts,
int width,
cairo_xlib_font_glyphset_info_t *glyphset_info)
{
/* Which XRenderCompositeText function to use */
cairo_xrender_composite_text_func_t composite_text_func;
@ -3606,9 +3714,13 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
j = 0;
for (i = 0; i < num_glyphs; i++) {
/* Start a new element for first output glyph, and for glyphs with
* unexpected position */
if (!j || glyphs[i].i.x || glyphs[i].i.y) {
/* Start a new element for first output glyph,
* or for any glyph that has unexpected position,
* or if current element has too many glyphs.
*
* These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs()
*/
if (_start_new_glyph_elt (j, &glyphs[i])) {
if (j) {
elts[nelt].nchars = n;
nelt++;
@ -3637,6 +3749,10 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
n = 0;
}
/* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the
* expected number of xGlyphElts. */
assert (nelt == num_elts);
composite_text_func (dst->dpy,
_render_operator (op),
src->src_picture,
@ -3653,6 +3769,11 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
return CAIRO_STATUS_SUCCESS;
}
/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
* enough room for padding */
#define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
static cairo_status_t
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
cairo_xlib_glyph_t *glyphs,
@ -3681,7 +3802,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
int request_size = 0;
_cairo_xlib_surface_ensure_dst_picture (dst);
_cairo_xlib_display_notify (dst->screen_info->display);
_cairo_xlib_display_notify (dst->display);
for (i = 0; i < num_glyphs; i++) {
int this_x, this_y;
@ -3738,6 +3859,10 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
if (!glyphset_info)
glyphset_info = this_glyphset_info;
/* The invariant here is that we can always flush the glyphs
* accumulated before this one, using old_width, and they
* would fit in the request.
*/
old_width = width;
/* Update max glyph index */
@ -3762,11 +3887,11 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
* to the mask first, and then composes that to final surface,
* though it's not a big deal.
*/
if (request_size + width > max_request_size - sz_xGlyphElt ||
if (request_size + width > max_request_size - _cairo_sz_xGlyphElt ||
(this_glyphset_info != glyphset_info)) {
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
scaled_font, op, src, attributes,
num_elts, old_width, glyphset_info);
status = _emit_glyphs_chunk (dst, glyphs, i,
scaled_font, op, src, attributes,
num_elts, old_width, glyphset_info);
if (status != CAIRO_STATUS_SUCCESS)
return status;
@ -3787,11 +3912,15 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
glyphs[i].i.x = this_x - x;
glyphs[i].i.y = this_y - y;
/* Start a new element for the first glyph, or for any glyph that
* has unexpected position */
if (!num_out_glyphs || glyphs[i].i.x || glyphs[i].i.y) {
/* Start a new element for the first glyph,
* or for any glyph that has unexpected position,
* or if current element has too many glyphs.
*
* These same conditions are mirrored in _emit_glyphs_chunk().
*/
if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) {
num_elts++;
request_size += sz_xGlyphElt;
request_size += _cairo_sz_xGlyphElt;
}
/* adjust current-position */
@ -3803,9 +3932,9 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
}
if (num_elts)
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
scaled_font, op, src, attributes,
num_elts, width, glyphset_info);
status = _emit_glyphs_chunk (dst, glyphs, i,
scaled_font, op, src, attributes,
num_elts, width, glyphset_info);
*remaining_glyphs = num_glyphs - i;
if (*remaining_glyphs && status == CAIRO_STATUS_SUCCESS)
@ -3814,6 +3943,23 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
return status;
}
static cairo_bool_t
_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst,
cairo_scaled_font_t *scaled_font)
{
cairo_xlib_surface_font_private_t *font_private;
font_private = scaled_font->surface_private;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
(font_private != NULL && font_private->display != dst->display))
{
return FALSE;
}
return TRUE;
}
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
@ -3830,11 +3976,9 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xlib_surface_t *src = NULL;
cairo_xlib_surface_font_private_t *font_private;
cairo_solid_pattern_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Just let unbounded operators go through the fallback code
@ -3865,22 +4009,14 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
font_private = scaled_font->surface_private;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
(font_private != NULL && font_private->display != dst->screen_info->display))
if (! _cairo_xlib_surface_owns_font (dst, scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
* them. We tie into the scaled_font's glyph cache and remove
* glyphs from the X server when they are ejected from the
* scaled_font cache. Because of this we first freeze the
* scaled_font's cache so that we don't cause any of our glyphs to
* be ejected and removed from the X server before we have a
* chance to render them. */
_cairo_scaled_font_freeze_cache (scaled_font);
* them.
*/
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
* the mask (the glyphs). This code below was executed as a side effect
@ -3920,7 +4056,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
goto BAIL0;
}
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
operation = _recategorize_composite_operation (dst, op, src,
&attributes, TRUE);
if (operation == DO_UNSUPPORTED) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL1;
@ -3930,14 +4067,19 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (status)
goto BAIL1;
status = _cairo_xlib_surface_emit_glyphs (dst,
(cairo_xlib_glyph_t *) glyphs,
num_glyphs,
scaled_font,
op,
src,
&attributes,
remaining_glyphs);
_cairo_scaled_font_freeze_cache (scaled_font);
if (_cairo_xlib_surface_owns_font (dst, scaled_font)) {
status = _cairo_xlib_surface_emit_glyphs (dst,
(cairo_xlib_glyph_t *) glyphs,
num_glyphs,
scaled_font,
op,
src,
&attributes,
remaining_glyphs);
} else
status = CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_scaled_font_thaw_cache (scaled_font);
BAIL1:
if (src)
@ -3945,8 +4087,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (src_pattern == &solid_pattern.base)
_cairo_pattern_fini (&solid_pattern.base);
BAIL0:
_cairo_scaled_font_thaw_cache (scaled_font);
_cairo_xlib_display_notify (dst->screen_info->display);
_cairo_xlib_display_notify (dst->display);
return status;
}

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

@ -42,7 +42,7 @@
#include "cairo-arc-private.h"
#include "cairo-path-private.h"
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
static const cairo_t _cairo_nil = {
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
@ -84,8 +84,7 @@ static const cairo_t _cairo_nil = {
cairo_status_t
_cairo_error (cairo_status_t status)
{
assert (status > CAIRO_STATUS_SUCCESS &&
status <= CAIRO_STATUS_LAST_STATUS);
assert (_cairo_status_is_error (status));
return status;
}
@ -288,7 +287,7 @@ cairo_set_user_data (cairo_t *cr,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return cr->status;
return _cairo_user_data_array_set_data (&cr->user_data,
key, user_data, destroy);
@ -926,6 +925,7 @@ cairo_set_line_width (cairo_t *cr, double width)
if (status)
_cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_line_width);
/**
* cairo_set_line_cap:
@ -955,6 +955,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
if (status)
_cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_line_cap);
/**
* cairo_set_line_join:
@ -984,6 +985,7 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
if (status)
_cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_line_join);
/**
* cairo_set_dash:
@ -2087,6 +2089,7 @@ cairo_stroke (cairo_t *cr)
cairo_new_path (cr);
}
slim_hidden_def(cairo_stroke);
/**
* cairo_stroke_preserve:
@ -3077,8 +3080,9 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cairo_glyph_t *glyphs = NULL, *last_glyph;
cairo_text_cluster_t *clusters = NULL;
int utf8_len, num_glyphs, num_clusters;
cairo_bool_t backward;
cairo_text_cluster_flags_t cluster_flags;
double x, y;
cairo_bool_t has_show_text_glyphs;
if (cr->status)
return;
@ -3090,12 +3094,15 @@ cairo_show_text (cairo_t *cr, const char *utf8)
utf8_len = strlen (utf8);
has_show_text_glyphs =
cairo_surface_has_show_text_glyphs (cairo_get_target (cr));
status = _cairo_gstate_text_to_glyphs (cr->gstate,
x, y,
utf8, utf8_len,
&glyphs, &num_glyphs,
cairo_has_show_text_glyphs (cr) ? &clusters : NULL, &num_clusters,
&backward);
has_show_text_glyphs ? &clusters : NULL, &num_clusters,
&cluster_flags);
if (status)
goto BAIL;
@ -3106,7 +3113,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
cluster_flags);
if (status)
goto BAIL;
@ -3169,36 +3176,6 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
_cairo_set_error (cr, status);
}
/**
* cairo_has_show_text_glyphs:
* @cr: a cairo context
*
* Returns whether the target surface of a cairo context supports
* sophisticated cairo_show_text_glyphs() operations. That is,
* whether it actually uses the provided text and cluster data
* to a cairo_show_text_glyphs() call.
*
* Note: Even if this function returns %FALSE, a
* cairo_show_text_glyphs() operation will still succeed. It just will
* act like a cairo_show_glyphs() operation. Users can use this
* function to avoid computing UTF-8 text and cluster mapping if the
* target surface does not use it.
*
* This is a convenience function that simply calls
* cairo_surface_has_show_text_glyphs() on @cr's target.
*
* Return value: %TRUE if the target surface of @cr supports
* cairo_show_text_glyphs(), %FALSE otherwise
*
* Since: 1.8
**/
cairo_bool_t
cairo_has_show_text_glyphs (cairo_t *cr)
{
return _cairo_gstate_has_show_text_glyphs (cr->gstate);
}
slim_hidden_def (cairo_has_show_text_glyphs);
/**
* cairo_show_text_glyphs:
* @cr: a cairo context
@ -3208,14 +3185,14 @@ slim_hidden_def (cairo_has_show_text_glyphs);
* @num_glyphs: number of glyphs to show
* @clusters: array of cluster mapping information
* @num_clusters: number of clusters in the mapping
* @backward: whether the text to glyphs mapping goes backward
* @cluster_flags: cluster mapping flags
*
* This operation has rendering effects similar to cairo_show_glyphs()
* but, if the target surface supports it, uses the provided text and
* cluster mapping to embed the text for the glyphs shown in the output.
* The cairo_has_show_text_glyphs() function can be used to query that.
* If the target does not support it, this function acts like
* cairo_show_glyphs().
* If the target does not support the extended attributes, this function
* acts like the basic cairo_show_glyphs() as if it had been passed
* @glyphs and @num_glyphs.
*
* The mapping between @utf8 and @glyphs is provided by an array of
* <firstterm>clusters</firstterm>. Each cluster covers a number of
@ -3224,7 +3201,8 @@ slim_hidden_def (cairo_has_show_text_glyphs);
* and @glyphs in entirety.
*
* The first cluster always covers bytes from the beginning of @utf8.
* If @backward is %FALSE, the first cluster also covers the beginning
* If @cluster_flags do not have the %CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
* set, the first cluster also covers the beginning
* of @glyphs, otherwise it covers the end of the @glyphs array and
* following clusters move backward.
*
@ -3240,7 +3218,7 @@ cairo_show_text_glyphs (cairo_t *cr,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward)
cairo_text_cluster_flags_t cluster_flags)
{
cairo_status_t status;
@ -3275,8 +3253,7 @@ cairo_show_text_glyphs (cairo_t *cr,
* and that cluster boundaries are UTF-8 boundaries. */
status = _cairo_validate_text_clusters (utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
clusters, num_clusters, cluster_flags);
if (status == CAIRO_STATUS_INVALID_CLUSTERS) {
/* Either got invalid UTF-8 text, or cluster mapping is bad.
* Differentiate those. */
@ -3297,8 +3274,7 @@ cairo_show_text_glyphs (cairo_t *cr,
status = _cairo_gstate_show_text_glyphs (cr->gstate,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
!!backward);
clusters, num_clusters, cluster_flags);
if (status)
_cairo_set_error (cr, status);
}
@ -3585,6 +3561,7 @@ cairo_get_line_width (cairo_t *cr)
return _cairo_gstate_get_line_width (cr->gstate);
}
slim_hidden_def (cairo_get_line_width);
/**
* cairo_get_line_cap:

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

@ -51,7 +51,11 @@
#endif
#ifndef cairo_public
# define cairo_public
# if defined (_MSC_VER) && ! defined (CAIRO_WIN32_STATIC_BUILD)
# define cairo_public __declspec(dllimport)
# else
# define cairo_public
# endif
#endif
CAIRO_BEGIN_DECLS
@ -892,6 +896,19 @@ cairo_text_cluster_allocate (int num_clusters);
cairo_public void
cairo_text_cluster_free (cairo_text_cluster_t *clusters);
/**
* cairo_text_cluster_flags_t:
* @CAIRO_TEXT_CLUSTER_FLAG_BACKWARD: The clusters in the cluster array
* map to glyphs in the glyph array from end to start.
*
* Specifies properties of a text cluster mapping.
*
* Since: 1.8
**/
typedef enum _cairo_text_cluster_flags {
CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001
} cairo_text_cluster_flags_t;
/**
* cairo_text_extents_t:
* @x_bearing: the horizontal distance from the origin to the
@ -1028,28 +1045,6 @@ typedef enum _cairo_subpixel_order {
CAIRO_SUBPIXEL_ORDER_VBGR
} cairo_subpixel_order_t;
/**
* cairo_lcd_filter_t:
* @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for
* font backend and target device
* @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
* @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter
* @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel
* @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel
*
* The LCD filter specifies the low-pass filter applied to LCD-optimized
* bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
*
* Since: 1.8
**/
typedef enum _cairo_lcd_filter {
CAIRO_LCD_FILTER_DEFAULT,
CAIRO_LCD_FILTER_NONE,
CAIRO_LCD_FILTER_INTRA_PIXEL,
CAIRO_LCD_FILTER_FIR3,
CAIRO_LCD_FILTER_FIR5
} cairo_lcd_filter_t;
/**
* cairo_hint_style_t:
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
@ -1155,12 +1150,6 @@ cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
cairo_public cairo_subpixel_order_t
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
cairo_public void
cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
cairo_lcd_filter_t lcd_filter);
cairo_public cairo_lcd_filter_t
cairo_font_options_get_lcd_filter (const cairo_font_options_t *options);
cairo_public void
cairo_font_options_set_hint_style (cairo_font_options_t *options,
cairo_hint_style_t hint_style);
@ -1220,9 +1209,6 @@ cairo_show_text (cairo_t *cr, const char *utf8);
cairo_public void
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
cairo_public cairo_bool_t
cairo_has_show_text_glyphs (cairo_t *cr);
cairo_public void
cairo_show_text_glyphs (cairo_t *cr,
const char *utf8,
@ -1231,7 +1217,7 @@ cairo_show_text_glyphs (cairo_t *cr,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward);
cairo_text_cluster_flags_t cluster_flags);
cairo_public void
cairo_text_path (cairo_t *cr, const char *utf8);
@ -1376,16 +1362,16 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
cairo_text_extents_t *extents);
cairo_public cairo_status_t
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags);
cairo_public cairo_font_face_t *
cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font);
@ -1525,7 +1511,8 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* @num_glyphs: pointer to number of glyphs
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
* @num_clusters: pointer to number of clusters
* @backward: pointer to whether the text to glyphs mapping goes backward
* @cluster_flags: pointer to location to store cluster flags corresponding to the
* output @clusters
*
* #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which
* is called to convert input text to an array of glyphs. This is used by the
@ -1536,35 +1523,30 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* as well as complex <firstterm>shaping</firstterm> required for scripts like
* Arabic and Indic.
*
* The @num_glyphs argument is preset to -1. The callback should allocate an
* array for the resulting glyphs (using malloc()), and populate the glyph indices and
* positions (in font space) assuming that the text is to be shown at the
* origin. Cairo will free the glyph array when done with it, no matter what
* the return value of the callback is.
*
* If @glyphs initially points to a non-%NULL value, that array can be used
* as a glyph buffer, and @num_glyphs points to the number of glyph
* entries available there. If the provided glyph array is too short for
* The @num_glyphs argument is preset to the number of glyph entries available
* in the @glyphs buffer. If the @glyphs buffer is %NULL, the value of
* @num_glyphs will be zero. If the provided glyph array is too short for
* the conversion (or for convenience), a new glyph array may be allocated
* using cairo_glyph_allocate() and placed in @glyphs. Upon return,
* @num_glyphs should contain the number of generated glyphs.
* If the value @glyphs points at has changed after the call, cairo will
* free the allocated glyph array using cairo_glyph_free().
* @num_glyphs should contain the number of generated glyphs. If the value
* @glyphs points at has changed after the call, the caller will free the
* allocated glyph array using cairo_glyph_free().
* The callback should populate the glyph indices and positions (in font space)
* assuming that the text is to be shown at the origin.
*
* If @clusters is not %NULL, @num_clusters and @backward are also non-%NULL,
* and cluster mapping should be computed.
* The semantics of how cluster array allocation works is similar to the glyph
* array. That is,
* If @clusters is not %NULL, @num_clusters and @cluster_flags are also
* non-%NULL, and cluster mapping should be computed. The semantics of how
* cluster array allocation works is similar to the glyph array. That is,
* if @clusters initially points to a non-%NULL value, that array may be used
* as a cluster buffer, and @num_clusters points to the number of cluster
* entries available there. If the provided cluster array is too short for
* the conversion (or for convenience), a new cluster array may be allocated
* using cairo_text_cluster_allocate() and placed in @clusters. Upon return,
* @num_clusters should contain the number of generated clusters.
* If the value @clusters points at has changed after the call, cairo will
* free the allocated cluster array using cairo_text_cluster_free().
* If the value @clusters points at has changed after the call, the caller
* will free the allocated cluster array using cairo_text_cluster_free().
*
* The callback is optional. If not set, or if @num_glyphs is negative upon
* The callback is optional. If @num_glyphs is negative upon
* the callback returning, the unicode_to_glyph callback
* is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t.
*
@ -1581,14 +1563,14 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
*
* Since: 1.8
**/
typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags);
/**
* cairo_user_scaled_font_unicode_to_glyph_func_t:
@ -1931,8 +1913,7 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_SVG,
CAIRO_SURFACE_TYPE_OS2,
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
CAIRO_SURFACE_TYPE_QPAINTER
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE
} cairo_surface_type_t;
cairo_public cairo_surface_type_t

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

@ -50,12 +50,9 @@
#include "config.h"
#endif
/* We use our own macros */
#undef PACKAGE
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#ifdef _MSC_VER
#define cairo_public __declspec(dllexport)
#endif
#include <assert.h>
#include <stdlib.h>
@ -75,11 +72,14 @@
#include "cairo-compiler-private.h"
#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_SVG_SURFACE)
#if CAIRO_HAS_PS_SURFACE || \
CAIRO_HAS_PDF_SURFACE || \
CAIRO_HAS_SVG_SURFACE || \
CAIRO_HAS_WIN32_SURFACE
#define CAIRO_HAS_FONT_SUBSET 1
#endif
#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE)
#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE
#define CAIRO_HAS_PDF_OPERATORS 1
#endif
@ -132,7 +132,7 @@ _cairo_win32_tmpfile (void);
* a bit of a pain, but it should be easy to always catch as long as
* one adds a new test case to test a trigger of the new status value.
*/
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_SLANT
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_WEIGHT
#ifdef __GNUC__
#define cairo_container_of(ptr, type, member) ({ \
@ -418,6 +418,10 @@ typedef struct _cairo_scaled_font_subset {
struct _cairo_scaled_font_backend {
cairo_font_type_t type;
cairo_warn cairo_status_t
(*get_implementation) (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face);
cairo_warn cairo_status_t
(*create_toy) (cairo_toy_font_face_t *toy_face,
const cairo_matrix_t *font_matrix,
@ -438,16 +442,16 @@ struct _cairo_scaled_font_backend {
* then just converting characters one by one.
*/
cairo_warn cairo_int_status_t
(*text_to_glyphs) (void *scaled_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
(*text_to_glyphs) (void *scaled_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags);
unsigned long
(*ucs4_to_index) (void *scaled_font,
@ -490,6 +494,10 @@ struct _cairo_font_face_backend {
void
(*destroy) (void *font_face);
cairo_warn cairo_status_t
(*get_implementation) (void *font_face,
cairo_font_face_t **font_face_out);
cairo_warn cairo_status_t
(*scaled_font_create) (void *font_face,
const cairo_matrix_t *font_matrix,
@ -498,6 +506,8 @@ struct _cairo_font_face_backend {
cairo_scaled_font_t **scaled_font);
};
extern const cairo_private struct _cairo_scaled_font_backend _cairo_user_scaled_font_backend;
/* concrete font backends */
#if CAIRO_HAS_FT_FONT
@ -559,9 +569,12 @@ struct _cairo_surface_backend {
* 1. It is as compatible as possible with @surface (in terms of
* efficiency)
*
* 2. It has the same size as @src
* 2. It has the same contents as @src within the given rectangle.
*
* 3. It has the same contents as @src within the given rectangle.
* 3. The offset of the similar surface with respect to the original
* surface is returned in the clone_offset vector.
* - if you clone the entire surface, this vector is zero.
* - if you clone (src_x, src_y)x(w, h) the vector is (src_x, src_y);
*/
cairo_warn cairo_status_t
(*clone_similar) (void *surface,
@ -570,6 +583,8 @@ struct _cairo_surface_backend {
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out);
/* XXX: dst should be the first argument for consistency */
@ -799,7 +814,7 @@ struct _cairo_surface_backend {
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font);
};
@ -825,24 +840,6 @@ struct _cairo_image_surface {
extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend;
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this
madness). I'm still working on a cleaner API, but in the meantime,
at least this does prevent precision loss in color when changing
alpha. */
struct _cairo_color {
double red;
double green;
double blue;
double alpha;
unsigned short red_short;
unsigned short green_short;
unsigned short blue_short;
unsigned short alpha_short;
};
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD
@ -966,8 +963,8 @@ typedef struct _cairo_traps {
#else
/* Paranoia: this should have been caught by configure. */
#error No font backends are available.
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_user_scaled_font_backend
#endif
@ -1249,16 +1246,16 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face);
cairo_private cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_text_cluster_flags_t *cluster_flags);
cairo_private cairo_status_t
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
@ -1266,9 +1263,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_private cairo_bool_t
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
const char *utf8,
@ -1277,7 +1271,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward);
cairo_text_cluster_flags_t cluster_flags);
cairo_private cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
@ -1358,6 +1352,17 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
cairo_private void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
/* cairo-font-face-twin.c */
cairo_private cairo_font_face_t *
_cairo_font_face_twin_create (cairo_font_slant_t slant,
cairo_font_weight_t weight);
/* cairo-font-face-twin-data.c */
extern const cairo_private int8_t _cairo_twin_outlines[];
extern const cairo_private uint16_t _cairo_twin_charmap[128];
/* cairo-font-options.c */
cairo_private void
@ -1383,7 +1388,7 @@ _cairo_validate_text_clusters (const char *utf8,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward);
cairo_text_cluster_flags_t cluster_flags);
/* cairo-path-fixed.c */
cairo_private void
@ -1547,7 +1552,7 @@ _cairo_scaled_font_create_in_error (cairo_status_t status);
cairo_private void
_cairo_scaled_font_reset_static_data (void);
cairo_private void
cairo_private cairo_status_t
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font);
cairo_private void
@ -1565,6 +1570,7 @@ cairo_private cairo_status_t
_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *fs_metrics);
/* This should only be called on an error path by a scaled_font constructor */
cairo_private void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
@ -1788,7 +1794,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font);
cairo_private cairo_status_t
@ -1836,6 +1842,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out);
cairo_private cairo_surface_t *
@ -1997,7 +2005,7 @@ 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 cairo_int_status_t
cairo_private cairo_bool_t
_pixman_format_from_masks (cairo_format_masks_t *masks,
pixman_format_code_t *format_ret);
@ -2109,21 +2117,19 @@ _cairo_polygon_init (cairo_polygon_t *polygon);
cairo_private void
_cairo_polygon_fini (cairo_polygon_t *polygon);
cairo_private cairo_status_t
_cairo_polygon_status (cairo_polygon_t *polygon);
cairo_private void
_cairo_polygon_move_to (cairo_polygon_t *polygon,
const cairo_point_t *point);
cairo_private void
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2);
cairo_private void
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point);
cairo_private void
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point);
_cairo_polygon_line_to (cairo_polygon_t *polygon,
const cairo_point_t *point);
cairo_private void
_cairo_polygon_close (cairo_polygon_t *polygon);
#define _cairo_polygon_status(P) (P)->status
/* cairo-spline.c */
cairo_private cairo_int_status_t
_cairo_spline_init (cairo_spline_t *spline,
@ -2176,6 +2182,9 @@ cairo_private cairo_bool_t
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
int *itx, int *ity);
cairo_private cairo_bool_t
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix);
cairo_private double
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
@ -2195,29 +2204,38 @@ cairo_private cairo_bool_t
_cairo_traps_get_limit (cairo_traps_t *traps,
cairo_box_t *limits);
cairo_private cairo_status_t
cairo_private void
_cairo_traps_init_box (cairo_traps_t *traps,
cairo_box_t *box);
const cairo_box_t *box);
cairo_private void
_cairo_traps_clear (cairo_traps_t *traps);
cairo_private void
_cairo_traps_fini (cairo_traps_t *traps);
cairo_private cairo_status_t
_cairo_traps_status (cairo_traps_t *traps);
#define _cairo_traps_status(T) (T)->status
cairo_private void
_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
cairo_private cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
const cairo_point_t t[3]);
cairo_private cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
const cairo_point_t q[4]);
cairo_private cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
const cairo_point_t *top_left,
const cairo_point_t *bottom_right);
cairo_private void
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2);
_cairo_traps_add_trap (cairo_traps_t *traps,
cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
cairo_private cairo_status_t
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
@ -2249,10 +2267,12 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
/* cairo-slope.c */
cairo_private void
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
_cairo_slope_init (cairo_slope_t *slope,
const cairo_point_t *a,
const cairo_point_t *b);
cairo_private int
_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b);
_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b);
/* cairo-pattern.c */
@ -2264,6 +2284,10 @@ cairo_private cairo_status_t
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other);
cairo_private cairo_status_t
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other);
cairo_private void
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
const cairo_color_t *color,
@ -2363,7 +2387,7 @@ cairo_private int
_cairo_ucs4_to_utf8 (uint32_t unicode,
char *utf8);
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0 || CAIRO_HAS_PDF_SURFACE+0
#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
#if CAIRO_HAS_UTF8_TO_UTF16
@ -2374,6 +2398,9 @@ _cairo_utf8_to_utf16 (const char *str,
int *items_written);
#endif
#define _cairo_status_is_error(status) \
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
cairo_private cairo_status_t
_cairo_error (cairo_status_t status);
@ -2391,21 +2418,22 @@ slim_hidden_proto (cairo_curve_to);
slim_hidden_proto (cairo_destroy);
slim_hidden_proto (cairo_fill_preserve);
slim_hidden_proto (cairo_font_face_destroy);
slim_hidden_proto (cairo_font_face_get_user_data);
slim_hidden_proto_no_warn (cairo_font_face_reference);
slim_hidden_proto (cairo_font_face_set_user_data);
slim_hidden_proto (cairo_font_options_equal);
slim_hidden_proto (cairo_font_options_hash);
slim_hidden_proto (cairo_font_options_merge);
slim_hidden_proto (cairo_font_options_set_antialias);
slim_hidden_proto (cairo_font_options_set_hint_metrics);
slim_hidden_proto (cairo_font_options_set_hint_style);
slim_hidden_proto (cairo_font_options_set_lcd_filter);
slim_hidden_proto (cairo_font_options_set_subpixel_order);
slim_hidden_proto (cairo_font_options_status);
slim_hidden_proto (cairo_get_current_point);
slim_hidden_proto (cairo_get_line_width);
slim_hidden_proto (cairo_get_matrix);
slim_hidden_proto (cairo_get_target);
slim_hidden_proto (cairo_get_tolerance);
slim_hidden_proto (cairo_has_show_text_glyphs);
slim_hidden_proto (cairo_glyph_allocate);
slim_hidden_proto (cairo_glyph_free);
slim_hidden_proto (cairo_image_surface_create);
@ -2462,12 +2490,16 @@ slim_hidden_proto_no_warn (cairo_scaled_font_reference);
slim_hidden_proto (cairo_scaled_font_status);
slim_hidden_proto (cairo_set_font_size);
slim_hidden_proto (cairo_set_font_options);
slim_hidden_proto (cairo_set_line_cap);
slim_hidden_proto (cairo_set_line_join);
slim_hidden_proto (cairo_set_line_width);
slim_hidden_proto (cairo_set_matrix);
slim_hidden_proto (cairo_set_operator);
slim_hidden_proto (cairo_set_source);
slim_hidden_proto (cairo_set_source);
slim_hidden_proto (cairo_set_source_surface);
slim_hidden_proto (cairo_status);
slim_hidden_proto (cairo_stroke);
slim_hidden_proto (cairo_stroke_preserve);
slim_hidden_proto (cairo_surface_create_similar);
slim_hidden_proto (cairo_surface_destroy);
@ -2488,6 +2520,12 @@ slim_hidden_proto (cairo_surface_status);
slim_hidden_proto (cairo_text_cluster_allocate);
slim_hidden_proto (cairo_text_cluster_free);
slim_hidden_proto (cairo_toy_font_face_create);
slim_hidden_proto (cairo_toy_font_face_get_slant);
slim_hidden_proto (cairo_toy_font_face_get_weight);
slim_hidden_proto (cairo_user_font_face_create);
slim_hidden_proto (cairo_user_font_face_set_init_func);
slim_hidden_proto (cairo_user_font_face_set_render_glyph_func);
slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func);
slim_hidden_proto (cairo_version_string);
#if CAIRO_HAS_PNG_FUNCTIONS

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

@ -176,11 +176,15 @@ _test_fallback_surface_clone_similar (void *abstract_surface,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
test_fallback_surface_t *surface = abstract_surface;
if (src->backend == surface->base.backend) {
*clone_offset_x = 0;
*clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;

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

@ -273,34 +273,18 @@ _test_meta_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
test_meta_surface_t *surface = abstract_surface;
cairo_int_status_t status;
surface->image_reflects_meta = FALSE;
/* Since this is a "wrapping" surface, we're calling back into
* _cairo_surface_show_text_glyphs from within a call to the same.
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
* and re-acquire the mutex around this nested call.
*
* Yes, this is ugly, but we consider it pragmatic as compared to
* adding locking code to all 18 surface-backend-specific
* show_glyphs functions, (which would get less testing and likely
* lead to bugs).
*/
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
return status;
return _cairo_surface_show_text_glyphs (surface->meta, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags,
scaled_font);
}
@ -308,43 +292,8 @@ static cairo_surface_t *
_test_meta_surface_snapshot (void *abstract_other)
{
test_meta_surface_t *other = abstract_other;
cairo_status_t status;
/* XXX: Just making a snapshot of other->meta is what we really
* want. But this currently triggers a bug somewhere (the "mask"
* test from the test suite segfaults).
*
* For now, we'll create a new image surface and replay onto
* that. It would be tempting to replay into other->image and then
* return a snapshot of that, but that will cause the self-copy
* test to fail, (since our replay will be affected by a clip that
* should not have any effect on the use of the resulting snapshot
* as a source).
*/
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_int_t extents;
cairo_surface_t *surface;
status = _cairo_surface_get_extents (other->image, &extents);
if (status)
return _cairo_surface_create_in_error (status);
surface = cairo_surface_create_similar (other->image,
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
status = _cairo_meta_surface_replay (other->meta, surface);
if (status) {
cairo_surface_destroy (surface);
surface = _cairo_surface_create_in_error (status);
}
return surface;
#endif
}
static const cairo_surface_backend_t test_meta_surface_backend = {

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

@ -93,14 +93,16 @@ _cairo_test_paginated_surface_create_for_data (unsigned char *data,
paginated = _cairo_paginated_surface_create (&surface->base,
content, width, height,
&test_paginated_surface_paginated_backend);
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
if (paginated->status) {
cairo_surface_destroy (target);
status = paginated->status;
if (status == CAIRO_STATUS_SUCCESS) {
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
return paginated;
}
return paginated;
cairo_surface_destroy (target);
free (surface);
return _cairo_surface_create_in_error (status);
}
static cairo_status_t
@ -250,35 +252,19 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font)
{
test_paginated_surface_t *surface = abstract_surface;
cairo_int_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
/* Since this is a "wrapping" surface, we're calling back into
* _cairo_surface_show_text_glyphs from within a call to the same.
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
* and re-acquire the mutex around this nested call.
*
* Yes, this is ugly, but we consider it pragmatic as compared to
* adding locking code to all 18 surface-backend-specific
* show_glyphs functions, (which would get less testing and likely
* lead to bugs).
*/
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
status = _cairo_surface_show_text_glyphs (surface->target, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
return status;
return _cairo_surface_show_text_glyphs (surface->target, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags,
scaled_font);
}

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

@ -1,6 +1,6 @@
diff -r b79d47dad1ea gfx/cairo/cairo/src/cairoint.h
--- a/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700
+++ b/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200
--- a/gfx/cairo/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700
+++ b/gfx/cairo/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200
@@ -159,6 +159,13 @@ CAIRO_BEGIN_DECLS
#ifndef M_PI