Backed out changeset 3d7b55f16ec5

This commit is contained in:
Jeff Muizelaar 2009-09-09 14:30:44 -04:00
parent b051e5a8e1
commit c9f45bc3f1
64 changed files with 1579 additions and 3135 deletions

View File

@ -874,7 +874,6 @@ _return_success (void)
typedef cairo_int_status_t
(*_set_clip_region_func) (void *surface,
cairo_region_t *region);
typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,

View File

@ -352,6 +352,14 @@ _cairo_array_size (cairo_array_t *array)
return array->size;
}
/* #cairo_user_data_array_t */
typedef struct {
const cairo_user_data_key_t *key;
void *user_data;
cairo_destroy_func_t destroy;
} cairo_user_data_slot_t;
/**
* _cairo_user_data_array_init:
* @array: a #cairo_user_data_array_t

View File

@ -55,19 +55,6 @@ 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)
#if SIZEOF_VOID_P==SIZEOF_INT
typedef int cairo_atomic_intptr_t;
#elif SIZEOF_VOID_P==SIZEOF_LONG
typedef long cairo_atomic_intptr_t;
#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
typedef long long cairo_atomic_intptr_t;
#else
#error No matching integer pointer type
#endif
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
(void*)__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
#endif
@ -84,9 +71,6 @@ _cairo_atomic_int_dec_and_test (int *x);
cairo_private int
_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
cairo_private void *
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
#endif
@ -107,9 +91,6 @@ _cairo_atomic_int_set (int *x, int value);
#endif
#define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
#define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \
_cairo_atomic_int_cmpxchg((int *)x, oldv, newv)
#define _cairo_status_set_error(status, err) do { \
/* hide compiler warnings about cairo_status_t != int (gcc treats its as \

View File

@ -36,11 +36,7 @@
#include "cairo-atomic-private.h"
#include "cairo-mutex-private.h"
#ifdef HAS_ATOMIC_OPS
COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) ||
sizeof(void*) == sizeof(long) ||
sizeof(void*) == sizeof(long long));
#else
#ifndef HAS_ATOMIC_OPS
void
_cairo_atomic_int_inc (int *x)
{
@ -75,19 +71,6 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
return ret;
}
void *
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
{
void *ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x;
if (ret == oldv)
*x = newv;
CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
return ret;
}
#endif
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER

View File

@ -88,20 +88,6 @@ typedef struct _cairo_cache_entry {
unsigned long size;
} cairo_cache_entry_t;
typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
struct _cairo_cache {
cairo_hash_table_t *hash_table;
cairo_cache_predicate_func_t predicate;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
unsigned long size;
int freeze_count;
};
typedef cairo_bool_t
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
@ -109,15 +95,14 @@ typedef void
(*cairo_cache_callback_func_t) (void *entry,
void *closure);
cairo_private cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
cairo_private cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
cairo_private void
_cairo_cache_fini (cairo_cache_t *cache);
_cairo_cache_destroy (cairo_cache_t *cache);
cairo_private void
_cairo_cache_freeze (cairo_cache_t *cache);

View File

@ -48,10 +48,48 @@ _cairo_cache_entry_is_non_zero (const void *entry)
return ((const cairo_cache_entry_t *) entry)->size;
}
static cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cache->hash_table = _cairo_hash_table_create (keys_equal);
if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (predicate == NULL)
predicate = _cairo_cache_entry_is_non_zero;
cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
cache->max_size = max_size;
cache->size = 0;
cache->freeze_count = 0;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_cache_pluck (void *entry, void *closure)
{
_cairo_cache_remove (closure, entry);
}
static void
_cairo_cache_fini (cairo_cache_t *cache)
{
_cairo_hash_table_foreach (cache->hash_table,
_cairo_cache_pluck,
cache);
assert (cache->size == 0);
_cairo_hash_table_destroy (cache->hash_table);
}
/**
* _cairo_cache_init:
* @cache: the #cairo_cache_t to initialise
* _cairo_cache_create:
* @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
@ -84,53 +122,49 @@ _cairo_cache_entry_is_non_zero (const void *entry)
* used to establish a window during which no automatic removal of
* entries will occur.
**/
cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cache->hash_table = _cairo_hash_table_create (keys_equal);
if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
cairo_status_t status;
cairo_cache_t *cache;
if (predicate == NULL)
predicate = _cairo_cache_entry_is_non_zero;
cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
cache = malloc (sizeof (cairo_cache_t));
if (unlikely (cache == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
cache->max_size = max_size;
cache->size = 0;
status = _cairo_cache_init (cache,
keys_equal,
predicate,
entry_destroy,
max_size);
if (unlikely (status)) {
free (cache);
return NULL;
}
cache->freeze_count = 0;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_cache_pluck (void *entry, void *closure)
{
_cairo_cache_remove (closure, entry);
return cache;
}
/**
* _cairo_cache_fini:
* _cairo_cache_destroy:
* @cache: a cache to destroy
*
* Immediately destroys the given cache, freeing all resources
* associated with it. As part of this process, the entry_destroy()
* function, (as passed to _cairo_cache_init()), will be called for
* function, (as passed to _cairo_cache_create()), will be called for
* each entry in the cache.
**/
void
_cairo_cache_fini (cairo_cache_t *cache)
_cairo_cache_destroy (cairo_cache_t *cache)
{
_cairo_hash_table_foreach (cache->hash_table,
_cairo_cache_pluck,
cache);
assert (cache->size == 0);
_cairo_hash_table_destroy (cache->hash_table);
_cairo_cache_fini (cache);
free (cache);
}
/**
@ -188,7 +222,7 @@ _cairo_cache_thaw (cairo_cache_t *cache)
*
* Performs a lookup in @cache looking for an entry which has a key
* that matches @key, (as determined by the keys_equal() function
* passed to _cairo_cache_init()).
* passed to _cairo_cache_create()).
*
* Return value: %TRUE if there is an entry in the cache that matches
* @key, (which will now be in *entry_return). %FALSE otherwise, (in

View File

@ -336,12 +336,17 @@ _cairo_clip_intersect_region (cairo_clip_t *clip,
if (clip->region) {
status = cairo_region_intersect (clip->region, region);
cairo_region_destroy (region);
} else {
clip->region = region;
clip->region = cairo_region_copy (region);
assert (clip->region != NULL);
if ((status = cairo_region_status (clip->region)))
clip->region = NULL;
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
cairo_region_destroy (region);
if (!clip->region || cairo_region_is_empty (clip->region))
_cairo_clip_set_all_clipped (clip, target);
@ -627,10 +632,9 @@ _cairo_clip_clip (cairo_clip_t *clip,
cairo_surface_t *target)
{
cairo_status_t status;
cairo_rectangle_int_t limits, extents;
cairo_rectangle_int_t rectangle;
cairo_traps_t traps;
cairo_box_t ignored_box;
cairo_bool_t have_limits;
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
@ -664,43 +668,13 @@ _cairo_clip_clip (cairo_clip_t *clip,
_cairo_traps_init (&traps);
/* Limit the traps to the target surface and current clip
/* Limit the traps to the target surface
* - so we don't add more traps than needed. */
have_limits = FALSE;
if (clip->region != NULL) {
cairo_region_get_extents (clip->region, &limits);
have_limits = TRUE;
}
if (clip->surface != NULL) {
if (have_limits) {
if (! _cairo_rectangle_intersect (&limits, &clip->surface_rect)) {
_cairo_clip_set_all_clipped (clip, target);
return CAIRO_STATUS_SUCCESS;
}
} else {
limits = clip->surface_rect;
have_limits = TRUE;
}
}
status = _cairo_surface_get_extents (target, &extents);
status = _cairo_surface_get_extents (target, &rectangle);
if (status == CAIRO_STATUS_SUCCESS) {
if (have_limits) {
if (! _cairo_rectangle_intersect (&limits, &extents)) {
_cairo_clip_set_all_clipped (clip, target);
return CAIRO_STATUS_SUCCESS;
}
} else {
limits = extents;
have_limits = TRUE;
}
}
if (have_limits) {
cairo_box_t box;
_cairo_box_from_rectangle (&box, &limits);
_cairo_box_from_rectangle (&box, &rectangle);
_cairo_traps_limit (&traps, &box);
}

View File

@ -79,6 +79,8 @@ cairo_debug_reset_static_data (void)
}
#if HAVE_VALGRIND
#include <memcheck.h>
void
_cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
{
@ -105,7 +107,7 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
width = image->width*4;
break;
default:
/* XXX compute width from pixman bpp */
ASSERT_NOT_REACHED;
return;
}
@ -117,45 +119,3 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
}
}
#endif
#if 0
void
_cairo_image_surface_write_to_ppm (cairo_image_surface_t *isurf, const char *fn)
{
char *fmt;
if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24)
fmt = "P6";
else if (isurf->format == CAIRO_FORMAT_A8)
fmt = "P5";
else
return;
FILE *fp = fopen(fn, "wb");
if (!fp)
return;
fprintf (fp, "%s %d %d 255\n", fmt,isurf->width, isurf->height);
for (int j = 0; j < isurf->height; j++) {
unsigned char *row = isurf->data + isurf->stride * j;
for (int i = 0; i < isurf->width; i++) {
if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24) {
unsigned char r = *row++;
unsigned char g = *row++;
unsigned char b = *row++;
*row++;
putc(r, fp);
putc(g, fp);
putc(b, fp);
} else {
unsigned char a = *row++;
putc(a, fp);
}
}
}
fclose (fp);
fprintf (stderr, "Wrote %s\n", fn);
}
#endif

View File

@ -766,7 +766,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
*src_x, *src_y, width, height,
CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
(cairo_surface_t **) &src,
&src_attr);
if (status)

View File

@ -283,11 +283,11 @@ face_props_parse (twin_face_properties_t *props,
}
static cairo_status_t
twin_font_face_create_properties (cairo_font_face_t *twin_face,
twin_face_properties_t **props_out)
twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
cairo_toy_font_face_t *toy_face)
{
twin_face_properties_t *props;
cairo_status_t status;
twin_face_properties_t *props;
props = malloc (sizeof (twin_face_properties_t));
if (unlikely (props == NULL))
@ -297,37 +297,22 @@ twin_font_face_create_properties (cairo_font_face_t *twin_face,
props->monospace = FALSE;
props->smallcaps = FALSE;
status = cairo_font_face_set_user_data (twin_face,
&twin_properties_key,
props, free);
if (unlikely (status)) {
free (props);
return status;
}
if (props_out)
*props_out = props;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
cairo_toy_font_face_t *toy_face)
{
cairo_status_t status;
twin_face_properties_t *props;
status = twin_font_face_create_properties (twin_face, &props);
if (unlikely (status))
return status;
props->slant = toy_face->slant;
props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
face_props_parse (props, toy_face->family);
status = cairo_font_face_set_user_data (twin_face,
&twin_properties_key,
props, free);
if (unlikely (status))
goto FREE_PROPS;
return CAIRO_STATUS_SUCCESS;
FREE_PROPS:
free (props);
return status;
}
@ -709,35 +694,6 @@ twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
* Face constructor
*/
static cairo_font_face_t *
_cairo_font_face_twin_create_internal (void)
{
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;
}
cairo_font_face_t *
_cairo_font_face_twin_create_fallback (void)
{
cairo_font_face_t *twin_font_face;
cairo_status_t status;
twin_font_face = _cairo_font_face_twin_create_internal ();
status = twin_font_face_create_properties (twin_font_face, NULL);
if (status) {
cairo_font_face_destroy (twin_font_face);
return (cairo_font_face_t *) &_cairo_font_face_nil;
}
return twin_font_face;
}
cairo_status_t
_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face)
@ -745,7 +701,10 @@ _cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
cairo_status_t status;
cairo_font_face_t *twin_font_face;
twin_font_face = _cairo_font_face_twin_create_internal ();
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);
status = twin_font_face_set_properties_from_toy (twin_font_face, toy_face);
if (status) {
cairo_font_face_destroy (twin_font_face);

View File

@ -132,7 +132,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
* cairo_font_options_destroy:
* @options: a #cairo_font_options_t
*
* Destroys a #cairo_font_options_t object created with
* Destroys a #cairo_font_options_t object created with with
* cairo_font_options_create() or cairo_font_options_copy().
**/
void

View File

@ -27,7 +27,7 @@
void
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
{
memset (freelist, 0, sizeof (cairo_freelist_t));
memset (freelist, 0, sizeof(cairo_freelist_t));
freelist->nodesize = nodesize;
}
@ -36,11 +36,7 @@ _cairo_freelist_fini (cairo_freelist_t *freelist)
{
cairo_freelist_node_t *node = freelist->first_free_node;
while (node) {
cairo_freelist_node_t *next;
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
next = node->next;
cairo_freelist_node_t *next = node->next;
free (node);
node = next;
}
@ -50,16 +46,10 @@ void *
_cairo_freelist_alloc (cairo_freelist_t *freelist)
{
if (freelist->first_free_node) {
cairo_freelist_node_t *node;
node = freelist->first_free_node;
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
cairo_freelist_node_t *node = freelist->first_free_node;
freelist->first_free_node = node->next;
VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
return node;
return (void*)node;
}
return malloc (freelist->nodesize);
}
@ -79,6 +69,5 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
if (node) {
node->next = freelist->first_free_node;
freelist->first_free_node = node;
VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
}
}

View File

@ -143,8 +143,6 @@ struct _cairo_ft_font_face {
#if CAIRO_HAS_FC_FONT
FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
cairo_font_face_t *resolved_font_face;
FcConfig *resolved_config;
#endif
};
@ -155,11 +153,13 @@ static cairo_status_t
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
FcPattern *pattern);
static cairo_font_face_t *
static cairo_status_t
_cairo_ft_resolve_pattern (FcPattern *pattern,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options);
const cairo_font_options_t *options,
cairo_ft_unscaled_font_t **unscaled,
cairo_ft_options_t *ft_options);
#endif
@ -239,9 +239,7 @@ _cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
if (! unscaled->from_face)
_font_map_release_face_lock_held (font_map, unscaled);
_font_map_release_face_lock_held (font_map, unscaled);
_cairo_ft_unscaled_font_fini (unscaled);
free (unscaled);
}
@ -1539,40 +1537,38 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
}
static cairo_status_t
_cairo_ft_font_face_scaled_font_create (void *abstract_font_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_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_ft_options_t ft_options,
cairo_scaled_font_t **font_out)
{
cairo_ft_font_face_t *font_face = abstract_font_face;
cairo_ft_scaled_font_t *scaled_font;
FT_Face face;
FT_Size_Metrics *metrics;
cairo_font_extents_t fs_metrics;
cairo_status_t status;
cairo_ft_unscaled_font_t *unscaled;
assert (font_face->unscaled);
face = _cairo_ft_unscaled_font_lock_face (font_face->unscaled);
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (unlikely (face == NULL)) /* backend error */
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
scaled_font = malloc (sizeof (cairo_ft_scaled_font_t));
scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
if (unlikely (scaled_font == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL;
}
scaled_font->unscaled = unscaled = font_face->unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
scaled_font->unscaled = unscaled;
_cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
_cairo_ft_options_merge (&scaled_font->ft_options, &font_face->ft_options);
_cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
status = _cairo_scaled_font_init (&scaled_font->base,
&font_face->base,
font_face,
font_matrix, ctm, options,
&_cairo_ft_scaled_font_backend);
if (unlikely (status))
@ -1652,7 +1648,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_font_face,
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
FAIL:
_cairo_ft_unscaled_font_unlock_face (font_face->unscaled);
_cairo_ft_unscaled_font_unlock_face (unscaled);
*font_out = _cairo_scaled_font_create_in_error (status);
return CAIRO_STATUS_SUCCESS; /* non-backend error */
}
@ -1934,7 +1930,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
FT_Pos x1, x2;
FT_Pos y1, y2;
FT_Pos advance;
if (!vertical_layout) {
x1 = (metrics->horiBearingX) & -64;
x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
@ -1989,7 +1985,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
else
fs_metrics.y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor;
fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
}
}
@ -2297,20 +2293,21 @@ _cairo_ft_font_face_destroy (void *abstract_face)
}
#if CAIRO_HAS_FC_FONT
if (font_face->pattern) {
if (font_face->pattern)
FcPatternDestroy (font_face->pattern);
cairo_font_face_destroy (font_face->resolved_font_face);
}
#endif
}
static cairo_font_face_t *
_cairo_ft_font_face_get_implementation (void *abstract_face,
static cairo_status_t
_cairo_ft_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)
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font)
{
cairo_ft_font_face_t *font_face = abstract_face;
cairo_ft_unscaled_font_t *unscaled = NULL;
cairo_ft_options_t ft_options;
/* The handling of font options is different depending on how the
* font face was created. When the user creates a font face with
@ -2327,35 +2324,34 @@ _cairo_ft_font_face_get_implementation (void *abstract_face,
* unscaled font. Otherwise, use the ones stored in font_face.
*/
if (font_face->pattern) {
cairo_font_face_t *resolved;
cairo_status_t status;
/* Cache the resolved font whilst the FcConfig remains consistent. */
resolved = font_face->resolved_font_face;
if (resolved != NULL) {
if (! FcInitBringUptoDate ()) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *) &_cairo_font_face_nil;
}
if (font_face->resolved_config == FcConfigGetCurrent ())
return cairo_font_face_reference (resolved);
cairo_font_face_destroy (resolved);
status = _cairo_ft_resolve_pattern (font_face->pattern,
font_matrix,
ctm,
options,
&unscaled,
&ft_options);
if (unlikely (status)) {
/* XXX It is possible for a failure to generate the unscaled font
* here could indicate that the font_face itself is broken - for
* which we should propagate the error.
*/
*scaled_font = _cairo_scaled_font_create_in_error (status);
return CAIRO_STATUS_SUCCESS;
}
resolved = _cairo_ft_resolve_pattern (font_face->pattern,
font_matrix,
ctm,
options);
font_face->resolved_font_face = cairo_font_face_reference (resolved);
font_face->resolved_config = FcConfigGetCurrent ();
return resolved;
}
} else
#endif
{
unscaled = font_face->unscaled;
ft_options = font_face->ft_options;
}
return abstract_face;
return _cairo_ft_scaled_font_create (unscaled,
&font_face->base,
font_matrix, ctm,
options, ft_options,
scaled_font);
}
const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
@ -2366,8 +2362,7 @@ const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
NULL,
#endif
_cairo_ft_font_face_destroy,
_cairo_ft_font_face_scaled_font_create,
_cairo_ft_font_face_get_implementation
_cairo_ft_font_face_scaled_font_create
};
#if CAIRO_HAS_FC_FONT
@ -2390,9 +2385,6 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
font_face->resolved_font_face = NULL;
font_face->resolved_config = NULL;
_cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
*out = &font_face->base;
@ -2585,11 +2577,13 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
_cairo_ft_font_options_substitute (options, pattern);
}
static cairo_font_face_t *
static cairo_status_t
_cairo_ft_resolve_pattern (FcPattern *pattern,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *font_options)
const cairo_font_options_t *font_options,
cairo_ft_unscaled_font_t **unscaled,
cairo_ft_options_t *ft_options)
{
cairo_status_t status;
@ -2597,9 +2591,6 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
FcPattern *resolved;
cairo_ft_font_transform_t sf;
FcResult result;
cairo_ft_unscaled_font_t *unscaled;
cairo_ft_options_t ft_options;
cairo_font_face_t *font_face;
scale = *ctm;
scale.x0 = scale.y0 = 0;
@ -2608,52 +2599,40 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
&scale);
status = _compute_transform (&sf, &scale);
if (unlikely (status))
return (cairo_font_face_t *)&_cairo_font_face_nil;
if (status)
return status;
pattern = FcPatternDuplicate (pattern);
if (pattern == NULL)
return (cairo_font_face_t *)&_cairo_font_face_nil;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
status = _cairo_ft_font_options_substitute (font_options, pattern);
if (status) {
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
if (status)
goto FREE_PATTERN;
}
FcDefaultSubstitute (pattern);
resolved = FcFontMatch (NULL, pattern, &result);
if (!resolved) {
/* We failed to find any font. Substitute twin so that the user can
* see something (and hopefully recognise that the font is missing)
* and not just receive a NO_MEMORY error during rendering.
*/
font_face = _cairo_font_face_twin_create_fallback ();
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
if (unlikely (status)) {
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, unscaled);
if (unlikely (status))
goto FREE_RESOLVED;
}
assert (unscaled != NULL);
_get_pattern_ft_options (resolved, &ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
_get_pattern_ft_options (resolved, ft_options);
FREE_RESOLVED:
FcPatternDestroy (resolved);
@ -2661,7 +2640,7 @@ FREE_RESOLVED:
FREE_PATTERN:
FcPatternDestroy (pattern);
return font_face;
return status;
}
/**

View File

@ -300,20 +300,6 @@ _cairo_glitz_surface_acquire_source_image (void *abstract_surface,
return _cairo_glitz_surface_get_image (surface, NULL, image_out, NULL);
}
static cairo_surface_t *
_cairo_glitz_surface_snapshot (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
cairo_status_t status;
cairo_image_surface_t *image;
status = _cairo_glitz_surface_get_image (surface, NULL, &image, NULL);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
return &image->base;
}
static void
_cairo_glitz_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
@ -733,7 +719,6 @@ _cairo_glitz_pattern_acquire_surface (const cairo_pattern_t *pattern,
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
x, y, width, height,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attr->base);
if (status)
@ -2331,7 +2316,7 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
NULL, /* fill */
NULL, /* show_glyphs */
_cairo_glitz_surface_snapshot,
NULL, /* snapshot */
_cairo_glitz_surface_is_similar,
_cairo_glitz_surface_reset

View File

@ -50,7 +50,6 @@ struct _cairo_gstate {
cairo_font_face_t *font_face;
cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */
cairo_scaled_font_t *previous_scaled_font; /* holdover */
cairo_matrix_t font_matrix;
cairo_font_options_t font_options;

View File

@ -77,8 +77,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
{
cairo_status_t status;
VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
gstate->next = NULL;
gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
@ -92,7 +90,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
gstate->font_face = NULL;
gstate->scaled_font = NULL;
gstate->previous_scaled_font = NULL;
cairo_matrix_init_scale (&gstate->font_matrix,
CAIRO_GSTATE_DEFAULT_FONT_SIZE,
@ -142,8 +139,6 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
{
cairo_status_t status;
VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
gstate->op = other->op;
gstate->tolerance = other->tolerance;
@ -158,7 +153,6 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
gstate->font_face = cairo_font_face_reference (other->font_face);
gstate->scaled_font = cairo_scaled_font_reference (other->scaled_font);
gstate->previous_scaled_font = cairo_scaled_font_reference (other->previous_scaled_font);
gstate->font_matrix = other->font_matrix;
@ -169,7 +163,6 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_stroke_style_fini (&gstate->stroke_style);
cairo_font_face_destroy (gstate->font_face);
cairo_scaled_font_destroy (gstate->scaled_font);
cairo_scaled_font_destroy (gstate->previous_scaled_font);
return status;
}
@ -197,9 +190,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_font_face_destroy (gstate->font_face);
gstate->font_face = NULL;
cairo_scaled_font_destroy (gstate->previous_scaled_font);
gstate->previous_scaled_font = NULL;
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
@ -216,8 +206,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_pattern_destroy (gstate->source);
gstate->source = NULL;
VG (VALGRIND_MAKE_MEM_NOACCESS (gstate, sizeof (cairo_gstate_t)));
}
/**
@ -276,7 +264,6 @@ _cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
*gstate = top->next;
_cairo_gstate_fini (top);
VG (VALGRIND_MAKE_MEM_UNDEFINED (&top->next, sizeof (cairo_gstate_t *)));
top->next = *freelist;
*freelist = top;
@ -827,13 +814,14 @@ _cairo_gstate_path_extents (cairo_gstate_t *gstate,
*y2 = py2;
}
static void
static cairo_status_t
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t **pattern,
cairo_pattern_t *original,
cairo_matrix_t *ctm_inverse)
{
_cairo_pattern_init_static_copy (pattern, original);
cairo_status_t status;
cairo_bool_t have_copy = FALSE;
/* apply device_transform first so that it is transformed by ctm_inverse */
if (original->type == CAIRO_PATTERN_TYPE_SURFACE) {
@ -843,38 +831,60 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
surface_pattern = (cairo_surface_pattern_t *) original;
surface = surface_pattern->surface;
if (_cairo_surface_has_device_transform (surface))
_cairo_pattern_transform (pattern, &surface->device_transform);
if (_cairo_surface_has_device_transform (surface)) {
status = _cairo_pattern_init_copy (*pattern, original);
if (unlikely (status))
return status;
have_copy = TRUE;
_cairo_pattern_transform (*pattern, &surface->device_transform);
}
}
if (! _cairo_matrix_is_identity (ctm_inverse))
_cairo_pattern_transform (pattern, ctm_inverse);
if (! _cairo_matrix_is_identity (ctm_inverse)) {
if (! have_copy) {
status = _cairo_pattern_init_copy (*pattern, original);
if (unlikely (status))
return status;
have_copy = TRUE;
}
_cairo_pattern_transform (*pattern, ctm_inverse);
}
if (! have_copy)
*pattern = original;
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
cairo_pattern_t *pattern)
cairo_pattern_t **pattern)
{
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
}
static void
static cairo_status_t
_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t **pattern,
cairo_pattern_t *mask)
{
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
}
cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_pattern_union_t pattern;
cairo_pattern_t *pattern;
cairo_pattern_union_t pattern_stack;
if (gstate->source->status)
return gstate->source->status;
@ -883,12 +893,19 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (unlikely (status))
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
pattern = &pattern_stack.base;
status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
if (unlikely (status))
return status;
return _cairo_surface_paint (gstate->target,
gstate->op,
&pattern.base,
NULL);
status = _cairo_surface_paint (gstate->target,
gstate->op,
pattern, NULL);
if (pattern == &pattern_stack.base)
_cairo_pattern_fini (pattern);
return status;
}
cairo_status_t
@ -896,7 +913,8 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_pattern_union_t source_pattern, mask_pattern;
cairo_pattern_union_t source_pattern_stack, mask_pattern_stack;
cairo_pattern_t *source_pattern, *mask_pattern;
if (mask->status)
return mask->status;
@ -908,21 +926,36 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (unlikely (status))
return status;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
source_pattern = &source_pattern_stack.base;
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
if (unlikely (status))
return status;
return _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base,
NULL);
mask_pattern = &mask_pattern_stack.base;
status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern, mask);
if (unlikely (status))
goto CLEANUP_SOURCE;
status = _cairo_surface_mask (gstate->target,
gstate->op,
source_pattern,
mask_pattern, NULL);
if (mask_pattern == &mask_pattern_stack.base)
_cairo_pattern_fini (&mask_pattern_stack.base);
CLEANUP_SOURCE:
if (source_pattern == &source_pattern_stack.base)
_cairo_pattern_fini (&source_pattern_stack.base);
return status;
}
cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_pattern_union_t source_pattern;
cairo_pattern_union_t source_pattern_stack;
cairo_pattern_t *source_pattern;
if (gstate->source->status)
return gstate->source->status;
@ -934,18 +967,26 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (unlikely (status))
return status;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
source_pattern = &source_pattern_stack.base;
status = _cairo_gstate_copy_transformed_source (gstate,
&source_pattern);
if (unlikely (status))
return status;
return _cairo_surface_stroke (gstate->target,
gstate->op,
&source_pattern.base,
path,
&gstate->stroke_style,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->tolerance,
gstate->antialias,
NULL);
status = _cairo_surface_stroke (gstate->target,
gstate->op,
source_pattern,
path,
&gstate->stroke_style,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->tolerance,
gstate->antialias, NULL);
if (source_pattern == &source_pattern_stack.base)
_cairo_pattern_fini (&source_pattern_stack.base);
return status;
}
cairo_status_t
@ -1010,7 +1051,8 @@ cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_pattern_union_t pattern;
cairo_pattern_union_t pattern_stack;
cairo_pattern_t *pattern;
if (gstate->source->status)
return gstate->source->status;
@ -1019,16 +1061,24 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (unlikely (status))
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
pattern = &pattern_stack.base;
status = _cairo_gstate_copy_transformed_source (gstate, &pattern);
if (unlikely (status))
return status;
return _cairo_surface_fill (gstate->target,
gstate->op,
&pattern.base,
path,
gstate->fill_rule,
gstate->tolerance,
gstate->antialias,
NULL);
status = _cairo_surface_fill (gstate->target,
gstate->op,
pattern,
path,
gstate->fill_rule,
gstate->tolerance,
gstate->antialias,
NULL);
if (pattern == &pattern_stack.base)
_cairo_pattern_fini (&pattern_stack.base);
return status;
}
void
@ -1243,14 +1293,10 @@ _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
static void
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
{
if (gstate->scaled_font == NULL)
return;
if (gstate->previous_scaled_font != NULL)
cairo_scaled_font_destroy (gstate->previous_scaled_font);
gstate->previous_scaled_font = gstate->scaled_font;
gstate->scaled_font = NULL;
if (gstate->scaled_font) {
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
}
}
cairo_status_t
@ -1574,7 +1620,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags)
{
cairo_pattern_union_t source_pattern;
cairo_pattern_union_t source_pattern_stack;
cairo_pattern_t *source_pattern;
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
cairo_glyph_t *transformed_glyphs;
cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
@ -1627,7 +1674,10 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (status || num_glyphs == 0)
goto CLEANUP_GLYPHS;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
source_pattern = &source_pattern_stack.base;
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern);
if (unlikely (status))
goto CLEANUP_GLYPHS;
/* For really huge font sizes, we can just do path;fill instead of
* show_glyphs, as show_glyphs would put excess pressure on the cache,
@ -1648,7 +1698,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
_cairo_surface_get_text_path_fill_threshold (gstate->target)) {
status = _cairo_surface_show_text_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
source_pattern,
utf8, utf8_len,
transformed_glyphs, num_glyphs,
transformed_clusters, num_clusters,
@ -1666,7 +1716,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (gstate->target,
gstate->op,
&source_pattern.base,
source_pattern,
&path,
CAIRO_FILL_RULE_WINDING,
gstate->tolerance,
@ -1675,6 +1725,9 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
_cairo_path_fixed_fini (&path);
}
if (source_pattern == &source_pattern_stack.base)
_cairo_pattern_fini (&source_pattern_stack.base);
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
cairo_glyph_free (transformed_glyphs);

View File

@ -449,7 +449,7 @@ slim_hidden_def (cairo_format_stride_for_width);
* Creates an image surface for the provided pixel data. The output
* buffer must be kept around until the #cairo_surface_t is destroyed
* or cairo_surface_finish() is called on the surface. The initial
* contents of @data will be used as the initial image contents; you
* contents of @buffer will be used as the initial image contents; you
* must explicitly clear the buffer, using, for example,
* cairo_rectangle() and cairo_fill() if you want it cleared.
*
@ -967,7 +967,6 @@ _cairo_image_surface_composite (cairo_operator_t op,
src_x, src_y,
mask_x, mask_y,
width, height,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
(cairo_surface_t **) &mask,
&src_attr, &mask_attr);
@ -1084,40 +1083,12 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
return status;
}
static pixman_format_code_t
_pixman_mask_format_from_antialias (cairo_antialias_t antialias)
static cairo_format_t
_cairo_mask_format_from_antialias (cairo_antialias_t antialias)
{
if (antialias == CAIRO_ANTIALIAS_NONE)
return PIXMAN_a1;
return PIXMAN_a8;
}
static void
_pixman_add_trapezoids (pixman_image_t *image,
int dst_x, int dst_y,
const cairo_trapezoid_t *traps,
int num_traps)
{
while (num_traps--) {
pixman_trapezoid_t trap;
trap.top = _cairo_fixed_to_16_16 (traps->top);
trap.bottom = _cairo_fixed_to_16_16 (traps->bottom);
trap.left.p1.x = _cairo_fixed_to_16_16 (traps->left.p1.x);
trap.left.p1.y = _cairo_fixed_to_16_16 (traps->left.p1.y);
trap.left.p2.x = _cairo_fixed_to_16_16 (traps->left.p2.x);
trap.left.p2.y = _cairo_fixed_to_16_16 (traps->left.p2.y);
trap.right.p1.x = _cairo_fixed_to_16_16 (traps->right.p1.x);
trap.right.p1.y = _cairo_fixed_to_16_16 (traps->right.p1.y);
trap.right.p2.x = _cairo_fixed_to_16_16 (traps->right.p2.x);
trap.right.p2.y = _cairo_fixed_to_16_16 (traps->right.p2.y);
pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
traps++;
}
return CAIRO_FORMAT_A1;
return CAIRO_FORMAT_A8;
}
static cairo_int_status_t
@ -1138,7 +1109,10 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src;
cairo_int_status_t status;
pixman_image_t *mask;
cairo_image_surface_t *mask = NULL;
pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
pixman_trapezoid_t *pixman_traps = stack_traps;
int i;
if (height == 0 || width == 0)
return CAIRO_STATUS_SUCCESS;
@ -1146,6 +1120,26 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
if (CAIRO_INJECT_FAULT ())
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/* Convert traps to pixman traps */
if (num_traps > ARRAY_LENGTH (stack_traps)) {
pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t));
if (unlikely (pixman_traps == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
for (i = 0; i < num_traps; i++) {
pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
}
/* Special case adding trapezoids onto a mask surface; we want to avoid
* creating an intermediate temporary mask unnecessarily.
*
@ -1165,18 +1159,19 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
! dst->has_clip &&
antialias != CAIRO_ANTIALIAS_NONE)
{
_pixman_add_trapezoids (dst->pixman_image, 0, 0, traps, num_traps);
return CAIRO_STATUS_SUCCESS;
pixman_add_trapezoids (dst->pixman_image, 0, 0,
num_traps, pixman_traps);
status = CAIRO_STATUS_SUCCESS;
goto finish;
}
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))
return status;
goto finish;
status = _cairo_image_surface_set_attributes (src, &attributes,
dst_x + width / 2.,
@ -1184,18 +1179,20 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
if (unlikely (status))
goto CLEANUP_SOURCE;
mask = pixman_image_create_bits (_pixman_mask_format_from_antialias (antialias),
width, height, NULL, 0);
if (unlikely (mask == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
mask = (cairo_image_surface_t *)
cairo_image_surface_create (
_cairo_mask_format_from_antialias (antialias),
width, height);
status = mask->base.status;
if (unlikely (status))
goto CLEANUP_SOURCE;
}
_pixman_add_trapezoids (mask, dst_x, dst_y, traps, num_traps);
pixman_add_trapezoids (mask->pixman_image, - dst_x, - dst_y,
num_traps, pixman_traps);
pixman_image_composite (_pixman_operator (op),
src->pixman_image,
mask,
mask->pixman_image,
dst->pixman_image,
src_x + attributes.x_offset,
src_y + attributes.y_offset,
@ -1203,8 +1200,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
dst_x, dst_y,
width, height);
pixman_image_unref (mask);
if (! _cairo_operator_bounded_by_mask (op))
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
&attributes,
@ -1213,10 +1208,15 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
src_x, src_y,
0, 0,
dst_x, dst_y, width, height);
cairo_surface_destroy (&mask->base);
CLEANUP_SOURCE:
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
finish:
if (pixman_traps != stack_traps)
free (pixman_traps);
return status;
}
@ -1237,9 +1237,9 @@ typedef struct _cairo_image_surface_span_renderer {
void
_cairo_image_surface_span_render_row (
int y,
const cairo_half_open_span_t *spans,
unsigned num_spans,
int y,
const cairo_half_open_span_t *spans,
unsigned num_spans,
cairo_image_surface_t *mask,
const cairo_composite_rectangles_t *rects)
{
@ -1414,7 +1414,6 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
CAIRO_CONTENT_COLOR_ALPHA,
rects->src.x, rects->src.y,
width, height,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &renderer->src,
&renderer->src_attributes);
if (status)

View File

@ -1,189 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Chris Wilson
*
* 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 Chris Wilson.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
#ifndef CAIRO_LIST_PRIVATE_H
#define CAIRO_LIST_PRIVATE_H
#include "cairo-compiler-private.h"
/* Basic circular, doubly linked list implementation */
typedef struct _cairo_list {
struct _cairo_list *next, *prev;
} cairo_list_t;
#define cairo_list_entry(ptr, type, member) \
cairo_container_of(ptr, type, member)
#define cairo_list_first_entry(ptr, type, member) \
cairo_list_entry((ptr)->next, type, member)
#define cairo_list_last_entry(ptr, type, member) \
cairo_list_entry((ptr)->prev, type, member)
#define cairo_list_foreach(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define cairo_list_foreach_entry(pos, type, head, member) \
for (pos = cairo_list_entry((head)->next, type, member);\
&pos->member != (head); \
pos = cairo_list_entry(pos->member.next, type, member))
#define cairo_list_foreach_entry_safe(pos, n, type, head, member) \
for (pos = cairo_list_entry ((head)->next, type, member),\
n = cairo_list_entry (pos->member.next, type, member);\
&pos->member != (head); \
pos = n, n = cairo_list_entry (n->member.next, type, member))
#define cairo_list_foreach_entry_reverse(pos, type, head, member) \
for (pos = cairo_list_entry((head)->prev, type, member);\
&pos->member != (head); \
pos = cairo_list_entry(pos->member.prev, type, member))
#ifdef CAIRO_LIST_DEBUG
static inline void
cairo_list_validate (const cairo_list_t *head)
{
cairo_list_t *link;
cairo_list_foreach (link, head) {
assert (link->next->prev == link);
assert (link->prev->next == link);
}
}
#else
#define cairo_list_validate(head)
#endif
static inline void
cairo_list_init (cairo_list_t *entry)
{
entry->next = entry;
entry->prev = entry;
}
static inline void
__cairo_list_add (cairo_list_t *entry,
cairo_list_t *prev,
cairo_list_t *next)
{
next->prev = entry;
entry->next = next;
entry->prev = prev;
prev->next = entry;
}
static inline void
cairo_list_add (cairo_list_t *entry, cairo_list_t *head)
{
cairo_list_validate (head);
__cairo_list_add (entry, head, head->next);
cairo_list_validate (head);
}
static inline void
cairo_list_add_tail (cairo_list_t *entry, cairo_list_t *head)
{
cairo_list_validate (head);
__cairo_list_add (entry, head->prev, head);
cairo_list_validate (head);
}
static inline void
__cairo_list_del (cairo_list_t *prev, cairo_list_t *next)
{
next->prev = prev;
prev->next = next;
}
static inline void
cairo_list_del (cairo_list_t *entry)
{
__cairo_list_del (entry->prev, entry->next);
cairo_list_init (entry);
}
static inline void
cairo_list_move (cairo_list_t *entry, cairo_list_t *head)
{
cairo_list_validate (head);
__cairo_list_del (entry->prev, entry->next);
__cairo_list_add (entry, head, head->next);
cairo_list_validate (head);
}
static inline void
cairo_list_move_tail (cairo_list_t *entry, cairo_list_t *head)
{
cairo_list_validate (head);
__cairo_list_del (entry->prev, entry->next);
__cairo_list_add (entry, head->prev, head);
cairo_list_validate (head);
}
static inline void
cairo_list_swap (cairo_list_t *entry, cairo_list_t *other)
{
cairo_list_validate (head);
__cairo_list_add (entry, other->prev, other->next);
cairo_list_init (other);
cairo_list_validate (head);
}
static inline cairo_bool_t
cairo_list_is_first (const cairo_list_t *entry,
const cairo_list_t *head)
{
cairo_list_validate (head);
return entry->prev == head;
}
static inline cairo_bool_t
cairo_list_is_last (const cairo_list_t *entry,
const cairo_list_t *head)
{
cairo_list_validate (head);
return entry->next == head;
}
static inline cairo_bool_t
cairo_list_is_empty (const cairo_list_t *head)
{
cairo_list_validate (head);
return head->next == head;
}
#endif /* CAIRO_LIST_PRIVATE_H */

View File

@ -150,9 +150,8 @@ typedef struct _cairo_meta_surface {
/* A meta-surface is logically unbounded, but when used as a
* source we need to render it to an image, so we need a size at
* which to create that image. */
double width_pixels;
double height_pixels;
cairo_rectangle_int_t extents;
int width_pixels;
int height_pixels;
cairo_array_t commands;
cairo_surface_t *commands_owner;
@ -161,13 +160,18 @@ typedef struct _cairo_meta_surface {
int replay_start_idx;
} cairo_meta_surface_t;
slim_hidden_proto (cairo_meta_surface_create);
slim_hidden_proto (cairo_meta_surface_replay);
cairo_private cairo_surface_t *
_cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels);
cairo_private cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
cairo_private cairo_status_t
_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,

View File

@ -42,9 +42,7 @@
* level of paint, mask, stroke, fill, and show_text_glyphs). The meta
* surface can then be "replayed" against any target surface with:
*
* <informalexample><programlisting>
* cairo_meta_surface_replay (meta, target);
* </programlisting></informalexample>
* _cairo_meta_surface_replay (meta, target);
*
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
@ -59,7 +57,6 @@
*/
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-clip-private.h"
@ -76,38 +73,13 @@ static const cairo_surface_backend_t cairo_meta_surface_backend;
*
* XXX: The naming of "pixels" in the size here is a misnomer. It's
* actually a size in whatever device-space units are desired (again,
* according to the intended replay target).
* according to the intended replay target). This should likely also
* be changed to use doubles not ints.
*/
/**
* cairo_meta_surface_create:
* @content: the content of the meta surface
* @width_pixels: width of the surface, in pixels
* @height_pixels: height of the surface, in pixels
*
* Creates a meta-surface which can be used to record all drawing operations
* at the highest level (that is, the level of paint, mask, stroke, fill
* and show_text_glyphs). The meta surface can then be "replayed" against
* any target surface with:
*
* <informalexample><programlisting>
* cairo_meta_surface_replay (meta, target);
* </programlisting></informalexample>
*
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
* the meta surface had instead been applied to the target surface.
*
* The recording phase of the meta surface is careful to snapshot all
* necessary objects (paths, patterns, etc.), in order to achieve
* accurate replay.
*
* Since 1.10
**/
cairo_surface_t *
cairo_meta_surface_create (cairo_content_t content,
double width_pixels,
double height_pixels)
_cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels)
{
cairo_meta_surface_t *meta;
@ -122,29 +94,6 @@ cairo_meta_surface_create (cairo_content_t content,
meta->width_pixels = width_pixels;
meta->height_pixels = height_pixels;
/* unbounded -> 'infinite' extents */
if (width_pixels < 0) {
meta->extents.x = CAIRO_RECT_INT_MIN;
meta->extents.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
meta->extents.x = 0;
if (ceil (width_pixels) > CAIRO_RECT_INT_MAX)
meta->extents.width = CAIRO_RECT_INT_MAX;
else
meta->extents.width = ceil (width_pixels);
}
if (height_pixels < 0) {
meta->extents.y = CAIRO_RECT_INT_MIN;
meta->extents.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
meta->extents.y = 0;
if (ceil (height_pixels) > CAIRO_RECT_INT_MAX)
meta->extents.height = CAIRO_RECT_INT_MAX;
else
meta->extents.height = ceil (height_pixels);
}
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
meta->commands_owner = NULL;
@ -153,7 +102,6 @@ cairo_meta_surface_create (cairo_content_t content,
return &meta->base;
}
slim_hidden_def (cairo_meta_surface_create);
static cairo_surface_t *
_cairo_meta_surface_create_similar (void *abstract_surface,
@ -161,7 +109,7 @@ _cairo_meta_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return cairo_meta_surface_create (content, width, height);
return _cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -186,31 +134,31 @@ _cairo_meta_surface_finish (void *abstract_surface)
/* 5 basic drawing operations */
case CAIRO_COMMAND_PAINT:
_cairo_pattern_fini_snapshot (&command->paint.source.base);
_cairo_pattern_fini (&command->paint.source.base);
free (command);
break;
case CAIRO_COMMAND_MASK:
_cairo_pattern_fini_snapshot (&command->mask.source.base);
_cairo_pattern_fini_snapshot (&command->mask.mask.base);
_cairo_pattern_fini (&command->mask.source.base);
_cairo_pattern_fini (&command->mask.mask.base);
free (command);
break;
case CAIRO_COMMAND_STROKE:
_cairo_pattern_fini_snapshot (&command->stroke.source.base);
_cairo_pattern_fini (&command->stroke.source.base);
_cairo_path_fixed_fini (&command->stroke.path);
_cairo_stroke_style_fini (&command->stroke.style);
free (command);
break;
case CAIRO_COMMAND_FILL:
_cairo_pattern_fini_snapshot (&command->fill.source.base);
_cairo_pattern_fini (&command->fill.source.base);
_cairo_path_fixed_fini (&command->fill.path);
free (command);
break;
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
_cairo_pattern_fini_snapshot (&command->show_text_glyphs.source.base);
_cairo_pattern_fini (&command->show_text_glyphs.source.base);
free (command->show_text_glyphs.utf8);
free (command->show_text_glyphs.glyphs);
free (command->show_text_glyphs.clusters);
@ -244,26 +192,11 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
cairo_meta_surface_t *surface = abstract_surface;
cairo_surface_t *image;
image = _cairo_surface_has_snapshot (&surface->base,
&_cairo_image_surface_backend,
surface->content);
if (image != NULL) {
*image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
image = _cairo_image_surface_create_with_content (surface->content,
ceil (surface->width_pixels),
ceil (surface->height_pixels));
surface->width_pixels,
surface->height_pixels);
status = cairo_meta_surface_replay (&surface->base, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
status = _cairo_surface_attach_snapshot (&surface->base, image, NULL);
status = _cairo_meta_surface_replay (&surface->base, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
@ -271,7 +204,8 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
*image_out = (cairo_image_surface_t *) image;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
return status;
}
static void
@ -282,16 +216,6 @@ _cairo_meta_surface_release_source_image (void *abstract_surface,
cairo_surface_destroy (&image->base);
}
static void
_draw_command_init (cairo_command_header_t *command,
cairo_command_type_t type,
cairo_meta_surface_t *meta)
{
command->type = type;
command->region = CAIRO_META_REGION_ALL;
command->extents = meta->extents;
}
static cairo_int_status_t
_cairo_meta_surface_paint (void *abstract_surface,
cairo_operator_t op,
@ -306,7 +230,12 @@ _cairo_meta_surface_paint (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_draw_command_init (&command->header, CAIRO_COMMAND_PAINT, meta);
command->header.type = CAIRO_COMMAND_PAINT;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -326,7 +255,7 @@ _cairo_meta_surface_paint (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
CLEANUP_SOURCE:
_cairo_pattern_fini_snapshot (&command->source.base);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
@ -347,7 +276,12 @@ _cairo_meta_surface_mask (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_draw_command_init (&command->header, CAIRO_COMMAND_MASK, meta);
command->header.type = CAIRO_COMMAND_MASK;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -365,9 +299,9 @@ _cairo_meta_surface_mask (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
CLEANUP_MASK:
_cairo_pattern_fini_snapshot (&command->mask.base);
_cairo_pattern_fini (&command->mask.base);
CLEANUP_SOURCE:
_cairo_pattern_fini_snapshot (&command->source.base);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
@ -393,7 +327,12 @@ _cairo_meta_surface_stroke (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_draw_command_init (&command->header, CAIRO_COMMAND_STROKE, meta);
command->header.type = CAIRO_COMMAND_STROKE;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -424,7 +363,7 @@ _cairo_meta_surface_stroke (void *abstract_surface,
CLEANUP_PATH:
_cairo_path_fixed_fini (&command->path);
CLEANUP_SOURCE:
_cairo_pattern_fini_snapshot (&command->source.base);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
@ -448,7 +387,12 @@ _cairo_meta_surface_fill (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_draw_command_init (&command->header, CAIRO_COMMAND_FILL, meta);
command->header.type = CAIRO_COMMAND_FILL;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -472,7 +416,7 @@ _cairo_meta_surface_fill (void *abstract_surface,
CLEANUP_PATH:
_cairo_path_fixed_fini (&command->path);
CLEANUP_SOURCE:
_cairo_pattern_fini_snapshot (&command->source.base);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
@ -506,7 +450,12 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_draw_command_init (&command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, meta);
command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -562,7 +511,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
free (command->glyphs);
free (command->clusters);
_cairo_pattern_fini_snapshot (&command->source.base);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
@ -593,10 +542,10 @@ _cairo_meta_surface_snapshot (void *abstract_other)
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
other->base.content);
meta->base.is_snapshot = TRUE;
meta->width_pixels = other->width_pixels;
meta->height_pixels = other->height_pixels;
meta->extents = other->extents;
meta->replay_start_idx = other->replay_start_idx;
meta->content = other->content;
@ -653,7 +602,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
/* Currently, we're using as the "size" of a meta surface the largest
* surface size against which the meta-surface is expected to be
* replayed, (as passed in to cairo_meta_surface_create()).
* replayed, (as passed in to _cairo_meta_surface_create).
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
@ -661,13 +610,13 @@ _cairo_meta_surface_get_extents (void *abstract_surface,
{
cairo_meta_surface_t *surface = abstract_surface;
if (surface->width_pixels < 0 || surface->height_pixels < 0)
if (surface->width_pixels == -1 && surface->height_pixels == -1)
return CAIRO_INT_STATUS_UNSUPPORTED;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = ceil (surface->width_pixels);
rectangle->height = ceil (surface->height_pixels);
rectangle->width = surface->width_pixels;
rectangle->height = surface->height_pixels;
return CAIRO_STATUS_SUCCESS;
}
@ -687,7 +636,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface)
}
static const cairo_surface_backend_t cairo_meta_surface_backend = {
CAIRO_SURFACE_TYPE_META,
CAIRO_INTERNAL_SURFACE_TYPE_META,
_cairo_meta_surface_create_similar,
_cairo_meta_surface_finish,
_cairo_meta_surface_acquire_source_image,
@ -1052,30 +1001,15 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
/**
* cairo_meta_surface_replay:
* @surface: the #cairo_meta_surface_t
* @target: a target #cairo_surface_t onto which to replay the operations
* @width_pixels: width of the surface, in pixels
* @height_pixels: height of the surface, in pixels
*
* A meta surface can be "replayed" against any target surface,
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
* the meta surface had instead been applied to the target surface.
*
* Since 1.10
**/
cairo_status_t
cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
return _cairo_meta_surface_replay_internal (surface,
target,
CAIRO_META_REPLAY,
CAIRO_META_REGION_ALL);
}
slim_hidden_def (cairo_meta_surface_replay);
/* Replay meta to surface. When the return status of each operation is
* one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
@ -1103,59 +1037,3 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
CAIRO_META_REPLAY,
region);
}
/**
* cairo_meta_surface_ink_extents:
* @surface: a #cairo_meta_surface_t
* @x0: the x-coordinate of the top-left of the ink bounding box
* @y0: the y-coordinate of the top-left of the ink bounding box
* @width: the width of the ink bounding box
* @height: the height of the ink bounding box
*
* Measures the extents of the operations stored within the meta-surface.
* This is useful to compute the required size of an image surface (or
* equivalent) into which to replay the full sequence of drawing operaitions.
*
* Since: 1.10
**/
void
cairo_meta_surface_ink_extents (cairo_surface_t *surface,
double *x0,
double *y0,
double *width,
double *height)
{
cairo_surface_t *null_surface;
cairo_surface_t *analysis_surface;
cairo_status_t status;
cairo_box_t bbox;
memset (&bbox, 0, sizeof (bbox));
if (! _cairo_surface_is_meta (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
goto DONE;
}
null_surface = _cairo_null_surface_create (CAIRO_CONTENT_COLOR_ALPHA);
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
cairo_surface_destroy (null_surface);
status = analysis_surface->status;
if (unlikely (status))
goto DONE;
status = cairo_meta_surface_replay (surface, analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
DONE:
if (x0)
*x0 = _cairo_fixed_to_double (bbox.p1.x);
if (y0)
*y0 = _cairo_fixed_to_double (bbox.p1.y);
if (width)
*width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
if (height)
*height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
}

View File

@ -58,13 +58,13 @@ cairo_status_to_string (cairo_status_t status)
{
switch (status) {
case CAIRO_STATUS_SUCCESS:
return "no error has occurred";
return "success";
case CAIRO_STATUS_NO_MEMORY:
return "out of memory";
case CAIRO_STATUS_INVALID_RESTORE:
return "cairo_restore() without matching cairo_save()";
return "cairo_restore without matching cairo_save";
case CAIRO_STATUS_INVALID_POP_GROUP:
return "no saved group to pop, i.e. cairo_pop_group() without matching cairo_push_group()";
return "cairo_pop_group without matching cairo_push_group";
case CAIRO_STATUS_NO_CURRENT_POINT:
return "no current point defined";
case CAIRO_STATUS_INVALID_MATRIX:
@ -118,11 +118,11 @@ cairo_status_to_string (cairo_status_t status)
case CAIRO_STATUS_INVALID_CLUSTERS:
return "input clusters do not represent the accompanying text and glyph arrays";
case CAIRO_STATUS_INVALID_SLANT:
return "invalid value for an input cairo_font_slant_t";
return "invalid value for an input #cairo_font_slant_t";
case CAIRO_STATUS_INVALID_WEIGHT:
return "invalid value for an input cairo_font_weight_t";
return "invalid value for an input #cairo_font_weight_t";
case CAIRO_STATUS_INVALID_SIZE:
return "invalid value (typically too big) for the size of the input (surface, pattern, etc.)";
return "invalid value for the size of the input (surface, pattern, etc.)";
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
return "user-font method not implemented";
default:

View File

@ -36,6 +36,7 @@
#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_toy_font_face_mutex)

View File

@ -97,7 +97,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
surface->backend = backend;
surface->meta = cairo_meta_surface_create (content, width, height);
surface->meta = _cairo_meta_surface_create (content, width, height);
status = cairo_surface_status (surface->meta);
if (unlikely (status))
goto FAIL_CLEANUP_SURFACE;
@ -148,8 +148,8 @@ _cairo_paginated_surface_set_size (cairo_surface_t *surface,
paginated_surface->height = height;
cairo_surface_destroy (paginated_surface->meta);
paginated_surface->meta = cairo_meta_surface_create (paginated_surface->content,
width, height);
paginated_surface->meta = _cairo_meta_surface_create (paginated_surface->content,
width, height);
status = cairo_surface_status (paginated_surface->meta);
if (unlikely (status))
return _cairo_surface_set_error (surface, status);
@ -222,7 +222,7 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
extents.width,
extents.height);
status = cairo_meta_surface_replay (surface->meta, image);
status = _cairo_meta_surface_replay (surface->meta, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
@ -266,7 +266,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
* so we have to do the scaling manually. */
cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
status = cairo_meta_surface_replay (surface->meta, image);
status = _cairo_meta_surface_replay (surface->meta, image);
if (unlikely (status))
goto CLEANUP_IMAGE;
@ -481,9 +481,9 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
cairo_surface_destroy (surface->meta);
surface->meta = cairo_meta_surface_create (surface->content,
surface->width,
surface->height);
surface->meta = _cairo_meta_surface_create (surface->content,
surface->width,
surface->height);
status = cairo_surface_status (surface->meta);
if (unlikely (status))
return status;

View File

@ -38,12 +38,6 @@
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
#include "cairo-list-private.h"
#define WATCH_PATH 0
#if WATCH_PATH
#include <stdio.h>
#endif
enum cairo_path_op {
CAIRO_PATH_OP_MOVE_TO = 0,
@ -51,16 +45,15 @@ enum cairo_path_op {
CAIRO_PATH_OP_CURVE_TO = 2,
CAIRO_PATH_OP_CLOSE_PATH = 3
};
/* we want to make sure a single byte is used for the enum */
/* we want to make sure a single byte is used for thie enum */
typedef char cairo_path_op_t;
/* make _cairo_path_fixed fit into ~512 bytes -- about 50 items */
#define CAIRO_PATH_BUF_SIZE ((512 - sizeof (cairo_path_buf_t)) \
/* make _cairo_path_fixed fit a 512 bytes. about 50 items */
#define CAIRO_PATH_BUF_SIZE ((512 - 4 * sizeof (void*) - sizeof (cairo_path_buf_t)) \
/ (2 * sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
typedef struct _cairo_path_buf {
cairo_list_t link;
struct _cairo_path_buf *next, *prev;
unsigned int buf_size;
unsigned int num_ops;
unsigned int num_points;
@ -68,7 +61,6 @@ typedef struct _cairo_path_buf {
cairo_path_op_t *op;
cairo_point_t *points;
} cairo_path_buf_t;
typedef struct _cairo_path_buf_fixed {
cairo_path_buf_t base;
@ -81,10 +73,9 @@ struct _cairo_path_fixed {
cairo_point_t current_point;
unsigned int has_current_point : 1;
unsigned int has_curve_to : 1;
unsigned int is_box : 1;
unsigned int is_region : 1;
cairo_path_buf_fixed_t buf;
cairo_path_buf_t *buf_tail;
cairo_path_buf_fixed_t buf_head;
};
cairo_private unsigned long
@ -114,14 +105,4 @@ _cairo_path_fixed_iter_is_fill_box (cairo_path_fixed_iter_t *_iter,
cairo_private cairo_bool_t
_cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter);
static inline cairo_bool_t
_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
{
#if WATCH_PATH
fprintf (stderr, "_cairo_path_fixed_is_region () = %s\n",
path->is_region ? "true" : "false");
#endif
return path->is_region;
}
#endif /* CAIRO_PATH_FIXED_PRIVATE_H */

View File

@ -40,11 +40,12 @@
#include "cairo-path-fixed-private.h"
/* private functions */
static cairo_status_t
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
const cairo_point_t *points,
int num_points);
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
cairo_point_t *points,
int num_points);
static void
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
@ -61,43 +62,28 @@ _cairo_path_buf_add_op (cairo_path_buf_t *buf,
cairo_path_op_t op);
static void
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
const cairo_point_t *points,
int num_points);
#define cairo_path_head(path__) (&(path__)->buf.base)
#define cairo_path_tail(path__) cairo_path_buf_prev (cairo_path_head (path__))
#define cairo_path_buf_next(pos__) \
cairo_list_entry ((pos__)->link.next, cairo_path_buf_t, link)
#define cairo_path_buf_prev(pos__) \
cairo_list_entry ((pos__)->link.prev, cairo_path_buf_t, link)
#define cairo_path_foreach_buf_start(pos__, path__) \
pos__ = cairo_path_head (path__); do
#define cairo_path_foreach_buf_end(pos__, path__) \
while ((pos__ = cairo_path_buf_next (pos__)) != cairo_path_head (path__))
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
cairo_point_t *points,
int num_points);
void
_cairo_path_fixed_init (cairo_path_fixed_t *path)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t)));
path->buf_head.base.next = NULL;
path->buf_head.base.prev = NULL;
path->buf_tail = &path->buf_head.base;
cairo_list_init (&path->buf.base.link);
path->buf.base.num_ops = 0;
path->buf.base.num_points = 0;
path->buf.base.buf_size = CAIRO_PATH_BUF_SIZE;
path->buf.base.op = path->buf.op;
path->buf.base.points = path->buf.points;
path->buf_head.base.num_ops = 0;
path->buf_head.base.num_points = 0;
path->buf_head.base.buf_size = CAIRO_PATH_BUF_SIZE;
path->buf_head.base.op = path->buf_head.op;
path->buf_head.base.points = path->buf_head.points;
path->current_point.x = 0;
path->current_point.y = 0;
path->last_move_point = path->current_point;
path->has_current_point = FALSE;
path->has_curve_to = FALSE;
path->is_region = TRUE;
path->is_box = TRUE;
path->last_move_point = path->current_point;
}
cairo_status_t
@ -111,23 +97,21 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
path->current_point = other->current_point;
path->has_current_point = other->has_current_point;
path->last_move_point = other->last_move_point;
path->has_curve_to = other->has_curve_to;
path->is_box = other->is_box;
path->is_region = other->is_region;
path->last_move_point = other->last_move_point;
path->buf.base.num_ops = other->buf.base.num_ops;
path->buf.base.num_points = other->buf.base.num_points;
path->buf.base.buf_size = other->buf.base.buf_size;
memcpy (path->buf.op, other->buf.base.op,
other->buf.base.num_ops * sizeof (other->buf.op[0]));
memcpy (path->buf.points, other->buf.points,
other->buf.base.num_points * sizeof (other->buf.points[0]));
path->buf_head.base.num_ops = other->buf_head.base.num_ops;
path->buf_head.base.num_points = other->buf_head.base.num_points;
path->buf_head.base.buf_size = other->buf_head.base.buf_size;
memcpy (path->buf_head.op, other->buf_head.base.op,
other->buf_head.base.num_ops * sizeof (other->buf_head.op[0]));
memcpy (path->buf_head.points, other->buf_head.points,
other->buf_head.base.num_points * sizeof (other->buf_head.points[0]));
num_points = num_ops = 0;
for (other_buf = cairo_path_buf_next (cairo_path_head (other));
other_buf != cairo_path_head (other);
other_buf = cairo_path_buf_next (other_buf))
for (other_buf = other->buf_head.base.next;
other_buf != NULL;
other_buf = other_buf->next)
{
num_ops += other_buf->num_ops;
num_points += other_buf->num_points;
@ -141,9 +125,9 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
for (other_buf = cairo_path_buf_next (cairo_path_head (other));
other_buf != cairo_path_head (other);
other_buf = cairo_path_buf_next (other_buf))
for (other_buf = other->buf_head.base.next;
other_buf != NULL;
other_buf = other_buf->next)
{
memcpy (buf->op + buf->num_ops, other_buf->op,
other_buf->num_ops * sizeof (buf->op[0]));
@ -163,20 +147,31 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
unsigned long
_cairo_path_fixed_hash (const cairo_path_fixed_t *path)
{
unsigned long hash = _CAIRO_HASH_INIT_VALUE;
unsigned long hash = 0;
const cairo_path_buf_t *buf;
int num_points, num_ops;
num_ops = num_points = 0;
cairo_path_foreach_buf_start (buf, path) {
hash = _cairo_hash_bytes (hash,
&path->current_point,
sizeof (path->current_point));
hash = _cairo_hash_bytes (hash,
&path->last_move_point,
sizeof (path->last_move_point));
num_ops = path->buf_head.base.num_ops;
num_points = path->buf_head.base.num_points;
for (buf = path->buf_head.base.next;
buf != NULL;
buf = buf->next)
{
hash = _cairo_hash_bytes (hash, buf->op,
buf->num_ops * sizeof (buf->op[0]));
buf->num_ops * sizeof (buf->op[0]));
hash = _cairo_hash_bytes (hash, buf->points,
buf->num_points * sizeof (buf->points[0]));
buf->num_points * sizeof (buf->points[0]));
num_ops += buf->num_ops;
num_points += buf->num_points;
} cairo_path_foreach_buf_end (buf, path);
}
hash = _cairo_hash_bytes (hash, &num_ops, sizeof (num_ops));
hash = _cairo_hash_bytes (hash, &num_points, sizeof (num_points));
@ -190,11 +185,15 @@ _cairo_path_fixed_size (const cairo_path_fixed_t *path)
const cairo_path_buf_t *buf;
int num_points, num_ops;
num_ops = num_points = 0;
cairo_path_foreach_buf_start (buf, path) {
num_ops = path->buf_head.base.num_ops;
num_points = path->buf_head.base.num_points;
for (buf = path->buf_head.base.next;
buf != NULL;
buf = buf->next)
{
num_ops += buf->num_ops;
num_points += buf->num_points;
} cairo_path_foreach_buf_end (buf, path);
}
return num_ops * sizeof (buf->op[0]) +
num_points * sizeof (buf->points[0]);
@ -213,29 +212,31 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (a == b)
return TRUE;
/* use the flags to quickly differentiate based on contents */
if (a->has_curve_to != b->has_curve_to ||
a->is_region != b->is_region ||
a->is_box != b->is_box)
{
return FALSE;
}
num_ops_a = num_points_a = 0;
if (a != NULL) {
cairo_path_foreach_buf_start (buf_a, a) {
num_ops_a = a->buf_head.base.num_ops;
num_points_a = a->buf_head.base.num_points;
for (buf_a = a->buf_head.base.next;
buf_a != NULL;
buf_a = buf_a->next)
{
num_ops_a += buf_a->num_ops;
num_points_a += buf_a->num_points;
} cairo_path_foreach_buf_end (buf_a, a);
}
}
} else
num_ops_a = num_points_a = 0;
num_ops_b = num_points_b = 0;
if (b != NULL) {
cairo_path_foreach_buf_start (buf_b, b) {
num_ops_b = b->buf_head.base.num_ops;
num_points_b = b->buf_head.base.num_points;
for (buf_b = b->buf_head.base.next;
buf_b != NULL;
buf_b = buf_b->next)
{
num_ops_b += buf_b->num_ops;
num_points_b += buf_b->num_points;
} cairo_path_foreach_buf_end (buf_b, b);
}
}
} else
num_ops_b = num_points_b = 0;
if (num_ops_a == 0 && num_ops_b == 0)
return TRUE;
@ -245,13 +246,13 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
assert (a != NULL && b != NULL);
buf_a = cairo_path_head (a);
buf_a = &a->buf_head.base;
num_points_a = buf_a->num_points;
num_ops_a = buf_a->num_ops;
ops_a = buf_a->op;
points_a = buf_a->points;
buf_b = cairo_path_head (b);
buf_b = &b->buf_head.base;
num_points_b = buf_b->num_points;
num_ops_b = buf_b->num_ops;
ops_b = buf_b->op;
@ -274,8 +275,8 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (num_ops_a || num_points_a)
return FALSE;
buf_a = cairo_path_buf_next (buf_a);
if (buf_a == cairo_path_head (a))
buf_a = buf_a->next;
if (buf_a == NULL)
break;
num_points_a = buf_a->num_points;
@ -292,8 +293,8 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
if (num_ops_b || num_points_b)
return FALSE;
buf_b = cairo_path_buf_next (buf_b);
if (buf_b == cairo_path_head (b))
buf_b = buf_b->next;
if (buf_b == NULL)
break;
num_points_b = buf_b->num_points;
@ -306,6 +307,7 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
return TRUE;
}
cairo_path_fixed_t *
_cairo_path_fixed_create (void)
{
@ -326,14 +328,20 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
{
cairo_path_buf_t *buf;
buf = cairo_path_buf_next (cairo_path_head (path));
while (buf != cairo_path_head (path)) {
buf = path->buf_head.base.next;
while (buf) {
cairo_path_buf_t *this = buf;
buf = cairo_path_buf_next (buf);
buf = buf->next;
_cairo_path_buf_destroy (this);
}
path->buf_head.base.next = NULL;
path->buf_head.base.prev = NULL;
path->buf_tail = &path->buf_head.base;
path->buf_head.base.num_ops = 0;
path->buf_head.base.num_points = 0;
VG (VALGRIND_MAKE_MEM_NOACCESS (path, sizeof (cairo_path_fixed_t)));
path->has_current_point = FALSE;
path->has_curve_to = FALSE;
}
void
@ -343,18 +351,6 @@ _cairo_path_fixed_destroy (cairo_path_fixed_t *path)
free (path);
}
static cairo_path_op_t
_cairo_path_last_op (cairo_path_fixed_t *path)
{
cairo_path_buf_t *buf;
buf = cairo_path_tail (path);
if (buf->num_ops == 0)
return -1;
return buf->op[buf->num_ops - 1];
}
cairo_status_t
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
@ -368,31 +364,21 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
/* If the previous op was also a MOVE_TO, then just change its
* point rather than adding a new op. */
if (_cairo_path_last_op (path) == CAIRO_PATH_OP_MOVE_TO) {
cairo_path_buf_t *buf;
buf = cairo_path_tail (path);
buf->points[buf->num_points - 1] = point;
if (path->buf_tail && path->buf_tail->num_ops &&
path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
{
cairo_point_t *last_move_to_point;
last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1];
*last_move_to_point = point;
} else {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (unlikely (status))
return status;
if (path->has_current_point && path->is_box) {
/* a move-to is first an implicit close */
path->is_box = path->current_point.x == path->last_move_point.x ||
path->current_point.y == path->last_move_point.y;
path->is_region &= path->is_box;
}
if (path->is_region) {
path->is_region = _cairo_fixed_is_integer (x) &&
_cairo_fixed_is_integer (y);
}
}
path->current_point = point;
path->last_move_point = point;
path->has_current_point = TRUE;
path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
@ -408,13 +394,15 @@ _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
if (unlikely (! path->has_current_point))
cairo_fixed_t x, y;
if (! path->has_current_point)
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
return _cairo_path_fixed_move_to (path,
path->current_point.x + dx,
path->current_point.y + dy);
x = path->current_point.x + dx;
y = path->current_point.y + dy;
return _cairo_path_fixed_move_to (path, x, y);
}
cairo_status_t
@ -430,28 +418,21 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
/* When there is not yet a current point, the line_to operation
* becomes a move_to instead. Note: We have to do this by
* explicitly calling into _cairo_path_fixed_move_to to ensure
* explicitly calling into _cairo_path_fixed_line_to to ensure
* that the last_move_point state is updated properly.
*/
if (! path->has_current_point) {
if (! path->has_current_point)
status = _cairo_path_fixed_move_to (path, point.x, point.y);
} else {
else
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (path->is_box) {
path->is_box = path->current_point.x == x ||
path->current_point.y == y;
path->is_region &= path->is_box;
}
if (path->is_region) {
path->is_region = _cairo_fixed_is_integer (x) &&
_cairo_fixed_is_integer (y);
}
}
if (unlikely (status))
return status;
path->current_point = point;
path->has_current_point = TRUE;
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -459,12 +440,15 @@ _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
cairo_fixed_t dy)
{
if (unlikely (! path->has_current_point))
cairo_fixed_t x, y;
if (! path->has_current_point)
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
return _cairo_path_fixed_line_to (path,
path->current_point.x + dx,
path->current_point.y + dy);
x = path->current_point.x + dx;
y = path->current_point.y + dy;
return _cairo_path_fixed_line_to (path, x, y);
}
cairo_status_t
@ -476,19 +460,17 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
cairo_status_t status;
cairo_point_t point[3];
/* make sure subpaths are started properly */
point[0].x = x0; point[0].y = y0;
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
if (! path->has_current_point) {
status = _cairo_path_fixed_move_to (path, x0, y0);
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
&point[0], 1);
if (unlikely (status))
return status;
}
if (x2 == path->current_point.x && y2 == path->current_point.y)
return _cairo_path_fixed_line_to (path, x2, y2);
point[0].x = x0; point[0].y = y0;
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (unlikely (status))
return status;
@ -496,8 +478,6 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
path->current_point = point[2];
path->has_current_point = TRUE;
path->has_curve_to = TRUE;
path->is_box = FALSE;
path->is_region = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@ -508,24 +488,26 @@ _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
cairo_fixed_t dx1, cairo_fixed_t dy1,
cairo_fixed_t dx2, cairo_fixed_t dy2)
{
if (unlikely (! path->has_current_point))
cairo_fixed_t x0, y0;
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
if (! path->has_current_point)
return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT);
if (dx2 == 0 && dy2 == 0) {
return _cairo_path_fixed_line_to (path,
path->current_point.x,
path->current_point.y);
}
x0 = path->current_point.x + dx0;
y0 = path->current_point.y + dy0;
x1 = path->current_point.x + dx1;
y1 = path->current_point.y + dy1;
x2 = path->current_point.x + dx2;
y2 = path->current_point.y + dy2;
return _cairo_path_fixed_curve_to (path,
path->current_point.x + dx0,
path->current_point.y + dy0,
path->current_point.x + dx1,
path->current_point.y + dy1,
path->current_point.x + dx2,
path->current_point.y + dy2);
x0, y0,
x1, y1,
x2, y2);
}
cairo_status_t
@ -540,9 +522,13 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
if (unlikely (status))
return status;
return _cairo_path_fixed_move_to (path,
path->last_move_point.x,
path->last_move_point.y);
status = _cairo_path_fixed_move_to (path,
path->last_move_point.x,
path->last_move_point.y);
if (unlikely (status))
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
@ -560,12 +546,12 @@ _cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
}
static cairo_status_t
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
const cairo_point_t *points,
int num_points)
_cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_path_op_t op,
cairo_point_t *points,
int num_points)
{
cairo_path_buf_t *buf = cairo_path_tail (path);
cairo_path_buf_t *buf = path->buf_tail;
if (buf->num_ops + 1 > buf->buf_size ||
buf->num_points + num_points > 2 * buf->buf_size)
@ -577,32 +563,6 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
_cairo_path_fixed_add_buf (path, buf);
}
if (WATCH_PATH) {
const char *op_str[] = {
"move-to",
"line-to",
"curve-to",
"close-path",
};
char buf[1024];
int len = 0;
int i;
len += snprintf (buf + len, sizeof (buf), "[");
for (i = 0; i < num_points; i++) {
if (i != 0)
len += snprintf (buf + len, sizeof (buf), " ");
len += snprintf (buf + len, sizeof (buf), "(%f, %f)",
_cairo_fixed_to_double (points[i].x),
_cairo_fixed_to_double (points[i].y));
}
len += snprintf (buf + len, sizeof (buf), "]");
fprintf (stderr,
"_cairo_path_fixed_add (%s, %s)\n",
op_str[(int) op], buf);
}
_cairo_path_buf_add_op (buf, op);
_cairo_path_buf_add_points (buf, points, num_points);
@ -613,7 +573,11 @@ static void
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
cairo_path_buf_t *buf)
{
cairo_list_add_tail (&buf->link, &cairo_path_head (path)->link);
buf->next = NULL;
buf->prev = path->buf_tail;
path->buf_tail->next = buf;
path->buf_tail = buf;
}
static cairo_path_buf_t *
@ -629,6 +593,8 @@ _cairo_path_buf_create (int buf_size)
2 * sizeof (cairo_point_t),
sizeof (cairo_path_buf_t));
if (buf) {
buf->next = NULL;
buf->prev = NULL;
buf->num_ops = 0;
buf->num_points = 0;
buf->buf_size = buf_size;
@ -654,16 +620,25 @@ _cairo_path_buf_add_op (cairo_path_buf_t *buf,
}
static void
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
const cairo_point_t *points,
int num_points)
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
cairo_point_t *points,
int num_points)
{
memcpy (buf->points + buf->num_points,
points,
sizeof (points[0]) * num_points);
buf->num_points += num_points;
int i;
for (i=0; i < num_points; i++) {
buf->points[buf->num_points++] = points[i];
}
}
static int const num_args[] =
{
1, /* cairo_path_move_to */
1, /* cairo_path_op_line_to */
3, /* cairo_path_op_curve_to */
0, /* cairo_path_op_close_path */
};
cairo_status_t
_cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
cairo_direction_t dir,
@ -673,22 +648,18 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
cairo_path_fixed_close_path_func_t *close_path,
void *closure)
{
const uint8_t num_args[] = {
1, /* cairo_path_move_to */
1, /* cairo_path_op_line_to */
3, /* cairo_path_op_curve_to */
0, /* cairo_path_op_close_path */
};
cairo_status_t status;
const cairo_path_buf_t *buf, *first;
const cairo_path_buf_t *buf;
cairo_path_op_t op;
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
int step = forward ? 1 : -1;
buf = first = forward ? cairo_path_head (path) : cairo_path_tail (path);
do {
for (buf = forward ? &path->buf_head.base : path->buf_tail;
buf;
buf = forward ? buf->next : buf->prev)
{
cairo_point_t *points;
int start, stop, i;
if (forward) {
start = 0;
stop = buf->num_ops;
@ -699,11 +670,12 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
points = buf->points + buf->num_points;
}
for (i = start; i != stop; i += step) {
cairo_path_op_t op = buf->op[i];
for (i=start; i != stop; i += step) {
op = buf->op[i];
if (! forward)
if (! forward) {
points -= num_args[(int) op];
}
switch (op) {
case CAIRO_PATH_OP_MOVE_TO:
@ -715,19 +687,20 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
case CAIRO_PATH_OP_CURVE_TO:
status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
break;
default:
ASSERT_NOT_REACHED;
case CAIRO_PATH_OP_CLOSE_PATH:
default:
status = (*close_path) (closure);
break;
}
if (unlikely (status))
return status;
if (forward)
if (forward) {
points += num_args[(int) op];
}
}
} while ((buf = forward ? cairo_path_buf_next (buf) : cairo_path_buf_prev (buf)) != first);
}
return CAIRO_STATUS_SUCCESS;
}
@ -736,14 +709,16 @@ static cairo_status_t
_append_move_to (void *closure,
const cairo_point_t *point)
{
return _cairo_path_fixed_move_to (closure, point->x, point->y);
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_move_to (path, point->x, point->y);
}
static cairo_status_t
_append_line_to (void *closure,
const cairo_point_t *point)
{
return _cairo_path_fixed_line_to (closure, point->x, point->y);
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_line_to (path, point->x, point->y);
}
static cairo_status_t
@ -752,16 +727,15 @@ _append_curve_to (void *closure,
const cairo_point_t *p1,
const cairo_point_t *p2)
{
return _cairo_path_fixed_curve_to (closure,
p0->x, p0->y,
p1->x, p1->y,
p2->x, p2->y);
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y);
}
static cairo_status_t
_append_close_path (void *closure)
{
return _cairo_path_fixed_close_path (closure);
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_close_path (path);
}
cairo_status_t
@ -784,10 +758,10 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t scalex,
cairo_fixed_t scaley)
{
cairo_path_buf_t *buf;
cairo_path_buf_t *buf = &path->buf_head.base;
unsigned int i;
cairo_path_foreach_buf_start (buf, path) {
while (buf) {
for (i = 0; i < buf->num_points; i++) {
if (scalex != CAIRO_FIXED_ONE)
buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex);
@ -797,7 +771,9 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley);
buf->points[i].y += offy;
}
} cairo_path_foreach_buf_end (buf, path);
buf = buf->next;
}
}
/**
@ -827,7 +803,8 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
return;
}
cairo_path_foreach_buf_start (buf, path) {
buf = &path->buf_head.base;
while (buf) {
for (i = 0; i < buf->num_points; i++) {
dx = _cairo_fixed_to_double (buf->points[i].x);
dy = _cairo_fixed_to_double (buf->points[i].y);
@ -837,7 +814,9 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
buf->points[i].x = _cairo_fixed_from_double (dx);
buf->points[i].y = _cairo_fixed_from_double (dy);
}
} cairo_path_foreach_buf_end (buf, path);
buf = buf->next;
}
}
cairo_bool_t
@ -850,15 +829,17 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
path->current_point.y != other->current_point.y ||
path->has_current_point != other->has_current_point ||
path->has_curve_to != other->has_curve_to ||
path->is_box != other->is_box ||
path->is_region != other->is_region ||
path->last_move_point.x != other->last_move_point.x ||
path->last_move_point.y != other->last_move_point.y)
return FALSE;
other_buf = cairo_path_head (other);
cairo_path_foreach_buf_start (path_buf, path) {
if (path_buf->num_ops != other_buf->num_ops ||
other_buf = &other->buf_head.base;
for (path_buf = &path->buf_head.base;
path_buf != NULL;
path_buf = path_buf->next)
{
if (other_buf == NULL ||
path_buf->num_ops != other_buf->num_ops ||
path_buf->num_points != other_buf->num_points ||
memcmp (path_buf->op, other_buf->op,
sizeof (cairo_path_op_t) * path_buf->num_ops) != 0 ||
@ -867,9 +848,8 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
{
return FALSE;
}
other_buf = cairo_path_buf_next (other_buf);
} cairo_path_foreach_buf_end (path_buf, path);
other_buf = other_buf->next;
}
return TRUE;
}
@ -937,6 +917,7 @@ _cpf_close_path (void *closure)
return cpf->close_path (cpf->closure);
}
cairo_status_t
_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
cairo_direction_t dir,
@ -948,7 +929,7 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
{
cpf_t flattener;
if (! path->has_curve_to) {
if (!path->has_curve_to) {
return _cairo_path_fixed_interpret (path, dir,
move_to,
line_to,
@ -973,7 +954,7 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
cairo_bool_t
_cairo_path_fixed_is_empty (cairo_path_fixed_t *path)
{
if (cairo_path_head (path)->num_ops == 0)
if (path->buf_head.base.num_ops == 0)
return TRUE;
return FALSE;
@ -986,9 +967,10 @@ cairo_bool_t
_cairo_path_fixed_is_box (cairo_path_fixed_t *path,
cairo_box_t *box)
{
cairo_path_buf_t *buf = cairo_path_head (path);
cairo_path_buf_t *buf = &path->buf_head.base;
if (! path->is_box)
/* We can't have more than one buf for this check */
if (buf->next != NULL)
return FALSE;
/* Do we have the right number of ops? */
@ -1061,12 +1043,11 @@ cairo_bool_t
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
cairo_box_t *box)
{
cairo_path_buf_t *buf;
cairo_path_buf_t *buf = &path->buf_head.base;
if (!_cairo_path_fixed_is_box (path, box))
return FALSE;
buf = cairo_path_head (path);
if (buf->points[0].y == buf->points[1].y)
return TRUE;
@ -1077,7 +1058,7 @@ void
_cairo_path_fixed_iter_init (cairo_path_fixed_iter_t *iter,
cairo_path_fixed_t *path)
{
iter->buf = cairo_path_head (path);
iter->buf = &path->buf_head.base;
iter->n_op = 0;
iter->n_point = 0;
}
@ -1086,7 +1067,7 @@ static cairo_bool_t
_cairo_path_fixed_iter_next_op (cairo_path_fixed_iter_t *iter)
{
if (++iter->n_op >= iter->buf->num_ops) {
iter->buf = cairo_path_buf_next (iter->buf);
iter->buf = iter->buf->next;
iter->n_op = 0;
iter->n_point = 0;
}
@ -1197,3 +1178,91 @@ _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter)
return FALSE;
}
/* Closure for path region testing. Every move_to must be to integer
* coordinates, there must be no curves, and every line_to or
* close_path must represent an axis aligned line to an integer point.
* We're relying on the path interpreter always sending a single
* move_to at the start of any subpath, not receiving having any
* superfluous move_tos, and the path intepreter bailing with our
* first non-successful error. */
typedef struct cairo_path_region_tester {
cairo_point_t last_move_point;
cairo_point_t current_point;
} cprt_t;
static cairo_status_t
_cprt_line_to (void *closure,
const cairo_point_t *p2)
{
cprt_t *self = closure;
cairo_point_t *p1 = &self->current_point;
if (p2->x == p1->x) {
if (_cairo_fixed_is_integer (p2->y)) {
p1->y = p2->y;
return CAIRO_STATUS_SUCCESS;
}
} else if (p2->y == p1->y) {
if (_cairo_fixed_is_integer (p2->x)) {
p1->x = p2->x;
return CAIRO_STATUS_SUCCESS;
}
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_status_t
_cprt_close_path (void *closure)
{
cprt_t *self = closure;
return _cprt_line_to (closure, &self->last_move_point);
}
static cairo_status_t
_cprt_move_to (void *closure,
const cairo_point_t *p)
{
cprt_t *self = closure;
cairo_status_t status;
status = _cprt_close_path (closure);
if (status)
return status;
if (_cairo_fixed_is_integer (p->x) && _cairo_fixed_is_integer (p->y)) {
self->current_point = *p;
self->last_move_point = *p;
return CAIRO_STATUS_SUCCESS;
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
/*
* Check whether the given path is representable as a region.
* That is, if the path contains only axis aligned lines between
* integer coordinates in device space.
*/
cairo_bool_t
_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
{
cprt_t cprt;
if (path->has_curve_to)
return FALSE;
cprt.current_point.x = 0;
cprt.current_point.y = 0;
cprt.last_move_point.x = 0;
cprt.last_move_point.y = 0;
return _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cprt_move_to,
_cprt_line_to,
NULL,
_cprt_close_path,
&cprt) == CAIRO_STATUS_SUCCESS;
}

View File

@ -122,11 +122,11 @@ _cairo_in_fill_add_edge (cairo_in_fill_t *in_fill,
}
/* First check whether the query is on an edge */
if ((p1->x == in_fill->x && p1->y == in_fill->y) ||
(p2->x == in_fill->x && p2->y == in_fill->y) ||
(! (p2->y < in_fill->y || p1->y > in_fill->y ||
(p1->x > in_fill->x && p2->x > in_fill->x) ||
(p1->x < in_fill->x && p2->x < in_fill->x)) &&
if ((p1->x == in_fill->x && p1->x == in_fill->y) ||
(p2->x == in_fill->x && p2->x == in_fill->y) ||
(! (p2->y < in_fill->y || p1->y > in_fill->y) &&
! (p1->x > in_fill->x && p2->x > in_fill->x) &&
! (p1->x < in_fill->x && p2->x < in_fill->x) &&
edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) == 0))
{
in_fill->on_edge = TRUE;

View File

@ -30,7 +30,7 @@
#include "cairoint.h"
static const cairo_solid_pattern_t _cairo_pattern_nil = {
const cairo_solid_pattern_t _cairo_pattern_nil = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
@ -96,23 +96,6 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern,
static void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{
#if HAVE_VALGRIND
switch (type) {
case CAIRO_PATTERN_TYPE_SOLID:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
break;
case CAIRO_PATTERN_TYPE_SURFACE:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
break;
case CAIRO_PATTERN_TYPE_LINEAR:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
break;
case CAIRO_PATTERN_TYPE_RADIAL:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
break;
}
#endif
pattern->type = type;
pattern->status = CAIRO_STATUS_SUCCESS;
@ -185,16 +168,12 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
*dst = *src;
} break;
case CAIRO_PATTERN_TYPE_SURFACE: {
cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
*dst = *src;
cairo_surface_reference (dst->surface);
} break;
@ -204,12 +183,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
cairo_status_t status;
if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
} else {
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
}
status = _cairo_gradient_pattern_init_copy (dst, src);
if (unlikely (status))
return status;
@ -224,37 +197,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
int size;
assert (other->status == CAIRO_STATUS_SUCCESS);
switch (other->type) {
default:
ASSERT_NOT_REACHED;
case CAIRO_PATTERN_TYPE_SOLID:
size = sizeof (cairo_solid_pattern_t);
break;
case CAIRO_PATTERN_TYPE_SURFACE:
size = sizeof (cairo_surface_pattern_t);
break;
case CAIRO_PATTERN_TYPE_LINEAR:
size = sizeof (cairo_linear_pattern_t);
break;
case CAIRO_PATTERN_TYPE_RADIAL:
size = sizeof (cairo_radial_pattern_t);
break;
}
memcpy (pattern, other, size);
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
_cairo_user_data_array_init (&pattern->user_data);
}
cairo_status_t
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
@ -308,40 +250,6 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
free (gradient->stops);
} break;
}
#if HAVE_VALGRIND
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
break;
case CAIRO_PATTERN_TYPE_SURFACE:
VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
break;
case CAIRO_PATTERN_TYPE_LINEAR:
VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
break;
case CAIRO_PATTERN_TYPE_RADIAL:
VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
break;
}
#endif
}
void
_cairo_pattern_fini_snapshot (cairo_pattern_t *pattern)
{
/* XXX this is quite ugly, but currently necessary to break the circular
* references with snapshot-cow and the meta-surface.
* This operation remains safe only whilst _cairo_surface_snapshot() is
* not public...
*/
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) pattern;
cairo_surface_finish (spat->surface);
}
_cairo_pattern_fini (pattern);
}
cairo_status_t
@ -456,92 +364,10 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
/* We use a small freed pattern cache here, because we don't want to
* constantly reallocate simple colors. */
#define MAX_PATTERN_CACHE_SIZE 4
typedef struct {
void *pool[MAX_PATTERN_CACHE_SIZE];
int top;
} freed_pool_t;
static freed_pool_t freed_pattern_pool[4];
static void *
_atomic_fetch (void **slot)
{
return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
}
static cairo_bool_t
_atomic_store (void **slot, void *pattern)
{
return _cairo_atomic_ptr_cmpxchg (slot, NULL, pattern) == NULL;
}
static void *
_freed_pattern_get (freed_pool_t *pool)
{
cairo_pattern_t *pattern;
int i;
i = pool->top - 1;
if (i < 0)
i = 0;
pattern = _atomic_fetch (&pool->pool[i]);
if (pattern != NULL) {
pool->top = i;
return pattern;
}
/* either empty or contended */
for (i = ARRAY_LENGTH (pool->pool); i--;) {
pattern = _atomic_fetch (&pool->pool[i]);
if (pattern != NULL) {
pool->top = i;
return pattern;
}
}
/* empty */
pool->top = 0;
return NULL;
}
static void
_freed_pattern_put (freed_pool_t *pool,
cairo_pattern_t *pattern)
{
int i = pool->top;
if (_atomic_store (&pool->pool[i], pattern)) {
pool->top = i + 1;
return;
}
/* either full or contended */
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
if (_atomic_store (&pool->pool[i], pattern)) {
pool->top = i + 1;
return;
}
}
/* full */
pool->top = ARRAY_LENGTH (pool->pool);
free (pattern);
}
static void
_freed_patterns_reset (void)
{
int i, j;
for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++) {
freed_pool_t *pool = &freed_pattern_pool[i];
for (j = 0; j < ARRAY_LENGTH (pool->pool); j++) {
free (pool->pool[j]);
pool->pool[j] = NULL;
}
}
}
static struct {
cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
int size;
} solid_pattern_cache;
cairo_pattern_t *
_cairo_pattern_create_solid (const cairo_color_t *color,
@ -549,8 +375,17 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
{
cairo_solid_pattern_t *pattern = NULL;
pattern =
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
if (solid_pattern_cache.size) {
int i = --solid_pattern_cache.size %
ARRAY_LENGTH (solid_pattern_cache.patterns);
pattern = solid_pattern_cache.patterns[i];
solid_pattern_cache.patterns[i] = NULL;
}
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
if (unlikely (pattern == NULL)) {
/* None cached, need to create a new pattern. */
pattern = malloc (sizeof (cairo_solid_pattern_t));
@ -566,7 +401,24 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
return &pattern->base;
}
cairo_pattern_t *
static void
_cairo_pattern_reset_solid_pattern_cache (void)
{
int i;
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
if (solid_pattern_cache.patterns[i])
free (solid_pattern_cache.patterns[i]);
solid_pattern_cache.patterns[i] = NULL;
}
solid_pattern_cache.size = 0;
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
}
static const cairo_pattern_t *
_cairo_pattern_create_in_error (cairo_status_t status)
{
cairo_pattern_t *pattern;
@ -686,16 +538,12 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
}
if (surface->status)
return _cairo_pattern_create_in_error (surface->status);
return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
pattern =
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
pattern = malloc (sizeof (cairo_surface_pattern_t));
if (unlikely (pattern == NULL)) {
pattern = malloc (sizeof (cairo_surface_pattern_t));
if (unlikely (pattern == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
}
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
@ -738,14 +586,10 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
{
cairo_linear_pattern_t *pattern;
pattern =
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
pattern = malloc (sizeof (cairo_linear_pattern_t));
if (unlikely (pattern == NULL)) {
pattern = malloc (sizeof (cairo_linear_pattern_t));
if (unlikely (pattern == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
@ -790,14 +634,10 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
{
cairo_radial_pattern_t *pattern;
pattern =
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
pattern = malloc (sizeof (cairo_radial_pattern_t));
if (unlikely (pattern == NULL)) {
pattern = malloc (sizeof (cairo_radial_pattern_t));
if (unlikely (pattern == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
@ -881,8 +721,6 @@ slim_hidden_def (cairo_pattern_status);
void
cairo_pattern_destroy (cairo_pattern_t *pattern)
{
cairo_pattern_type_t type;
if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
return;
@ -892,11 +730,26 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
return;
type = pattern->type;
_cairo_pattern_fini (pattern);
/* maintain a small cache of freed patterns */
_freed_pattern_put (&freed_pattern_pool[type], pattern);
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
int i;
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
i = solid_pattern_cache.size++ %
ARRAY_LENGTH (solid_pattern_cache.patterns);
/* swap an old pattern for this 'cache-hot' pattern */
if (solid_pattern_cache.patterns[i])
free (solid_pattern_cache.patterns[i]);
solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern;
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
} else {
free (pattern);
}
}
slim_hidden_def (cairo_pattern_destroy);
@ -1254,7 +1107,7 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
*
* <informalexample><programlisting>
* cairo_set_source_surface (cr, image, x, y);
* cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
* cairo_pattern_set_filter (cairo_get_source (cr), %CAIRO_FILTER_NEAREST);
* </programlisting></informalexample>
**/
void
@ -1941,7 +1794,6 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
int y,
unsigned int width,
unsigned int height,
unsigned int flags,
cairo_surface_t **out,
cairo_surface_attributes_t *attr)
{
@ -2003,9 +1855,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
* images such that the new image, when repeated, has the same effect
* of reflecting the original pattern.
*/
if (flags & CAIRO_PATTERN_ACQUIRE_NO_REFLECT &&
attr->extend == CAIRO_EXTEND_REFLECT)
{
if (attr->extend == CAIRO_EXTEND_REFLECT) {
cairo_t *cr;
cairo_surface_t *src;
int w, h;
@ -2122,28 +1972,13 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
/* Never acquire a larger area than the source itself */
is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
} else {
int trim = 0;
if (sampled_area.x >= extents.x &&
sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
{
/* source is horizontally contained within extents, trim */
extents.x = sampled_area.x;
extents.width = sampled_area.width;
trim |= 0x1;
}
if (sampled_area.y >= extents.y &&
sampled_area.y >= extents.y &&
sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width &&
sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
{
/* source is vertically contained within extents, trim */
extents.y = sampled_area.y;
extents.height = sampled_area.height;
trim |= 0x2;
}
if (trim == 0x3) {
/* source is wholly contained within extents, drop the REPEAT */
extents = sampled_area;
attr->extend = CAIRO_EXTEND_NONE;
}
@ -2231,7 +2066,6 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
int y,
unsigned int width,
unsigned int height,
unsigned int flags,
cairo_surface_t **surface_out,
cairo_surface_attributes_t *attributes)
{
@ -2321,9 +2155,7 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
status = _cairo_pattern_acquire_surface_for_surface (src, dst,
content,
x, y,
width, height,
flags,
x, y, width, height,
surface_out,
attributes);
} break;
@ -2362,7 +2194,6 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
int mask_y,
unsigned int width,
unsigned int height,
unsigned int flags,
cairo_surface_t **src_out,
cairo_surface_t **mask_out,
cairo_surface_attributes_t *src_attributes,
@ -2403,7 +2234,6 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
src_content,
src_x, src_y,
width, height,
flags,
src_out, src_attributes);
if (unlikely (status))
goto BAIL;
@ -2417,7 +2247,6 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
CAIRO_CONTENT_ALPHA,
mask_x, mask_y,
width, height,
flags,
mask_out, mask_attributes);
if (unlikely (status))
_cairo_pattern_release_surface (src, *src_out, src_attributes);
@ -2580,10 +2409,7 @@ static unsigned long
_cairo_surface_pattern_hash (unsigned long hash,
const cairo_pattern_t *pattern)
{
const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
hash ^= surface->surface->unique_id;
/* XXX requires cow-snapshots */
return hash;
}
@ -2737,10 +2563,8 @@ static cairo_bool_t
_cairo_surface_pattern_equal (const cairo_pattern_t *A,
const cairo_pattern_t *B)
{
const cairo_surface_pattern_t *a = (cairo_surface_pattern_t *) A;
const cairo_surface_pattern_t *b = (cairo_surface_pattern_t *) B;
return a->surface->unique_id == b->surface->unique_id;
/* XXX requires cow-snapshots */
return FALSE;
}
cairo_bool_t
@ -3031,6 +2855,6 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
void
_cairo_pattern_reset_static_data (void)
{
_freed_patterns_reset ();
_cairo_pattern_reset_solid_pattern_cache ();
_cairo_pattern_reset_solid_surface_cache ();
}

View File

@ -60,20 +60,6 @@ typedef struct _cairo_pdf_group_resources {
cairo_array_t fonts;
} cairo_pdf_group_resources_t;
typedef struct _cairo_pdf_source_surface_entry {
cairo_hash_entry_t base;
unsigned int id;
cairo_bool_t interpolate;
cairo_pdf_resource_t surface_res;
int width;
int height;
} cairo_pdf_source_surface_entry_t;
typedef struct _cairo_pdf_source_surface {
cairo_surface_t *surface;
cairo_pdf_source_surface_entry_t *hash_entry;
} cairo_pdf_source_surface_t;
typedef struct _cairo_pdf_pattern {
double width;
double height;
@ -132,9 +118,7 @@ struct _cairo_pdf_surface {
cairo_array_t pages;
cairo_array_t rgb_linear_functions;
cairo_array_t alpha_linear_functions;
cairo_array_t page_patterns;
cairo_array_t page_surfaces;
cairo_hash_table_t *all_surfaces;
cairo_array_t patterns;
cairo_array_t smask_groups;
cairo_array_t knockout_group;

View File

@ -194,9 +194,6 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
static cairo_status_t
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
static cairo_bool_t
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
static const cairo_surface_backend_t cairo_pdf_surface_backend;
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
@ -271,30 +268,23 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
_cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
_cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
_cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
_cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
_cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
if (unlikely (surface->all_surfaces == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL0;
}
_cairo_pdf_group_resources_init (&surface->resources);
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
if (! surface->font_subsets) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL1;
goto BAIL0;
}
surface->next_available_resource.id = 1;
surface->pages_resource = _cairo_pdf_surface_new_object (surface);
if (surface->pages_resource.id == 0) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL2;
goto BAIL1;
}
surface->pdf_version = CAIRO_PDF_VERSION_1_5;
@ -334,10 +324,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
return surface->paginated_surface;
}
BAIL2:
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
BAIL1:
_cairo_hash_table_destroy (surface->all_surfaces);
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
BAIL0:
_cairo_array_fini (&surface->objects);
free (surface);
@ -583,22 +571,14 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
{
int i, size;
cairo_pdf_pattern_t *pattern;
cairo_pdf_source_surface_t *src_surface;
cairo_pdf_smask_group_t *group;
size = _cairo_array_num_elements (&surface->page_patterns);
size = _cairo_array_num_elements (&surface->patterns);
for (i = 0; i < size; i++) {
pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i);
cairo_pattern_destroy (pattern->pattern);
}
_cairo_array_truncate (&surface->page_patterns, 0);
size = _cairo_array_num_elements (&surface->page_surfaces);
for (i = 0; i < size; i++) {
src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
cairo_surface_destroy (src_surface->surface);
}
_cairo_array_truncate (&surface->page_surfaces, 0);
_cairo_array_truncate (&surface->patterns, 0);
size = _cairo_array_num_elements (&surface->smask_groups);
for (i = 0; i < size; i++) {
@ -881,176 +861,6 @@ _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
return _cairo_array_append (&surface->smask_groups, &group);
}
static cairo_bool_t
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
{
const cairo_pdf_source_surface_entry_t *a = key_a;
const cairo_pdf_source_surface_entry_t *b = key_b;
return (a->id == b->id) && (a->interpolate == b->interpolate);
}
static void
_cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
{
key->base.hash = key->id;
}
static cairo_int_status_t
_get_jpx_image_info (cairo_surface_t *source,
cairo_image_info_t *info,
const unsigned char **mime_data,
unsigned int *mime_data_length)
{
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
mime_data, mime_data_length);
if (*mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
}
static cairo_int_status_t
_get_jpeg_image_info (cairo_surface_t *source,
cairo_image_info_t *info,
const unsigned char **mime_data,
unsigned int *mime_data_length)
{
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
mime_data, mime_data_length);
if (*mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
}
static cairo_status_t
_get_source_surface_size (cairo_surface_t *source,
int *width,
int *height)
{
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status;
cairo_image_info_t info;
const unsigned char *mime_data;
unsigned int mime_data_length;
if (_cairo_surface_is_meta (source)) {
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (source, &extents);
if (unlikely (status))
return status;
*width = extents.width;
*height = extents.height;
return status;
}
status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
if (status == CAIRO_STATUS_SUCCESS) {
*width = info.width;
*height = info.height;
} else if (_cairo_status_is_error (status)) {
return status;
}
status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
if (status == CAIRO_STATUS_SUCCESS) {
*width = info.width;
*height = info.height;
} else if (_cairo_status_is_error (status)) {
return status;
}
status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
if (unlikely (status))
return status;
*width = image->width;
*height = image->height;
_cairo_surface_release_source_image (source, image, image_extra);
return status;
}
static cairo_status_t
_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *source,
cairo_filter_t filter,
cairo_pdf_resource_t *surface_res,
int *width,
int *height)
{
cairo_pdf_source_surface_t src_surface;
cairo_pdf_source_surface_entry_t surface_key;
cairo_pdf_source_surface_entry_t *surface_entry;
cairo_status_t status;
cairo_bool_t interpolate;
switch (filter) {
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
interpolate = TRUE;
break;
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
case CAIRO_FILTER_GAUSSIAN:
interpolate = FALSE;
break;
}
surface_key.id = source->unique_id;
surface_key.interpolate = interpolate;
_cairo_pdf_source_surface_init_key (&surface_key);
surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
if (surface_entry) {
*surface_res = surface_entry->surface_res;
*width = surface_entry->width;
*height = surface_entry->height;
return CAIRO_STATUS_SUCCESS;
}
surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
if (surface_entry == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
surface_entry->id = surface_key.id;
surface_entry->interpolate = interpolate;
_cairo_pdf_source_surface_init_key (surface_entry);
src_surface.hash_entry = surface_entry;
src_surface.surface = cairo_surface_reference (source);
surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
if (surface_entry->surface_res.id == 0) {
free (surface_entry);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
status = _get_source_surface_size (source, &surface_entry->width,
&surface_entry->height);
status = _cairo_array_append (&surface->page_surfaces, &src_surface);
if (unlikely (status)) {
free (surface_entry);
return status;
}
status = _cairo_hash_table_insert (surface->all_surfaces,
&surface_entry->base);
*surface_res = surface_entry->surface_res;
*width = surface_entry->width;
*height = surface_entry->height;
return status;
}
static cairo_status_t
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
@ -1125,7 +935,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
*pattern_res = pdf_pattern.pattern_res;
*gstate_res = pdf_pattern.gstate_res;
status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
status = _cairo_array_append (&surface->patterns, &pdf_pattern);
if (unlikely (status)) {
cairo_pattern_destroy (pdf_pattern.pattern);
return status;
@ -1395,7 +1205,6 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
static cairo_status_t
_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *resource,
cairo_bool_t is_form)
{
cairo_status_t status;
@ -1410,7 +1219,7 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
if (is_form) {
status =
_cairo_pdf_surface_open_stream (surface,
resource,
NULL,
surface->compress_content,
" /Type /XObject\n"
" /Subtype /Form\n"
@ -1427,7 +1236,7 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
} else {
status =
_cairo_pdf_surface_open_stream (surface,
resource,
NULL,
surface->compress_content,
NULL);
}
@ -1475,17 +1284,7 @@ _cairo_pdf_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return cairo_meta_surface_create (content, width, height);
}
static void
_cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
{
cairo_pdf_source_surface_entry_t *surface_entry = entry;
cairo_hash_table_t *patterns = closure;
_cairo_hash_table_remove (patterns, &surface_entry->base);
free (surface_entry);
return _cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -1567,12 +1366,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
_cairo_array_fini (&surface->pages);
_cairo_array_fini (&surface->rgb_linear_functions);
_cairo_array_fini (&surface->alpha_linear_functions);
_cairo_array_fini (&surface->page_patterns);
_cairo_array_fini (&surface->page_surfaces);
_cairo_hash_table_foreach (surface->all_surfaces,
_cairo_pdf_source_surface_entry_pluck,
surface->all_surfaces);
_cairo_hash_table_destroy (surface->all_surfaces);
_cairo_array_fini (&surface->patterns);
_cairo_array_fini (&surface->smask_groups);
_cairo_array_fini (&surface->fonts);
_cairo_array_fini (&surface->knockout_group);
@ -1624,7 +1418,7 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_pdf_surface_t *surface = abstract_surface;
surface->has_fallback_images = has_fallbacks;
status = _cairo_pdf_surface_open_content_stream (surface, NULL, has_fallbacks);
status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks);
if (unlikely (status))
return status;
@ -1744,7 +1538,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
static cairo_status_t
_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
cairo_image_surface_t *image,
cairo_pdf_resource_t *image_res,
cairo_pdf_resource_t *image_ret,
cairo_filter_t filter)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@ -1842,7 +1636,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
if (need_smask)
status = _cairo_pdf_surface_open_stream (surface,
image_res,
NULL,
TRUE,
IMAGE_DICTIONARY
" /SMask %d 0 R\n",
@ -1851,7 +1645,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
smask.id);
else
status = _cairo_pdf_surface_open_stream (surface,
image_res,
NULL,
TRUE,
IMAGE_DICTIONARY,
image->width, image->height,
@ -1861,8 +1655,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
#undef IMAGE_DICTIONARY
if (image_res == NULL)
*image_res = surface->pdf_stream.self;
*image_ret = surface->pdf_stream.self;
_cairo_output_stream_write (surface->output, rgb, rgb_size);
status = _cairo_pdf_surface_close_stream (surface);
@ -1875,7 +1668,9 @@ CLEANUP:
static cairo_int_status_t
_cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
cairo_surface_t *source,
cairo_pdf_resource_t res)
cairo_pdf_resource_t *res,
int *width,
int *height)
{
cairo_status_t status;
const unsigned char *mime_data;
@ -1895,7 +1690,7 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
return status;
status = _cairo_pdf_surface_open_stream (surface,
&res,
NULL,
FALSE,
" /Type /XObject\n"
" /Subtype /Image\n"
@ -1908,17 +1703,23 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
if (status)
return status;
*res = surface->pdf_stream.self;
_cairo_output_stream_write (surface->output, mime_data, mime_data_length);
_cairo_output_stream_printf (surface->output, "\n");
status = _cairo_pdf_surface_close_stream (surface);
*width = info.width;
*height = info.height;
return status;
}
static cairo_int_status_t
_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
cairo_surface_t *source,
cairo_pdf_resource_t res)
cairo_pdf_resource_t *res,
int *width,
int *height)
{
cairo_status_t status;
const unsigned char *mime_data;
@ -1940,7 +1741,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_pdf_surface_open_stream (surface,
&res,
NULL,
FALSE,
" /Type /XObject\n"
" /Subtype /Image\n"
@ -1956,54 +1757,25 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
*res = surface->pdf_stream.self;
_cairo_output_stream_write (surface->output, mime_data, mime_data_length);
_cairo_output_stream_printf (surface->output, "\n");
status = _cairo_pdf_surface_close_stream (surface);
*width = info.width;
*height = info.height;
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *source,
cairo_pdf_resource_t resource,
cairo_bool_t interpolate)
{
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status;
status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
if (unlikely (status))
return status;
status = _cairo_pdf_surface_emit_image (surface, image,
&resource, interpolate);
if (unlikely (status))
goto BAIL;
BAIL:
_cairo_surface_release_source_image (source, image, image_extra);
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern,
cairo_pdf_resource_t *resource,
int *width,
int *height,
int *origin_x,
int *origin_y)
cairo_pdf_pattern_t *pdf_pattern,
cairo_pdf_resource_t *resource,
int *width,
int *height,
int *origin_x,
int *origin_y)
{
cairo_image_surface_t *image;
cairo_surface_t *pad_image;
@ -2012,73 +1784,63 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
int x = 0;
int y = 0;
cairo_bool_t interpolate;
status = _cairo_pdf_surface_emit_jpx_image (surface, pattern->surface,
resource, width, height);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
status = _cairo_pdf_surface_emit_jpeg_image (surface, pattern->surface,
resource, width, height);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
if (unlikely (status))
return status;
return status;
pad_image = &image->base;
if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
cairo_box_t box;
cairo_rectangle_int_t rect;
cairo_surface_pattern_t pad_pattern;
cairo_box_t box;
cairo_rectangle_int_t rect;
cairo_surface_pattern_t pad_pattern;
/* get the operation extents in pattern space */
_cairo_box_from_rectangle (&box, &pdf_pattern->extents);
_cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
_cairo_box_round_to_rectangle (&box, &rect);
x = -rect.x;
y = -rect.y;
/* get the operation extents in pattern space */
_cairo_box_from_rectangle (&box, &pdf_pattern->extents);
_cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
_cairo_box_round_to_rectangle (&box, &rect);
x = -rect.x;
y = -rect.y;
pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
rect.width,
rect.height);
if (pad_image->status) {
status = pad_image->status;
goto BAIL;
}
pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
rect.width,
rect.height);
if (pad_image->status) {
status = pad_image->status;
goto BAIL;
}
_cairo_pattern_init_for_surface (&pad_pattern, &image->base);
cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
pad_pattern.base.extend = CAIRO_EXTEND_PAD;
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pad_pattern.base,
NULL,
pad_image,
0, 0,
0, 0,
0, 0,
rect.width,
rect.height);
_cairo_pattern_fini (&pad_pattern.base);
if (unlikely (status))
goto BAIL;
}
switch (pdf_pattern->pattern->filter) {
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
interpolate = TRUE;
break;
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
case CAIRO_FILTER_GAUSSIAN:
interpolate = FALSE;
break;
}
*resource = _cairo_pdf_surface_new_object (surface);
if (resource->id == 0) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL;
_cairo_pattern_init_for_surface (&pad_pattern, &image->base);
cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
pad_pattern.base.extend = CAIRO_EXTEND_PAD;
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pad_pattern.base,
NULL,
pad_image,
0, 0,
0, 0,
0, 0,
rect.width,
rect.height);
_cairo_pattern_fini (&pad_pattern.base);
if (unlikely (status))
goto BAIL;
}
status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
resource, interpolate);
resource, pattern->base.filter);
if (unlikely (status))
goto BAIL;
goto BAIL;
*width = ((cairo_image_surface_t *)pad_image)->width;
*height = ((cairo_image_surface_t *)pad_image)->height;
@ -2087,18 +1849,17 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
BAIL:
if (pad_image != &image->base)
cairo_surface_destroy (pad_image);
cairo_surface_destroy (pad_image);
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *meta_surface,
cairo_pdf_resource_t resource)
cairo_pdf_resource_t *resource)
{
double old_width, old_height;
cairo_paginated_mode_t old_paginated_mode;
@ -2124,10 +1885,11 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
*/
surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
_cairo_pdf_group_resources_clear (&surface->resources);
status = _cairo_pdf_surface_open_content_stream (surface, &resource, TRUE);
status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
if (unlikely (status))
return status;
*resource = surface->content;
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (unlikely (status))
@ -2160,32 +1922,17 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *src_surface)
{
if (_cairo_surface_is_meta (src_surface->surface)) {
return _cairo_pdf_surface_emit_meta_surface (surface,
src_surface->surface,
src_surface->hash_entry->surface_res);
} else {
return _cairo_pdf_surface_emit_image_surface (surface,
src_surface->surface,
src_surface->hash_entry->surface_res,
src_surface->hash_entry->interpolate);
}
}
static cairo_status_t
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern)
{
cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
cairo_status_t status;
cairo_pdf_resource_t pattern_resource = {0};
cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
cairo_matrix_t cairo_p2d, pdf_p2d;
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
double xstep, ystep;
cairo_rectangle_int_t surface_extents;
int pattern_width = 0; /* squelch bogus compiler warning */
int pattern_height = 0; /* squelch bogus compiler warning */
int origin_x = 0; /* squelch bogus compiler warning */
@ -2193,26 +1940,35 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
int bbox_x, bbox_y;
char draw_surface[200];
if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD &&
! _cairo_surface_is_meta (pattern->surface))
{
status = _cairo_pdf_surface_emit_padded_image_surface (surface,
pdf_pattern,
&pattern_resource,
&pattern_width,
&pattern_height,
&origin_x,
&origin_y);
}
else
{
status = _cairo_pdf_surface_add_source_surface (surface,
pattern->surface,
pdf_pattern->pattern->filter,
if (_cairo_surface_is_meta (pattern->surface)) {
cairo_surface_t *meta_surface = pattern->surface;
cairo_rectangle_int_t pattern_extents;
status = _cairo_pdf_surface_emit_meta_surface (surface,
meta_surface,
&pattern_resource);
if (unlikely (status))
return status;
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
if (unlikely (status))
return status;
pattern_width = pattern_extents.width;
pattern_height = pattern_extents.height;
} else {
status = _cairo_pdf_surface_emit_image_surface (surface,
pdf_pattern,
&pattern_resource,
&pattern_width,
&pattern_height);
&pattern_height,
&origin_x,
&origin_y);
if (unlikely (status))
return status;
}
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
if (unlikely (status))
return status;
@ -2298,7 +2054,10 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
cairo_matrix_init_identity (&pdf_p2d);
cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
@ -4686,10 +4445,8 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
group->height);
/* _mask is a special case that requires two groups - source
* and mask as well as a smask and gstate dictionary */
if (group->operation == PDF_MASK) {
status = _cairo_pdf_surface_write_mask_group (surface, group);
goto RESTORE_SIZE;
}
if (group->operation == PDF_MASK)
return _cairo_pdf_surface_write_mask_group (surface, group);
status = _cairo_pdf_surface_open_group (surface, &group->group_res);
if (unlikely (status))
@ -4741,7 +4498,6 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_close_group (surface, NULL);
RESTORE_SIZE:
_cairo_pdf_surface_set_size_internal (surface,
old_width,
old_height);
@ -4754,8 +4510,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
{
cairo_pdf_pattern_t pattern;
cairo_pdf_smask_group_t *group;
cairo_pdf_source_surface_t src_surface;
int pattern_index, group_index, surface_index;
int pattern_index, group_index;
cairo_status_t status;
/* Writing out PDF_MASK groups will cause additional smask groups
@ -4767,8 +4522,7 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
*/
pattern_index = 0;
group_index = 0;
surface_index = 0;
while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) ||
(group_index < _cairo_array_num_elements (&surface->smask_groups)))
{
for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
@ -4778,19 +4532,12 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
return status;
}
for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
_cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) {
_cairo_array_copy_element (&surface->patterns, pattern_index, &pattern);
status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
if (unlikely (status))
return status;
}
for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
_cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
if (unlikely (status))
return status;
}
}
return CAIRO_STATUS_SUCCESS;
@ -4831,7 +4578,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
return status;
_cairo_pdf_group_resources_clear (&surface->resources);
status = _cairo_pdf_surface_open_content_stream (surface, NULL, FALSE);
status = _cairo_pdf_surface_open_content_stream (surface, FALSE);
if (unlikely (status))
return status;
@ -5088,7 +4835,7 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
return status;
_cairo_pdf_group_resources_clear (&surface->resources);
return _cairo_pdf_surface_open_content_stream (surface, NULL, TRUE);
return _cairo_pdf_surface_open_content_stream (surface, TRUE);
}
static cairo_int_status_t

View File

@ -58,8 +58,6 @@ _cairo_pen_init (cairo_pen_t *pen,
if (CAIRO_INJECT_FAULT ())
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t)));
pen->radius = radius;
pen->tolerance = tolerance;
@ -105,15 +103,13 @@ _cairo_pen_fini (cairo_pen_t *pen)
if (pen->vertices != pen->vertices_embedded)
free (pen->vertices);
VG (VALGRIND_MAKE_MEM_NOACCESS (pen, sizeof (cairo_pen_t)));
pen->vertices = pen->vertices_embedded;
pen->num_vertices = 0;
}
cairo_status_t
_cairo_pen_init_copy (cairo_pen_t *pen, const cairo_pen_t *other)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t)));
*pen = *other;
if (CAIRO_INJECT_FAULT ())

View File

@ -39,8 +39,6 @@
void
_cairo_polygon_init (cairo_polygon_t *polygon)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (polygon, sizeof (cairo_polygon_t)));
polygon->status = CAIRO_STATUS_SUCCESS;
polygon->num_edges = 0;
@ -56,8 +54,6 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
{
if (polygon->edges != polygon->edges_embedded)
free (polygon->edges);
VG (VALGRIND_MAKE_MEM_NOACCESS (polygon, sizeof (cairo_polygon_t)));
}
/* make room for at least one more edge */

View File

@ -1294,7 +1294,7 @@ _cairo_ps_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return cairo_meta_surface_create (content, width, height);
return _cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -1896,7 +1896,6 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
return image->base.status;
switch (filter) {
default:
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:

View File

@ -749,7 +749,7 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
return ffont->cgFont;
}
#ifndef __LP64__
/*
* compat with old ATSUI backend
*/
@ -789,4 +789,3 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
{
return cairo_quartz_font_face_create_for_atsu_font_id (font_id);
}
#endif

View File

@ -1717,23 +1717,6 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_quartz_surface_snapshot (void *abstract_surface)
{
cairo_int_status_t status;
cairo_quartz_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
if (surface->imageSurfaceEquiv)
return NULL;
status = _cairo_quartz_get_image (surface, &image);
if (unlikely (status))
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
return &image->base;
}
static void
_cairo_quartz_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
@ -2717,7 +2700,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
NULL, /* show_glyphs */
#endif
_cairo_quartz_surface_snapshot,
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL /* fill_stroke */

View File

@ -66,10 +66,8 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
cairo_public cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
#ifndef __LP64__
cairo_public cairo_font_face_t *
cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id);
#endif
#endif /* CAIRO_HAS_QUARTZ_FONT */

View File

@ -79,8 +79,6 @@ _cairo_region_set_error (cairo_region_t *region,
void
_cairo_region_init (cairo_region_t *region)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
region->status = CAIRO_STATUS_SUCCESS;
pixman_region32_init (&region->rgn);
}
@ -89,8 +87,6 @@ void
_cairo_region_init_rectangle (cairo_region_t *region,
const cairo_rectangle_int_t *rectangle)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
region->status = CAIRO_STATUS_SUCCESS;
pixman_region32_init_rect (&region->rgn,
rectangle->x, rectangle->y,
@ -101,7 +97,6 @@ void
_cairo_region_fini (cairo_region_t *region)
{
pixman_region32_fini (&region->rgn);
VG (VALGRIND_MAKE_MEM_NOACCESS (region, sizeof (cairo_region_t)));
}
/**
@ -134,51 +129,6 @@ cairo_region_create (void)
}
slim_hidden_def (cairo_region_create);
cairo_region_t *
cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
int count)
{
pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
pixman_box32_t *pboxes = stack_pboxes;
cairo_region_t *region;
int i;
region = _cairo_malloc (sizeof (cairo_region_t));
if (!region)
return (cairo_region_t *)&_cairo_region_nil;
region->status = CAIRO_STATUS_SUCCESS;
if (count > ARRAY_LENGTH (stack_pboxes)) {
pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
if (unlikely (pboxes == NULL)) {
free (region);
return (cairo_region_t *)&_cairo_region_nil;
}
}
for (i = 0; i < count; i++) {
pboxes[i].x1 = rects[i].x;
pboxes[i].y1 = rects[i].y;
pboxes[i].x2 = rects[i].x + rects[i].width;
pboxes[i].y2 = rects[i].y + rects[i].height;
}
if (! pixman_region32_init_rects (&region->rgn, pboxes, count)) {
free (region);
region = (cairo_region_t *)&_cairo_region_nil;
}
if (pboxes != stack_pboxes)
free (pboxes);
return region;
}
slim_hidden_def (cairo_region_create_rectangles);
/**
* cairo_region_create_rectangle:
* @rectangle: a #cairo_rectangle_int_t

View File

@ -92,9 +92,9 @@ struct _cairo_scaled_font {
cairo_matrix_t ctm; /* user space => device space */
cairo_font_options_t options;
unsigned int placeholder : 1; /* protected by fontmap mutex */
unsigned int holdover : 1;
unsigned int finished : 1;
cairo_bool_t placeholder; /* protected by fontmap mutex */
cairo_bool_t finished;
/* "live" scaled_font members */
cairo_matrix_t scale; /* font space => device space */

View File

@ -230,13 +230,11 @@ _cairo_sub_fonts_equal (const void *key_a, const void *key_b)
{
const cairo_sub_font_t *sub_font_a = key_a;
const cairo_sub_font_t *sub_font_b = key_b;
cairo_scaled_font_t *a = sub_font_a->scaled_font;
cairo_scaled_font_t *b = sub_font_b->scaled_font;
if (sub_font_a->is_scaled)
return a == b;
return sub_font_a->scaled_font == sub_font_b->scaled_font;
else
return a->font_face == b->font_face || a->original_font_face == b->original_font_face;
return sub_font_a->scaled_font->font_face == sub_font_b->scaled_font->font_face;
}
static void

View File

@ -64,7 +64,7 @@
/* XXX: This number is arbitrary---we've never done any measurement of this. */
#define MAX_GLYPH_PAGES_CACHED 256
static cairo_cache_t cairo_scaled_glyph_page_cache;
static cairo_cache_t *cairo_scaled_glyph_page_cache;
#define CAIRO_SCALED_GLYPH_PAGE_SIZE 32
struct _cairo_scaled_glyph_page {
@ -218,7 +218,6 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT} ,
FALSE, /* placeholder */
FALSE, /* holdover */
TRUE, /* finished */
{ 1., 0., 0., 1., 0, 0}, /* scale */
{ 1., 0., 0., 1., 0, 0}, /* scale_inverse */
@ -644,23 +643,6 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a,
cairo_font_options_equal (&key_a->options, &key_b->options);
}
static cairo_bool_t
_cairo_scaled_font_matches (const cairo_scaled_font_t *scaled_font,
const cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options)
{
return scaled_font->original_font_face == font_face &&
memcmp ((unsigned char *)(&scaled_font->font_matrix.xx),
(unsigned char *)(&font_matrix->xx),
sizeof(cairo_matrix_t)) == 0 &&
memcmp ((unsigned char *)(&scaled_font->ctm.xx),
(unsigned char *)(&ctm->xx),
sizeof(cairo_matrix_t)) == 0 &&
cairo_font_options_equal (&scaled_font->options, options);
}
static cairo_bool_t
_cairo_scaled_glyphs_equal (const void *abstract_a, const void *abstract_b)
{
@ -727,7 +709,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
scaled_font->cache_frozen = FALSE;
scaled_font->global_cache_frozen = FALSE;
scaled_font->holdover = FALSE;
scaled_font->finished = FALSE;
CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
@ -764,7 +745,7 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
if (scaled_font->global_cache_frozen) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
_cairo_cache_thaw (&cairo_scaled_glyph_page_cache);
_cairo_cache_thaw (cairo_scaled_glyph_page_cache);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
scaled_font->global_cache_frozen = FALSE;
@ -780,7 +761,7 @@ _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
while (scaled_font->glyph_pages != NULL) {
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
_cairo_cache_remove (cairo_scaled_glyph_page_cache,
&scaled_font->glyph_pages->cache_entry);
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
@ -899,18 +880,28 @@ 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->type == CAIRO_FONT_TYPE_TOY) {
/* indirect implementation, lookup the face that is used for the toy face */
font_face = _cairo_toy_font_face_get_implementation (font_face);
if (unlikely (font_face->status))
return _cairo_scaled_font_create_in_error (font_face->status);
}
font_map = _cairo_scaled_font_map_lock ();
if (unlikely (font_map == NULL))
return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_scaled_font_init_key (&key, font_face,
font_matrix, ctm, options);
scaled_font = font_map->mru_scaled_font;
if (scaled_font != NULL &&
_cairo_scaled_font_matches (scaled_font,
font_face, font_matrix, ctm, options))
scaled_font->hash_entry.hash == key.hash_entry.hash &&
_cairo_scaled_font_keys_equal (scaled_font, &key))
{
assert (! scaled_font->placeholder);
if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) {
if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
/* We increment the reference count manually here, (rather
* than calling into cairo_scaled_font_reference), since we
* must modify the reference count while our lock is still
@ -924,26 +915,9 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
scaled_font->hash_entry.hash = ZOMBIE;
if (font_face->backend->get_implementation != NULL) {
font_face = font_face->backend->get_implementation (font_face,
font_matrix,
ctm,
options);
}
}
else
{
if (font_face->backend->get_implementation != NULL) {
font_face = font_face->backend->get_implementation (font_face,
font_matrix,
ctm,
options);
}
_cairo_scaled_font_init_key (&key, font_face,
font_matrix, ctm, options);
while ((scaled_font = _cairo_hash_table_lookup (font_map->hash_table,
&key.hash_entry)))
{
@ -960,30 +934,25 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
/* If the original reference count is 0, then this font must have
* been found in font_map->holdovers, (which means this caching is
* actually working). So now we remove it from the holdovers
* array, unless we caught the font in the middle of destruction.
*/
* array. */
if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
if (scaled_font->holdover) {
int i;
int i;
for (i = 0; i < font_map->num_holdovers; i++) {
if (font_map->holdovers[i] == scaled_font) {
font_map->num_holdovers--;
memmove (&font_map->holdovers[i],
&font_map->holdovers[i+1],
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
break;
}
}
for (i = 0; i < font_map->num_holdovers; i++)
if (font_map->holdovers[i] == scaled_font)
break;
assert (i < font_map->num_holdovers);
scaled_font->holdover = FALSE;
}
font_map->num_holdovers--;
memmove (&font_map->holdovers[i],
&font_map->holdovers[i+1],
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
/* reset any error status */
scaled_font->status = CAIRO_STATUS_SUCCESS;
}
if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) {
if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
/* We increment the reference count manually here, (rather
* than calling into cairo_scaled_font_reference), since we
* must modify the reference count while our lock is still
@ -1024,12 +993,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
return scaled_font;
}
/* Our caching above is defeated if the backend switches fonts on us -
* e.g. old incarnations of toy-font-face and lazily resolved
* ft-font-faces
*/
assert (scaled_font->font_face == font_face);
scaled_font->original_font_face =
cairo_font_face_reference (original_font_face);
@ -1055,9 +1018,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
cairo_scaled_font_destroy (old);
if (font_face != original_font_face)
cairo_font_face_destroy (font_face);
return scaled_font;
}
slim_hidden_def (cairo_scaled_font_create);
@ -1112,9 +1072,9 @@ _cairo_scaled_font_reset_static_data (void)
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
if (cairo_scaled_glyph_page_cache.hash_table != NULL) {
_cairo_cache_fini (&cairo_scaled_glyph_page_cache);
cairo_scaled_glyph_page_cache.hash_table = NULL;
if (cairo_scaled_glyph_page_cache != NULL) {
_cairo_cache_destroy (cairo_scaled_glyph_page_cache);
cairo_scaled_glyph_page_cache = NULL;
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
@ -1170,21 +1130,13 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
if (! _cairo_reference_count_dec_and_test (&scaled_font->ref_count))
return;
font_map = _cairo_scaled_font_map_lock ();
assert (font_map != NULL);
/* Another thread may have resurrected the font whilst we waited */
if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
if (! scaled_font->placeholder &&
scaled_font->hash_entry.hash != ZOMBIE)
{
/* Another thread may have already inserted us into the holdovers */
if (scaled_font->holdover)
goto unlock;
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon (and is why we must hold the lock over the atomic op on
@ -1192,7 +1144,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* destroy the least-recently-used holdover.
*/
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
{
lru = font_map->holdovers[0];
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&lru->ref_count));
@ -1205,13 +1158,12 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
}
font_map->holdovers[font_map->num_holdovers++] = scaled_font;
scaled_font->holdover = TRUE;
font_map->holdovers[font_map->num_holdovers] = scaled_font;
font_map->num_holdovers++;
} else
lru = scaled_font;
}
unlock:
_cairo_scaled_font_map_unlock ();
/* If we pulled an item from the holdovers array, (while the font
@ -1220,7 +1172,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* safely call fini on it without any lock held. This is desirable
* as we never want to call into any backend function with a lock
* held. */
if (lru != NULL) {
if (lru) {
_cairo_scaled_font_fini_internal (lru);
free (lru);
}
@ -1906,48 +1858,37 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
int i;
cairo_point_int_t min = { CAIRO_RECT_INT_MAX, CAIRO_RECT_INT_MAX };
cairo_point_int_t max = { CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN };
cairo_scaled_glyph_t *glyph_cache[64];
if (unlikely (scaled_font->status))
if (scaled_font->status)
return scaled_font->status;
_cairo_scaled_font_freeze_cache (scaled_font);
memset (glyph_cache, 0, sizeof (glyph_cache));
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
int left, top;
int right, bottom;
int x, y;
int cache_index = glyphs[i].index % ARRAY_LENGTH (glyph_cache);
scaled_glyph = glyph_cache[cache_index];
if (scaled_glyph == NULL ||
_cairo_scaled_glyph_index (scaled_glyph) != glyphs[i].index)
{
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (unlikely (status))
break;
glyph_cache[cache_index] = scaled_glyph;
}
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (unlikely (status))
break;
/* XXX glyph images are snapped to pixel locations */
x = _cairo_lround (glyphs[i].x);
y = _cairo_lround (glyphs[i].y);
left = x + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x);
top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
right = x + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
right = x + _cairo_fixed_integer_ceil(scaled_glyph->bbox.p2.x);
bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
if (left < min.x) min.x = left;
if (right > max.x) max.x = right;
if (top < min.y) min.y = top;
if (left < min.x) min.x = left;
if (right > max.x) max.x = right;
if (top < min.y) min.y = top;
if (bottom > max.y) max.y = bottom;
}
@ -2528,24 +2469,24 @@ _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font,
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
if (scaled_font->global_cache_frozen == FALSE) {
if (unlikely (cairo_scaled_glyph_page_cache.hash_table == NULL)) {
status = _cairo_cache_init (&cairo_scaled_glyph_page_cache,
NULL,
_cairo_scaled_glyph_page_can_remove,
_cairo_scaled_glyph_page_destroy,
MAX_GLYPH_PAGES_CACHED);
if (unlikely (status)) {
if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
cairo_scaled_glyph_page_cache =
_cairo_cache_create (NULL,
_cairo_scaled_glyph_page_can_remove,
_cairo_scaled_glyph_page_destroy,
MAX_GLYPH_PAGES_CACHED);
if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
free (page);
return status;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
}
_cairo_cache_freeze (&cairo_scaled_glyph_page_cache);
_cairo_cache_freeze (cairo_scaled_glyph_page_cache);
scaled_font->global_cache_frozen = TRUE;
}
status = _cairo_cache_insert (&cairo_scaled_glyph_page_cache,
status = _cairo_cache_insert (cairo_scaled_glyph_page_cache,
&page->cache_entry);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
if (unlikely (status)) {
@ -2575,8 +2516,7 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
_cairo_scaled_glyph_fini (scaled_font, scaled_glyph);
if (--page->num_glyphs == 0) {
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&page->cache_entry);
_cairo_cache_remove (cairo_scaled_glyph_page_cache, &page->cache_entry);
assert (scaled_font->glyph_pages != page);
}
}
@ -2751,9 +2691,6 @@ cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font)
if (scaled_font->status)
return (cairo_font_face_t*) &_cairo_font_face_nil;
if (scaled_font->original_font_face != NULL)
return scaled_font->original_font_face;
return scaled_font->font_face;
}
slim_hidden_def (cairo_scaled_font_get_font_face);

View File

@ -290,7 +290,6 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_WEIGHT: RETURN_NIL;
case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
default:
break;
}
@ -396,7 +395,6 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_WEIGHT: RETURN_NIL;
case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
default:
break;
}

View File

@ -38,8 +38,6 @@
void
_cairo_stroke_style_init (cairo_stroke_style_t *style)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (style, sizeof (cairo_stroke_style_t)));
style->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
style->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT;
style->line_join = CAIRO_GSTATE_LINE_JOIN_DEFAULT;
@ -57,8 +55,6 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
if (CAIRO_INJECT_FAULT ())
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
VG (VALGRIND_MAKE_MEM_UNDEFINED (style, sizeof (cairo_stroke_style_t)));
style->line_width = other->line_width;
style->line_cap = other->line_cap;
style->line_join = other->line_join;
@ -90,8 +86,6 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style)
style->dash = NULL;
}
style->num_dashes = 0;
VG (VALGRIND_MAKE_MEM_NOACCESS (style, sizeof (cairo_stroke_style_t)));
}
/*

View File

@ -398,6 +398,9 @@ _clip_and_composite (cairo_clip_t *clip,
extents);
}
if (src == &solid_pattern.base)
_cairo_pattern_fini (&solid_pattern.base);
return status;
}
@ -418,9 +421,6 @@ _composite_trap_region (cairo_clip_t *clip,
unsigned int clip_serial;
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
@ -428,6 +428,9 @@ _composite_trap_region (cairo_clip_t *clip,
op = CAIRO_OPERATOR_DEST_OUT;
}
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
if (num_rects > 1) {
if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -463,6 +466,9 @@ _composite_trap_region (cairo_clip_t *clip,
if (clip_surface)
_cairo_pattern_fini (&mask.base);
if (src == &solid_pattern.base)
_cairo_pattern_fini (&solid_pattern.base);
return status;
}
@ -482,23 +488,26 @@ _composite_traps_draw_func (void *closure,
{
cairo_composite_traps_info_t *info = closure;
cairo_solid_pattern_t pattern;
cairo_status_t status;
if (dst_x != 0 || dst_y != 0)
_cairo_traps_translate (info->traps, - dst_x, - dst_y);
if (src == NULL) {
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
}
return _cairo_surface_composite_trapezoids (op,
src, dst, info->antialias,
extents->x, extents->y,
extents->x - dst_x, extents->y - dst_y,
extents->width, extents->height,
info->traps->traps,
info->traps->num_traps);
status = _cairo_surface_composite_trapezoids (op,
src, dst, info->antialias,
extents->x, extents->y,
extents->x - dst_x, extents->y - dst_y,
extents->width, extents->height,
info->traps->traps,
info->traps->num_traps);
_cairo_pattern_fini (&pattern.base);
return status;
}
/* Warning: This call modifies the coordinates of traps */
@ -675,7 +684,8 @@ _composite_spans_fill_func (void *closure,
{
cairo_composite_rectangles_t rects;
cairo_composite_spans_fill_info_t *info = closure;
cairo_solid_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
_cairo_composite_rectangles_init (
&rects, extents->x, extents->y,
@ -689,16 +699,18 @@ _composite_spans_fill_func (void *closure,
/* We're called without a source pattern from
* _create_composite_mask_pattern(). */
if (src == NULL) {
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (src == NULL)
src = &pattern.base;
}
return _cairo_path_fixed_fill_using_spans (
status = _cairo_path_fixed_fill_using_spans (
op, src, info->path, dst,
info->fill_rule, info->tolerance, info->antialias,
&rects);
_cairo_pattern_fini (&pattern.base);
return status;
}
cairo_status_t
@ -1015,11 +1027,10 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
}
}
if (src == NULL) {
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
}
status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src,
dst,
@ -1030,18 +1041,24 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
extents->height,
glyph_info->glyphs,
glyph_info->num_glyphs);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
return _cairo_scaled_font_show_glyphs (glyph_info->font,
op,
src, dst,
extents->x, extents->y,
extents->x - dst_x,
extents->y - dst_y,
extents->width, extents->height,
glyph_info->glyphs,
glyph_info->num_glyphs);
status = _cairo_scaled_font_show_glyphs (glyph_info->font,
op,
src, dst,
extents->x, extents->y,
extents->x - dst_x,
extents->y - dst_y,
extents->width, extents->height,
glyph_info->glyphs,
glyph_info->num_glyphs);
if (src == &pattern.base)
_cairo_pattern_fini (&pattern.base);
return status;
}
cairo_status_t
@ -1196,7 +1213,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
int x1, y1, x2, y2;
int i;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (num_rects <= 0)
return CAIRO_STATUS_SUCCESS;

View File

@ -43,8 +43,6 @@
#include "cairo-types-private.h"
#include "cairo-reference-count-private.h"
typedef void (*cairo_surface_func_t) (cairo_surface_t *);
struct _cairo_surface {
const cairo_surface_backend_t *backend;
@ -58,8 +56,6 @@ struct _cairo_surface {
cairo_reference_count_t ref_count;
cairo_status_t status;
cairo_bool_t finished;
unsigned int unique_id;
cairo_user_data_array_t user_data;
cairo_user_data_array_t mime_data;
@ -96,10 +92,7 @@ struct _cairo_surface {
unsigned int current_clip_serial;
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
cairo_surface_t *snapshot_of;
cairo_surface_func_t snapshot_detach;
/* current snapshots of this surface */
cairo_array_t snapshots;
cairo_bool_t is_snapshot;
/*
* Surface font options, falling back to backend's default options,

View File

@ -50,7 +50,6 @@ const cairo_surface_t name = { \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
status, /* status */ \
FALSE, /* finished */ \
0, /* unique id */ \
{ 0, 0, 0, NULL, }, /* user_data */ \
{ 0, 0, 0, NULL, }, /* mime_data */ \
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \
@ -62,13 +61,7 @@ const cairo_surface_t name = { \
NULL, /* clip */ \
0, /* next_clip_serial */ \
0, /* current_clip_serial */ \
NULL, /* snapshot_of */ \
NULL, /* snapshot_detach */ \
{ 0, /* size */ \
0, /* num_elements */ \
0, /* element_size */ \
NULL, /* elements */ \
}, /* snapshots */ \
FALSE, /* is_snapshot */ \
FALSE, /* has_font_options */ \
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
@ -78,7 +71,6 @@ const cairo_surface_t name = { \
}
static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_SURFACE_TYPE_MISMATCH, _cairo_surface_nil_surface_type_mismatch);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual);
@ -188,151 +180,6 @@ cairo_surface_status (cairo_surface_t *surface)
}
slim_hidden_def (cairo_surface_status);
static unsigned int
_cairo_surface_allocate_unique_id (void)
{
static unsigned int unique_id;
#if CAIRO_NO_MUTEX
if (++unique_id == 0)
unique_id = 1;
return unique_id;
#else
unsigned int old, id;
do {
old = _cairo_atomic_uint_get (&unique_id);
id = old + 1;
if (id == 0)
id = 1;
} while (! _cairo_atomic_uint_cmpxchg (&unique_id, old, id));
return id;
#endif
}
static cairo_bool_t
_cairo_surface_has_snapshots (cairo_surface_t *surface)
{
return surface->snapshots.num_elements != 0;
}
static void
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
{
cairo_surface_t **snapshots;
unsigned int i;
if (! _cairo_surface_has_snapshots (surface))
return;
/* XXX do something intelligent! */
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
snapshots[i]->snapshot_of = NULL;
if (snapshots[i]->snapshot_detach != NULL)
snapshots[i]->snapshot_detach (snapshots[i]);
cairo_surface_destroy (snapshots[i]);
}
surface->snapshots.num_elements = 0;
assert (! _cairo_surface_has_snapshots (surface));
}
cairo_status_t
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *snapshot,
cairo_surface_func_t detach_func)
{
cairo_status_t status;
assert (surface != snapshot);
if (snapshot->snapshot_of != NULL)
_cairo_surface_detach_snapshot (snapshot);
snapshot->snapshot_of = surface;
snapshot->snapshot_detach = detach_func;
status = _cairo_array_append (&surface->snapshots, &snapshot);
if (unlikely (status))
return status;
cairo_surface_reference (snapshot);
return CAIRO_STATUS_SUCCESS;
}
cairo_surface_t *
_cairo_surface_has_snapshot (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
cairo_content_t content)
{
cairo_surface_t **snapshots;
unsigned int i;
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
if (snapshots[i]->backend == backend &&
snapshots[i]->content == content)
{
return snapshots[i];
}
}
return NULL;
}
void
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
{
cairo_surface_t *surface;
cairo_surface_t **snapshots;
unsigned int i;
assert (snapshot->snapshot_of != NULL);
surface = snapshot->snapshot_of;
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
if (snapshots[i] == snapshot)
break;
}
assert (i < surface->snapshots.num_elements);
surface->snapshots.num_elements--;
memmove (&snapshots[i],
&snapshots[i+1],
sizeof (cairo_surface_t *)*(surface->snapshots.num_elements - i));
snapshot->snapshot_of = NULL;
if (snapshot->snapshot_detach != NULL)
snapshot->snapshot_detach (snapshot);
cairo_surface_destroy (snapshot);
}
static cairo_bool_t
_cairo_surface_is_writable (cairo_surface_t *surface)
{
return ! surface->finished &&
surface->snapshot_of == NULL &&
! _cairo_surface_has_snapshots (surface);
}
static void
_cairo_surface_begin_modification (cairo_surface_t *surface)
{
assert (surface->status == CAIRO_STATUS_SUCCESS);
assert (! surface->finished);
assert (surface->snapshot_of == NULL);
_cairo_surface_detach_snapshots (surface);
}
void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
@ -347,7 +194,6 @@ _cairo_surface_init (cairo_surface_t *surface,
CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1);
surface->status = CAIRO_STATUS_SUCCESS;
surface->finished = FALSE;
surface->unique_id = _cairo_surface_allocate_unique_id ();
_cairo_user_data_array_init (&surface->user_data);
_cairo_user_data_array_init (&surface->mime_data);
@ -365,8 +211,7 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->next_clip_serial = 0;
surface->current_clip_serial = 0;
_cairo_array_init (&surface->snapshots, sizeof (cairo_surface_t *));
surface->snapshot_of = NULL;
surface->is_snapshot = FALSE;
surface->has_font_options = FALSE;
}
@ -591,14 +436,11 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (! _cairo_reference_count_dec_and_test (&surface->ref_count))
return;
assert (surface->snapshot_of == NULL);
if (! surface->finished)
cairo_surface_finish (surface);
_cairo_user_data_array_fini (&surface->user_data);
_cairo_user_data_array_fini (&surface->mime_data);
_cairo_array_fini (&surface->snapshots);
free (surface);
}
@ -698,9 +540,6 @@ cairo_surface_finish (cairo_surface_t *surface)
}
surface->finished = TRUE;
if (surface->snapshot_of != NULL)
_cairo_surface_detach_snapshot (surface);
}
slim_hidden_def (cairo_surface_finish);
@ -772,30 +611,27 @@ cairo_surface_get_mime_data (cairo_surface_t *surface,
const unsigned char **data,
unsigned int *length)
{
cairo_user_data_slot_t *slots;
int i, num_slots;
cairo_status_t status;
cairo_mime_data_t *mime_data;
*data = NULL;
*length = 0;
if (unlikely (surface->status))
if (surface->status)
return;
/* The number of mime-types attached to a surface is usually small,
* typically zero. Therefore it is quicker to do a strcmp() against
* each key than it is to intern the string (i.e. compute a hash,
* search the hash table, and do a final strcmp).
*/
num_slots = surface->mime_data.num_elements;
slots = _cairo_array_index (&surface->mime_data, 0);
for (i = 0; i < num_slots; i++) {
if (strcmp ((char *) slots[i].key, mime_type) == 0) {
cairo_mime_data_t *mime_data = slots[i].user_data;
*data = mime_data->data;
*length = mime_data->length;
return;
}
status = _cairo_intern_string (&mime_type, -1);
if (unlikely (status)) {
status = _cairo_surface_set_error (surface, status);
return;
}
mime_data = _cairo_user_data_array_get_data (&surface->mime_data,
(cairo_user_data_key_t *) mime_type);
if (mime_data == NULL)
return;
*data = mime_data->data;
*length = mime_data->length;
}
slim_hidden_def (cairo_surface_get_mime_data);
@ -937,7 +773,7 @@ _cairo_surface_set_font_options (cairo_surface_t *surface,
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface,
@ -1013,9 +849,6 @@ cairo_surface_flush (cairo_surface_t *surface)
if (surface->finished)
return;
/* update the current snapshots *before* the user updates the surface */
_cairo_surface_detach_snapshots (surface);
if (surface->backend->flush) {
status = surface->backend->flush (surface);
if (unlikely (status))
@ -1035,6 +868,11 @@ 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);
}
@ -1066,18 +904,13 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
}
/* The application *should* have called cairo_surface_flush() before
* modifying the surface independently of cairo (and thus having to
* call mark_dirty()). */
assert (! _cairo_surface_has_snapshots (surface));
/* Always reset the clip here, to avoid having external calls to
* clip manipulation functions of the underlying device clip result
* in a desync between the cairo clip and the backend clip, due to
@ -1129,15 +962,13 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
}
_cairo_surface_begin_modification (surface);
surface->device_transform.xx = sx;
surface->device_transform.yy = sy;
surface->device_transform.xy = 0.0;
@ -1177,15 +1008,13 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
}
_cairo_surface_begin_modification (surface);
surface->device_transform.x0 = x_offset;
surface->device_transform.y0 = y_offset;
@ -1262,15 +1091,13 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
}
_cairo_surface_begin_modification (surface);
surface->x_fallback_resolution = x_pixels_per_inch;
surface->y_fallback_resolution = y_pixels_per_inch;
}
@ -1414,7 +1241,7 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
if (surface->status)
return surface->status;
assert (_cairo_surface_is_writable (surface));
assert (!surface->finished);
if (surface->backend->acquire_dest_image == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1451,85 +1278,13 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
assert (_cairo_surface_is_writable (surface));
assert (!surface->finished);
if (surface->backend->release_dest_image)
surface->backend->release_dest_image (surface, interest_rect,
image, image_rect, image_extra);
}
static cairo_status_t
_cairo_meta_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
cairo_content_t content,
int src_x,
int src_y,
int width,
int height,
int *clone_offset_x,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
cairo_meta_surface_t *meta = (cairo_meta_surface_t *) src;
cairo_surface_t *similar;
cairo_status_t status;
similar = _cairo_surface_has_snapshot (src,
surface->backend,
src->content & content);
if (similar != NULL) {
*clone_out = cairo_surface_reference (similar);
*clone_offset_x = 0;
*clone_offset_y = 0;
return CAIRO_STATUS_SUCCESS;
}
if (width*height*8 < meta->extents.width*meta->extents.height) {
similar = cairo_surface_create_similar (surface,
src->content & content,
width, height);
status = similar->status;
if (unlikely (status))
return status;
cairo_surface_set_device_offset (similar, -src_x, -src_y);
status = cairo_meta_surface_replay (src, similar);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;
}
} else {
similar = cairo_surface_create_similar (surface,
src->content & content,
meta->extents.width,
meta->extents.height);
status = similar->status;
if (unlikely (status))
return status;
status = cairo_meta_surface_replay (src, similar);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;
}
status = _cairo_surface_attach_snapshot (src, similar, NULL);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;
}
src_x = src_y = 0;
}
*clone_out = similar;
*clone_offset_x = src_x;
*clone_offset_y = src_y;
return CAIRO_STATUS_SUCCESS;
}
struct acquire_source_image_data
{
cairo_surface_t *src;
@ -1586,6 +1341,7 @@ _wrap_image (cairo_surface_t *src,
}
/**
* _cairo_surface_clone_similar:
* @surface: a #cairo_surface_t
@ -1644,13 +1400,27 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* First check to see if we can replay to a similar surface */
if (_cairo_surface_is_meta (src)) {
return _cairo_meta_surface_clone_similar (surface, src,
content,
src_x, src_y,
width, height,
clone_offset_x,
clone_offset_y,
clone_out);
cairo_surface_t *similar;
similar = cairo_surface_create_similar (surface,
src->content & content,
width, height);
status = similar->status;
if (unlikely (status))
return status;
cairo_surface_set_device_offset (similar, -src_x, -src_y);
status = _cairo_meta_surface_replay (src, similar);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;
}
*clone_out = similar;
*clone_offset_x = src_x;
*clone_offset_y = src_y;
return CAIRO_STATUS_SUCCESS;
}
/* If we failed, try again with an image surface */
@ -1729,45 +1499,18 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
if (surface->finished)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
if (surface->snapshot_of != NULL)
if (surface->is_snapshot)
return cairo_surface_reference (surface);
snapshot = _cairo_surface_has_snapshot (surface,
surface->backend,
surface->content);
if (snapshot != NULL)
return cairo_surface_reference (snapshot);
if (surface->backend->snapshot != NULL) {
snapshot = NULL;
if (surface->backend->snapshot != NULL)
snapshot = surface->backend->snapshot (surface);
if (unlikely (snapshot->status))
return snapshot;
/* Is this surface just a proxy - e.g. paginated surfaces? */
if (snapshot->backend != surface->backend) {
cairo_surface_t *previous;
previous = _cairo_surface_has_snapshot (surface,
snapshot->backend,
snapshot->content);
if (previous != NULL) {
cairo_surface_destroy (snapshot);
return cairo_surface_reference (previous);
}
}
}
if (snapshot == NULL) {
snapshot = _cairo_surface_has_snapshot (surface,
&_cairo_image_surface_backend,
surface->content);
if (snapshot != NULL)
return cairo_surface_reference (snapshot);
if (snapshot == NULL)
snapshot = _cairo_surface_fallback_snapshot (surface);
if (unlikely (snapshot->status))
return snapshot;
}
if (unlikely (snapshot->status))
return snapshot;
status = _cairo_surface_copy_mime_data (snapshot, surface);
if (unlikely (status)) {
@ -1778,11 +1521,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
snapshot->device_transform = surface->device_transform;
snapshot->device_transform_inverse = surface->device_transform_inverse;
status = _cairo_surface_attach_snapshot (surface, snapshot, NULL);
if (unlikely (status)) {
cairo_surface_destroy (snapshot);
return _cairo_surface_create_in_error (status);
}
snapshot->is_snapshot = TRUE;
return snapshot;
}
@ -1832,11 +1571,6 @@ _cairo_surface_composite (cairo_operator_t op,
{
cairo_int_status_t status;
if (dst->status)
return dst->status;
assert (_cairo_surface_is_writable (dst));
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
@ -1844,6 +1578,14 @@ _cairo_surface_composite (cairo_operator_t op,
assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
}
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
if (dst->backend->composite) {
status = dst->backend->composite (op,
src, mask, dst,
@ -1893,7 +1635,10 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
if (surface->status)
return surface->status;
assert (_cairo_surface_is_writable (surface));
assert (! surface->is_snapshot);
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
rect.x = x;
rect.y = y;
@ -1931,7 +1676,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
if (surface->status)
return surface->status;
assert (_cairo_surface_is_writable (surface));
assert (! surface->is_snapshot);
num_rects = cairo_region_num_rectangles (region);
if (num_rects == 0)
@ -1986,7 +1731,10 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
if (surface->status)
return surface->status;
assert (_cairo_surface_is_writable (surface));
assert (! surface->is_snapshot);
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
@ -2015,7 +1763,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
if (surface->status)
return surface->status;
_cairo_surface_begin_modification (surface);
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (&source,
surface,
@ -2052,7 +1800,7 @@ _cairo_surface_mask (cairo_surface_t *surface,
if (surface->status)
return surface->status;
_cairo_surface_begin_modification (surface);
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (&source,
surface,
@ -2107,8 +1855,6 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
if (surface->status)
return surface->status;
_cairo_surface_begin_modification (surface);
if (surface->backend->fill_stroke) {
cairo_pattern_union_t dev_stroke_source;
cairo_pattern_union_t dev_fill_source;
@ -2187,7 +1933,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
if (surface->status)
return surface->status;
_cairo_surface_begin_modification (surface);
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (&source,
surface,
@ -2236,7 +1982,7 @@ _cairo_surface_fill (cairo_surface_t *surface,
if (surface->status)
return surface->status;
_cairo_surface_begin_modification (surface);
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (&source,
surface,
@ -2280,16 +2026,19 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
{
cairo_int_status_t status;
if (dst->status)
return dst->status;
assert (_cairo_surface_is_writable (dst));
/* These operators aren't interpreted the same way by the backends;
* they are implemented in terms of other operators in cairo-gstate.c
*/
assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
if (dst->status)
return dst->status;
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
if (dst->backend->composite_trapezoids) {
status = dst->backend->composite_trapezoids (op,
pattern, dst,
@ -2318,7 +2067,7 @@ _cairo_surface_create_span_renderer (cairo_operator_t op,
cairo_antialias_t antialias,
const cairo_composite_rectangles_t *rects)
{
assert (dst->snapshot_of == NULL);
assert (! dst->is_snapshot);
if (dst->status)
return _cairo_span_renderer_create_in_error (dst->status);
@ -2345,7 +2094,7 @@ _cairo_surface_check_span_renderer (cairo_operator_t op,
{
cairo_int_status_t status;
assert (dst->snapshot_of == NULL);
assert (! dst->is_snapshot);
if (dst->status)
return FALSE;
@ -2386,7 +2135,7 @@ cairo_surface_copy_page (cairo_surface_t *surface)
if (surface->status)
return;
assert (surface->snapshot_of == NULL);
assert (! surface->is_snapshot);
if (surface->finished) {
status_ignored = _cairo_surface_set_error (surface,
@ -2423,7 +2172,7 @@ cairo_surface_show_page (cairo_surface_t *surface)
if (surface->status)
return;
_cairo_surface_begin_modification (surface);
assert (! surface->is_snapshot);
if (surface->finished) {
status_ignored = _cairo_surface_set_error (surface,
@ -2541,9 +2290,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);
status = surface->backend->set_clip_region (surface, region);
@ -2681,35 +2427,6 @@ _cairo_surface_set_empty_clip_path (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
/**
* _cairo_surface_set_empty_clip_region:
* @surface: the #cairo_surface_t to set the clip on
* @serial: the clip serial number associated with the clip path
*
* Create an empty clip region, one that represents the entire surface clipped
* out, and assigns the given clipping serial to the surface.
**/
static cairo_status_t
_cairo_surface_set_empty_clip_region (cairo_surface_t *surface,
unsigned int serial)
{
cairo_region_t *region;
cairo_status_t status;
if (surface->status)
return surface->status;
region = cairo_region_create ();
status = region->status;
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_set_clip_region (surface, region, serial);
cairo_region_destroy (region);
return _cairo_surface_set_error (surface, status);
}
cairo_clip_t *
_cairo_surface_get_clip (cairo_surface_t *surface)
{
@ -2745,8 +2462,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
clip->serial);
if (surface->backend->set_clip_region != NULL)
return _cairo_surface_set_empty_clip_region (surface,
clip->serial);
return _cairo_surface_set_clip_region (surface,
clip->region,
clip->serial);
} else {
if (clip->path)
return _cairo_surface_set_clip_path (surface,
@ -2892,10 +2610,10 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (surface->status)
return surface->status;
if (num_glyphs == 0 && utf8_len == 0)
return CAIRO_STATUS_SUCCESS;
assert (! surface->is_snapshot);
_cairo_surface_begin_modification (surface);
if (!num_glyphs && !utf8_len)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_copy_pattern_for_destination (&source,
surface,
@ -3023,7 +2741,10 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (dst->status)
return dst->status;
assert (_cairo_surface_is_writable (dst));
assert (! dst->is_snapshot);
if (dst->finished)
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
if (dst->backend->old_show_glyphs) {
status = dst->backend->old_show_glyphs (scaled_font,
@ -3048,7 +2769,7 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
unsigned int height)
{
cairo_rectangle_int_t dst_rectangle;
cairo_region_t clear_region;
cairo_region_t *clear_region;
cairo_status_t status;
/* The area that was drawn is the area in the destination rectangle but
@ -3059,7 +2780,10 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
dst_rectangle.width = width;
dst_rectangle.height = height;
_cairo_region_init_rectangle (&clear_region, &dst_rectangle);
clear_region = cairo_region_create_rectangle (&dst_rectangle);
status = clear_region->status;
if (unlikely (status))
goto CLEANUP_REGIONS;
if (src_rectangle) {
if (! _cairo_rectangle_intersect (&dst_rectangle, src_rectangle))
@ -3072,17 +2796,17 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
}
/* Now compute the area that is in dst but not drawn */
status = cairo_region_subtract_rectangle (&clear_region, &dst_rectangle);
status = cairo_region_subtract_rectangle (clear_region, &dst_rectangle);
if (unlikely (status))
goto CLEANUP_REGIONS;
EMPTY:
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
clear_region);
CLEANUP_REGIONS:
_cairo_region_fini (&clear_region);
cairo_region_destroy (clear_region);
return _cairo_surface_set_error (dst, status);
}
@ -3135,7 +2859,7 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
if (dst->status)
return dst->status;
assert (_cairo_surface_is_writable (dst));
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.
@ -3213,7 +2937,7 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
if (dst->status)
return dst->status;
assert (_cairo_surface_is_writable (dst));
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.
@ -3299,8 +3023,6 @@ _cairo_surface_create_in_error (cairo_status_t status)
switch (status) {
case CAIRO_STATUS_NO_MEMORY:
return (cairo_surface_t *) &_cairo_surface_nil;
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
return (cairo_surface_t *) &_cairo_surface_nil_surface_type_mismatch;
case CAIRO_STATUS_INVALID_CONTENT:
return (cairo_surface_t *) &_cairo_surface_nil_invalid_content;
case CAIRO_STATUS_INVALID_FORMAT:
@ -3332,6 +3054,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_STRING:
case CAIRO_STATUS_INVALID_PATH_DATA:
case CAIRO_STATUS_SURFACE_FINISHED:
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_DASH:
case CAIRO_STATUS_INVALID_DSC_COMMENT:

View File

@ -856,7 +856,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
int width,
int height)
{
return cairo_meta_surface_create (content, width, height);
return _cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -1200,9 +1200,6 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
}
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot (&surface->base);
if (unlikely (meta->base.status))
return meta->base.status;
paginated_surface = _cairo_svg_surface_create_for_document (document,
meta->content,
meta->width_pixels,
@ -1217,7 +1214,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
status = cairo_meta_surface_replay (&meta->base, paginated_surface);
status = _cairo_meta_surface_replay (&meta->base, paginated_surface);
if (unlikely (status)) {
cairo_surface_destroy (&meta->base);
cairo_surface_destroy (paginated_surface);
@ -1334,8 +1331,8 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
"patternUnits=\"userSpaceOnUse\" "
"width=\"%d\" height=\"%d\"",
pattern_id,
(int) ceil (meta_surface->width_pixels),
(int) ceil (meta_surface->height_pixels));
meta_surface->width_pixels,
meta_surface->height_pixels);
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (output, ">\n");
}
@ -2658,7 +2655,6 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);
cairo_surface_finish (&snapshot->meta->base);
status2 = cairo_surface_status (&snapshot->meta->base);
cairo_surface_destroy (&snapshot->meta->base);
if (status == CAIRO_STATUS_SUCCESS)

View File

@ -387,36 +387,28 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
return _cairo_font_face_set_error (&font_face->base, CAIRO_STATUS_FONT_TYPE_MISMATCH);
}
static cairo_font_face_t *
_cairo_toy_font_face_get_implementation (void *abstract_font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options)
{
cairo_toy_font_face_t *font_face = abstract_font_face;
if (font_face->impl_face) {
cairo_font_face_t *impl = font_face->impl_face;
if (impl->backend->get_implementation != NULL) {
return impl->backend->get_implementation (impl,
font_matrix,
ctm,
options);
}
return cairo_font_face_reference (impl);
}
return abstract_font_face;
}
static cairo_bool_t
_cairo_font_face_is_toy (cairo_font_face_t *font_face)
{
return font_face->backend == &_cairo_toy_font_face_backend;
}
cairo_font_face_t *
_cairo_toy_font_face_get_implementation (cairo_font_face_t *font_face)
{
cairo_toy_font_face_t *toy_font_face;
if (font_face->status)
return NULL;
toy_font_face = (cairo_toy_font_face_t *) font_face;
if (! _cairo_font_face_is_toy (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
return toy_font_face->impl_face ? toy_font_face->impl_face : font_face;
}
/**
* cairo_toy_font_face_get_family:
* @font_face: A toy font face
@ -503,8 +495,7 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
CAIRO_FONT_TYPE_TOY,
NULL, /* create_for_toy */
_cairo_toy_font_face_destroy,
_cairo_toy_font_face_scaled_font_create,
_cairo_toy_font_face_get_implementation
_cairo_toy_font_face_scaled_font_create
};
void

View File

@ -47,8 +47,6 @@ _compare_point_fixed_by_y (const void *av, const void *bv);
void
_cairo_traps_init (cairo_traps_t *traps)
{
VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
traps->status = CAIRO_STATUS_SUCCESS;
traps->num_traps = 0;
@ -93,8 +91,6 @@ _cairo_traps_fini (cairo_traps_t *traps)
{
if (traps->traps != traps->traps_embedded)
free (traps->traps);
VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
}
/**
@ -619,10 +615,9 @@ cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t *traps,
cairo_region_t **region)
{
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
cairo_rectangle_int_t *rects = stack_rects;
cairo_int_status_t status;
int i, rect_count;
cairo_region_t *r;
int i;
for (i = 0; i < traps->num_traps; i++) {
if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
@ -636,15 +631,13 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
}
}
if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
r = cairo_region_create ();
if (unlikely (r->status))
return r->status;
if (unlikely (rects == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
rect_count = 0;
for (i = 0; i < traps->num_traps; i++) {
cairo_rectangle_int_t rect;
int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
@ -655,27 +648,21 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
*/
if (x1 == x2 || y1 == y2)
continue;
rects[rect_count].x = x1;
rects[rect_count].y = y1;
rects[rect_count].width = x2 - x1;
rects[rect_count].height = y2 - y1;
rect_count++;
rect.x = x1;
rect.y = y1;
rect.width = x2 - x1;
rect.height = y2 - y1;
status = cairo_region_union_rectangle (r, &rect);
if (unlikely (status)) {
cairo_region_destroy (r);
return status;
}
}
*region = cairo_region_create_rectangles (rects, rect_count);
status = cairo_region_status (*region);
if (rects != stack_rects)
free (rects);
if (unlikely (status)) {
cairo_region_destroy (*region);
*region = NULL;
}
return status;
*region = r;
return CAIRO_STATUS_SUCCESS;
}
/* moves trap points such that they become the actual corners of the trapezoid */

View File

@ -647,7 +647,7 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
if (unlikely (status))
return _cairo_truetype_font_set_error (font, status);
/* set checkSumAdjustment to 0 for table checksum calculation */
/* set checkSumAdjustment to 0 for table checksum calcualtion */
*(uint32_t *)(buffer + 8) = 0;
return CAIRO_STATUS_SUCCESS;

View File

@ -425,8 +425,8 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
goto cleanup;
}
status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
if (unlikely (status))
goto cleanup;
@ -520,8 +520,8 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
_cairo_output_stream_printf (surface->stream, "q\n");
status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status == CAIRO_STATUS_SUCCESS)

View File

@ -122,6 +122,20 @@ struct _cairo_font_options {
cairo_hint_metrics_t hint_metrics;
};
typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
struct _cairo_cache {
cairo_hash_table_t *hash_table;
cairo_cache_predicate_func_t predicate;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
unsigned long size;
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
@ -162,7 +176,8 @@ typedef enum _cairo_int_status {
} cairo_int_status_t;
typedef enum _cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,

View File

@ -85,14 +85,13 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
CAIRO_CONTENT_COLOR_ALPHA :
CAIRO_CONTENT_ALPHA;
meta_surface = cairo_meta_surface_create (content, -1, -1);
meta_surface = _cairo_meta_surface_create (content, -1, -1);
cr = cairo_create (meta_surface);
cairo_surface_destroy (meta_surface);
cairo_set_matrix (cr, &scaled_font->base.scale);
cairo_set_font_size (cr, 1.0);
cairo_set_font_options (cr, &scaled_font->base.options);
cairo_set_source_rgb (cr, 1., 1., 1.);
return cr;
}
@ -158,7 +157,8 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
_cairo_analysis_surface_set_ctm (analysis_surface,
&scaled_font->extent_scale);
status = cairo_meta_surface_replay (meta_surface, analysis_surface);
status = _cairo_meta_surface_replay (meta_surface,
analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
@ -213,7 +213,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
cairo_surface_set_device_offset (surface,
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
status = cairo_meta_surface_replay (meta_surface, surface);
status = _cairo_meta_surface_replay (meta_surface, surface);
if (unlikely (status)) {
cairo_surface_destroy(surface);

View File

@ -977,7 +977,8 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_METRICS | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
memset (&metrics, 0, sizeof (GLYPHMETRICS));
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
memset (&metrics, 0, sizeof (GLYPHMETRICS));
} else {
if (metrics.gmBlackBoxX > 0 && scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE) {
/* The bounding box reported by Windows supposedly contains the glyph's "black" area;
@ -993,6 +994,8 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
}
}
cairo_win32_scaled_font_done_font (&scaled_font->base);
if (status)
return status;
if (scaled_font->swap_axes) {
extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
@ -1031,9 +1034,12 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_METRICS | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
memset (&metrics, 0, sizeof (GLYPHMETRICS));
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
memset (&metrics, 0, sizeof (GLYPHMETRICS));
}
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
if (status)
return status;
extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;

View File

@ -1607,7 +1607,7 @@ _cairo_win32_printing_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return cairo_meta_surface_create (content, width, height);
return _cairo_meta_surface_create (content, width, height);
}
static cairo_int_status_t

View File

@ -2102,7 +2102,7 @@ _cairo_win32_surface_span_renderer_finish (void *abstract_renderer)
cairo_pattern_t *mask_pattern = cairo_pattern_create_for_surface (&renderer->mask->base);
/* composite onto the image surface directly if we can */
if (dst->image) {
GdiFlush(); /* XXX: I'm not sure if this needed or not */
GdiFlush();
status = dst->image->backend->composite (renderer->op,
renderer->pattern, mask_pattern, dst->image,

View File

@ -74,6 +74,7 @@ cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool
cairo_public cairo_status_t
cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
#if CAIRO_HAS_WIN32_FONT
/*

View File

@ -101,8 +101,6 @@ typedef struct cairo_xcb_surface {
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
#define CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
#define CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
static void
_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface);
@ -613,20 +611,6 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surfa
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_xcb_surface_snapshot (void *abstract_surface)
{
cairo_xcb_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
cairo_status_t status;
status = _get_image_surface (surface, NULL, &image, NULL);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
return &image->base;
}
static void
_cairo_xcb_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
@ -856,22 +840,13 @@ _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface,
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NONE);
_cairo_xcb_surface_set_repeat (surface, 0);
break;
case CAIRO_EXTEND_REPEAT:
_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NORMAL);
_cairo_xcb_surface_set_repeat (surface, 1);
break;
case CAIRO_EXTEND_REFLECT:
if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_REFLECT);
break;
case CAIRO_EXTEND_PAD:
if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_PAD);
break;
default:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1149,7 +1124,6 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
src_x, src_y,
mask_x, mask_y,
width, height,
CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
(cairo_surface_t **) &src,
(cairo_surface_t **) &mask,
&src_attr, &mask_attr);
@ -1437,7 +1411,6 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
(cairo_surface_t **) &src,
&attributes);
if (status)
@ -1585,6 +1558,7 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
xcb_render_change_picture (surface->dpy, surface->dst_picture,
XCB_RENDER_CP_CLIP_MASK, none);
} else {
cairo_status_t status;
xcb_rectangle_t *rects = NULL;
int n_rects, i;
@ -1602,13 +1576,13 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
rects[i].x = rect.x;
rects[i].y = rect.y;
rects[i].width = rect.width;
rects[i].height = rect.height;
}
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
surface->num_clip_rects = n_rects;
@ -1654,8 +1628,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs,
cairo_rectangle_int_t *extents);
int *remaining_glyphs);
static cairo_bool_t
_cairo_xcb_surface_is_similar (void *surface_a,
@ -1729,8 +1702,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
NULL, /* stroke */
NULL, /* fill */
_cairo_xcb_surface_show_glyphs,
_cairo_xcb_surface_snapshot,
NULL, /* snapshot */
_cairo_xcb_surface_is_similar,
@ -2463,8 +2435,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs,
cairo_rectangle_int_t *extents)
int *remaining_glyphs)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_xcb_surface_t *dst = abstract_dst;
@ -2533,7 +2504,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
0, 0, 1, 1,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
} else {
@ -2550,7 +2520,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents.x, glyph_extents.y,
glyph_extents.width, glyph_extents.height,
CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
(cairo_surface_t **) &src,
&attributes);
}

View File

@ -287,7 +287,6 @@ _cairo_xlib_display_get (Display *dpy,
sizeof (display->cached_xrender_formats));
display->buggy_repeat = FALSE;
display->buggy_pad_reflect = TRUE;
/* This buggy_repeat condition is very complicated because there
* are multiple X server code bases (with multiple versioning
@ -334,19 +333,13 @@ _cairo_xlib_display_get (Display *dpy,
* (just using VendorRelase < 70000000), as buggy_repeat=TRUE.
*/
if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
if (VendorRelease (dpy) >= 60700000) {
if (VendorRelease (dpy) < 70000000)
display->buggy_repeat = TRUE;
} else {
if (VendorRelease (dpy) < 10400000)
display->buggy_repeat = TRUE;
if (VendorRelease (dpy) >= 10699000)
display->buggy_pad_reflect = FALSE;
}
if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) < 70000000)
display->buggy_repeat = TRUE;
if (VendorRelease (dpy) < 10400000)
display->buggy_repeat = TRUE;
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
if (VendorRelease (dpy) <= 40500000)
display->buggy_repeat = TRUE;
}
/* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */

View File

@ -73,7 +73,6 @@ struct _cairo_xlib_display {
cairo_xlib_hook_t *close_display_hooks;
unsigned int buggy_repeat :1;
unsigned int buggy_pad_reflect :1;
unsigned int closed :1;
};
@ -103,8 +102,8 @@ struct _cairo_xlib_screen_info {
cairo_bool_t has_font_options;
cairo_font_options_t font_options;
GC gc[4];
int gc_depths; /* 4 x uint8_t, high bit == needs reset */
GC gc[9];
unsigned int gc_needs_clip_reset;
cairo_array_t visuals;
};
@ -154,13 +153,12 @@ _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
cairo_private GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
Drawable drawable,
int depth,
unsigned int *need_reset);
cairo_private void
cairo_private cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
int depth,
GC gc,
cairo_bool_t reset_clip);

View File

@ -268,29 +268,19 @@ void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
{
cairo_xlib_visual_info_t **visuals;
Display *dpy;
int i, old;
int i;
CAIRO_MUTEX_LOCK (info->mutex);
dpy = info->display->display;
#if HAS_ATOMIC_OPS
do {
old = info->gc_depths;
} while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, 0) != old);
#else
old = info->gc_depths;
#endif
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (old >> (8*i) & 0x7f)
XFreeGC (dpy, info->gc[i]);
if (info->gc[i] != NULL) {
XFreeGC (info->display->display, info->gc[i]);
info->gc[i] = NULL;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (dpy, visuals[i]);
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
_cairo_array_truncate (&info->visuals, 0);
CAIRO_MUTEX_UNLOCK (info->mutex);
@ -368,8 +358,8 @@ _cairo_xlib_screen_info_get (cairo_xlib_display_t *display,
info->screen = screen;
info->has_render = FALSE;
info->has_font_options = FALSE;
info->gc_depths = 0;
memset (info->gc, 0, sizeof (info->gc));
info->gc_needs_clip_reset = 0;
_cairo_array_init (&info->visuals,
sizeof (cairo_xlib_visual_info_t*));
@ -396,165 +386,71 @@ _cairo_xlib_screen_info_get (cairo_xlib_display_t *display,
return CAIRO_STATUS_SUCCESS;
}
#if HAS_ATOMIC_OPS
static int
depth_to_index (int depth)
{
switch(depth){
case 1: return 1;
case 8: return 2;
case 12: return 3;
case 15: return 4;
case 16: return 5;
case 24: return 6;
case 30: return 7;
case 32: return 8;
}
return 0;
}
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
Drawable drawable,
int depth,
unsigned int *dirty)
{
XGCValues gcv;
int i, new, old;
GC gc;
cairo_bool_t needs_reset;
do {
gc = NULL;
old = info->gc_depths;
if (old == 0)
break;
if (((old >> 0) & 0x7f) == depth)
i = 0;
else if (((old >> 8) & 0x7f) == depth)
i = 1;
else if (((old >> 16) & 0x7f) == depth)
i = 2;
else if (((old >> 24) & 0x7f) == depth)
i = 3;
else
break;
gc = info->gc[i];
new = old & ~(0xff << (8*i));
} while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, new) != old);
if (likely (gc != NULL)) {
(void) _cairo_atomic_ptr_cmpxchg (&info->gc[i], gc, NULL);
if (old & 0x80 << (8 * i))
*dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
return gc;
}
gcv.graphics_exposures = False;
return XCreateGC (info->display->display, drawable,
GCGraphicsExposures, &gcv);
}
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
GC gc,
cairo_bool_t reset_clip)
{
int i, old, new;
depth |= reset_clip ? 0x80 : 0;
do {
do {
i = -1;
old = info->gc_depths;
if (((old >> 0) & 0x7f) == 0)
i = 0;
else if (((old >> 8) & 0x7f) == 0)
i = 1;
else if (((old >> 16) & 0x7f) == 0)
i = 2;
else if (((old >> 24) & 0x7f) == 0)
i = 3;
else
goto out;
new = old | (depth << (8*i));
} while (_cairo_atomic_ptr_cmpxchg (&info->gc[i], NULL, gc) != NULL);
} while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, new) != old);
return;
out:
if (unlikely (_cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
gc,
NULL)))
{
/* leak the server side resource... */
XFree ((char *) gc);
}
}
#else
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
Drawable drawable,
unsigned int *dirty)
{
GC gc = NULL;
int i;
depth = depth_to_index (depth);
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (((info->gc_depths >> (8*i)) & 0x7f) == depth) {
if (info->gc_depths & 0x80 << (8*i))
*dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
info->gc_depths &= ~(0xff << (8*i));
gc = info->gc[i];
break;
}
}
gc = info->gc[depth];
info->gc[depth] = NULL;
needs_reset = info->gc_needs_clip_reset & (1 << depth);
info->gc_needs_clip_reset &= ~(1 << depth);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (gc == NULL) {
XGCValues gcv;
gcv.graphics_exposures = False;
gc = XCreateGC (info->display->display, drawable,
GCGraphicsExposures, &gcv);
}
if (needs_reset)
*dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
return gc;
}
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info,
unsigned int depth,
GC gc,
cairo_bool_t reset_clip)
cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
GC oldgc;
depth |= reset_clip ? 0x80 : 0;
depth = depth_to_index (depth);
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (((info->gc_depths >> (8*i)) & 0x7f) == 0)
break;
}
if (i == ARRAY_LENGTH (info->gc)) {
cairo_status_t status;
/* perform random substitution to ensure fair caching over depths */
i = rand () % ARRAY_LENGTH (info->gc);
status =
_cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
info->gc[i],
NULL);
if (unlikely (status)) {
/* leak the server side resource... */
XFree ((char *) info->gc[i]);
}
}
info->gc[i] = gc;
info->gc_depths &= ~(0xff << (8*i));
info->gc_depths |= depth << (8*i);
oldgc = info->gc[depth];
info->gc[depth] = gc;
if (reset_clip)
info->gc_needs_clip_reset |= 1 << depth;
else
info->gc_needs_clip_reset &= ~(1 << depth);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (oldgc != NULL) {
status = _cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
oldgc,
NULL);
}
return status;
}
#endif
cairo_status_t
_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,

View File

@ -76,7 +76,6 @@ struct _cairo_xlib_surface {
* we can reuse the test for now.
*/
cairo_bool_t buggy_repeat;
cairo_bool_t buggy_pad_reflect;
int width;
int height;

View File

@ -67,9 +67,6 @@ _cairo_xlib_surface_create_internal (Display *dpy,
static cairo_status_t
_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);
static void
_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface);
static void
_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface);
@ -92,10 +89,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
int *remaining_glyphs,
cairo_rectangle_int_t *extents);
/* XXX temporarily used by cairo-qt-surface.c */
slim_hidden_proto (cairo_xlib_surface_create);
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
/*
* Instead of taking two round trips for each blending request,
* assume that if a particular drawable fails GetImage that it will
@ -210,7 +203,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
int height)
{
cairo_xlib_surface_t *src = abstract_src;
XRenderPictFormat *xrender_format;
XRenderPictFormat *xrender_format = src->xrender_format;
cairo_xlib_surface_t *surface;
Pixmap pix;
@ -219,12 +212,17 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
_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
* case of a bitmap, it won't even have that). */
if (xrender_format == NULL && src->visual != NULL)
xrender_format = XRenderFindVisualFormat (src->dpy, src->visual);
/* If we never found an XRenderFormat or if it isn't compatible
* with the content being requested, then we fallback to just
* constructing a cairo_format_t instead, (which will fairly
* arbitrarily pick a visual/depth for the similar surface.
*/
xrender_format = src->xrender_format;
if (xrender_format == NULL ||
_xrender_format_to_content (xrender_format) != content)
{
@ -303,11 +301,14 @@ _cairo_xlib_surface_finish (void *abstract_surface)
}
if (surface->gc != NULL) {
_cairo_xlib_screen_put_gc (surface->screen_info,
surface->depth,
surface->gc,
surface->gc_has_clip_rects);
cairo_status_t status2;
status2 = _cairo_xlib_screen_put_gc (surface->screen_info,
surface->depth,
surface->gc,
surface->gc_has_clip_rects);
surface->gc = NULL;
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
if (surface->clip_rects != surface->embedded_clip_rects)
@ -657,7 +658,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
ximage = NULL;
}
if (!ximage) {
if (!ximage)
{
/* XGetImage from a window is dangerous because it can
* produce errors if the window is unmapped or partially
@ -691,12 +693,9 @@ _get_image_surface (cairo_xlib_surface_t *surface,
XFreePixmap (surface->dpy, pixmap);
}
if (!ximage)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_xlib_surface_maybe_put_gc (surface);
}
if (!ximage)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_swap_ximage_to_native (ximage);
@ -836,7 +835,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
static void
_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface)
{
if (!surface->src_picture) {
if (!surface->src_picture)
{
XRenderPictureAttributes pa;
int mask = 0;
@ -900,14 +900,19 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
static cairo_status_t
_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
{
XGCValues gcv;
if (surface->gc == NULL) {
surface->gc = _cairo_xlib_screen_get_gc (surface->screen_info,
surface->depth,
surface->drawable,
&surface->clip_dirty);
if (unlikely (surface->gc == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (surface->gc == NULL) {
gcv.graphics_exposures = False;
surface->gc = XCreateGC (surface->dpy, surface->drawable,
GCGraphicsExposures, &gcv);
if (unlikely (surface->gc == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
}
if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC)
@ -916,21 +921,6 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface)
{
/* return the GC back to the common pool if clean */
if (surface->gc_has_clip_rects)
return;
_cairo_xlib_screen_put_gc (surface->screen_info,
surface->depth,
surface->gc,
FALSE);
surface->gc = NULL;
}
static cairo_status_t
_draw_image_surface (cairo_xlib_surface_t *surface,
cairo_image_surface_t *image,
@ -1089,8 +1079,6 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
&ximage, src_x, src_y, dst_x, dst_y,
width, height);
_cairo_xlib_surface_maybe_put_gc (surface);
BAIL:
if (own_data)
free (ximage.data);
@ -1119,22 +1107,6 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_xlib_surface_snapshot (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
cairo_status_t status;
_cairo_xlib_display_notify (surface->display);
status = _get_image_surface (surface, NULL, &image, NULL);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
return &image->base;
}
static void
_cairo_xlib_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
@ -1362,6 +1334,9 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
{
XTransform xtransform;
if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
/* Casting between pixman_transform_t and XTransform is safe because
* they happen to be the exact same type.
*/
@ -1387,6 +1362,9 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface,
{
const char *render_filter;
if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
if (surface->filter == filter)
return CAIRO_STATUS_SUCCESS;
@ -1438,6 +1416,9 @@ _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat)
XRenderPictureAttributes pa;
unsigned long mask;
if (!surface->src_picture)
return;
if (surface->repeat == repeat)
return;
@ -1471,15 +1452,7 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
_cairo_xlib_surface_set_repeat (surface, RepeatNormal);
break;
case CAIRO_EXTEND_REFLECT:
if (surface->buggy_pad_reflect)
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_xlib_surface_set_repeat (surface, RepeatReflect);
break;
case CAIRO_EXTEND_PAD:
if (surface->buggy_pad_reflect)
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_xlib_surface_set_repeat (surface, RepeatPad);
break;
default:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1781,9 +1754,6 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
src_x, src_y,
mask_x, mask_y,
width, height,
dst->buggy_pad_reflect ?
CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
(cairo_surface_t **) &mask,
&src_attr, &mask_attr);
@ -1871,8 +1841,6 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
src_y + src_attr.y_offset + ity,
width, height,
dst_x, dst_y);
_cairo_xlib_surface_maybe_put_gc (dst);
break;
case DO_XTILE:
@ -1899,8 +1867,6 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
XFillRectangle (dst->dpy, dst->drawable, dst->gc,
dst_x, dst_y, width, height);
_cairo_xlib_surface_maybe_put_gc (dst);
break;
case DO_UNSUPPORTED:
@ -1950,7 +1916,6 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
0, 0,
ARRAY_LENGTH (dither_pattern[0]),
ARRAY_LENGTH (dither_pattern),
CAIRO_PATTERN_ACQUIRE_NONE,
&solid_surface,
&attrs);
if (unlikely (status))
@ -1974,8 +1939,6 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
rects[i].width, rects[i].height);
}
_cairo_xlib_surface_maybe_put_gc (surface);
BAIL:
_cairo_pattern_release_surface (&solid.base, solid_surface, &attrs);
@ -2202,9 +2165,6 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
dst->buggy_pad_reflect ?
CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))
@ -2544,9 +2504,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
NULL, /* stroke */
NULL, /* fill */
_cairo_xlib_surface_show_glyphs,
_cairo_xlib_surface_snapshot,
NULL, /* snapshot */
_cairo_xlib_surface_is_similar,
_cairo_xlib_surface_reset,
NULL, /* fill_stroke */
@ -2709,7 +2667,6 @@ _cairo_xlib_surface_create_internal (Display *dpy,
/* so we can use the XTile fallback */
surface->buggy_repeat = TRUE;
}
surface->buggy_pad_reflect = screen_info->display->buggy_pad_reflect;
surface->dst_picture = None;
surface->src_picture = None;
@ -2827,7 +2784,6 @@ cairo_xlib_surface_create (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
visual, NULL, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create);
/**
* cairo_xlib_surface_create_for_bitmap:
@ -2885,7 +2841,6 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
NULL, format, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
/**
* cairo_xlib_surface_get_xrender_format:
@ -3645,13 +3600,14 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
}
n = new;
d = data;
do {
while (c--)
{
char b = *d++;
b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
*n++ = b;
} while (--c);
}
data = new;
}
break;
@ -3659,21 +3615,28 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
break;
case CAIRO_FORMAT_ARGB32:
if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) {
unsigned int c = glyph_surface->stride * glyph_surface->height / 4;
const uint32_t *d;
uint32_t *new, *n;
unsigned int c = glyph_surface->stride * glyph_surface->height;
unsigned char *d;
unsigned char *new, *n;
new = malloc (4 * c);
new = malloc (c);
if (unlikely (new == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL;
}
n = new;
d = (uint32_t *) data;
do {
*n++ = bswap_32 (*d++);
} while (--c);
data = (uint8_t *) new;
d = data;
while (c >= 4)
{
n[3] = d[0];
n[2] = d[1];
n[1] = d[2];
n[0] = d[3];
d += 4;
n += 4;
c -= 4;
}
data = new;
}
break;
case CAIRO_FORMAT_RGB24:
@ -4132,7 +4095,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
0, 0, 1, 1,
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))
@ -4151,9 +4113,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents.x, glyph_extents.y,
glyph_extents.width, glyph_extents.height,
dst->buggy_pad_reflect ?
CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))

File diff suppressed because it is too large Load Diff

View File

@ -210,7 +210,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_SUCCESS: no error has occurred
* @CAIRO_STATUS_NO_MEMORY: out of memory
* @CAIRO_STATUS_INVALID_RESTORE: cairo_restore() called without matching cairo_save()
* @CAIRO_STATUS_INVALID_POP_GROUP: no saved group to pop, i.e. cairo_pop_group() without matching cairo_push_group()
* @CAIRO_STATUS_INVALID_POP_GROUP: no saved group to pop
* @CAIRO_STATUS_NO_CURRENT_POINT: no current point defined
* @CAIRO_STATUS_INVALID_MATRIX: invalid matrix (not invertible)
* @CAIRO_STATUS_INVALID_STATUS: invalid value for an input #cairo_status_t
@ -239,7 +239,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_INVALID_CLUSTERS: input clusters do not represent the accompanying text and glyph array (Since 1.8)
* @CAIRO_STATUS_INVALID_SLANT: invalid value for an input #cairo_font_slant_t (Since 1.8)
* @CAIRO_STATUS_INVALID_WEIGHT: invalid value for an input #cairo_font_weight_t (Since 1.8)
* @CAIRO_STATUS_INVALID_SIZE: invalid value (typically too big) for the size of the input (surface, pattern, etc.) (Since 1.10)
* @CAIRO_STATUS_INVALID_SIZE: invalid value (typically too big) for a size (Since 1.10)
* @CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: user-font method not implemented (Since 1.10)
* @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
* status values defined in this enumeration. When using this value, note
@ -1889,8 +1889,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
* @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
* @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
* @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10
* @CAIRO_SURFACE_TYPE_META: The surface is a meta-type, since 1.10
* @CAIRO_SURFACE_TYPE_QPAINTER: The surface is of type qpainter
* @CAIRO_SURFACE_TYPE_DDRAW: The surface is of type ddraw
*
* #cairo_surface_type_t is used to describe the type of a given
@ -1932,8 +1931,7 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
CAIRO_SURFACE_TYPE_SCRIPT,
CAIRO_SURFACE_TYPE_QT,
CAIRO_SURFACE_TYPE_META,
CAIRO_SURFACE_TYPE_QPAINTER,
CAIRO_SURFACE_TYPE_DDRAW
} cairo_surface_type_t;
@ -2112,24 +2110,6 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
#endif
/* Meta-surface functions */
cairo_public cairo_surface_t *
cairo_meta_surface_create (cairo_content_t content,
double width_pixels,
double height_pixels);
cairo_public void
cairo_meta_surface_ink_extents (cairo_surface_t *surface,
double *x0,
double *y0,
double *width,
double *height);
cairo_public cairo_status_t
cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
/* Pattern creation functions */
cairo_public cairo_pattern_t *
@ -2397,10 +2377,6 @@ cairo_region_create (void);
cairo_public cairo_region_t *
cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle);
cairo_public cairo_region_t *
cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
int count);
cairo_public cairo_region_t *
cairo_region_copy (cairo_region_t *original);

View File

@ -181,7 +181,7 @@ do { \
* in libgcc in case a target does not have one, which should be just as
* good as the open-coded solution below, (which is "HACKMEM 169").
*/
static inline int cairo_const
static inline int
_cairo_popcount (uint32_t mask)
{
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
@ -210,25 +210,25 @@ _cairo_popcount (uint32_t mask)
#else
static inline uint16_t cairo_const
static inline uint16_t
cpu_to_be16(uint16_t v)
{
return (v << 8) | (v >> 8);
}
static inline uint16_t cairo_const
static inline uint16_t
be16_to_cpu(uint16_t v)
{
return cpu_to_be16 (v);
}
static inline uint32_t cairo_const
static inline uint32_t
cpu_to_be32(uint32_t v)
{
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
}
static inline uint32_t cairo_const
static inline uint32_t
be32_to_cpu(uint32_t v)
{
return cpu_to_be32 (v);
@ -264,12 +264,10 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
const cairo_rectangle_int_t *src);
cairo_private cairo_bool_t
_cairo_box_intersects_line_segment (cairo_box_t *box,
cairo_line_t *line) cairo_pure;
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
cairo_private cairo_bool_t
_cairo_box_contains_point (cairo_box_t *box,
const cairo_point_t *point) cairo_pure;
_cairo_box_contains_point (cairo_box_t *box, const cairo_point_t *point);
cairo_private void
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *rects,
@ -321,12 +319,6 @@ _cairo_array_num_elements (cairo_array_t *array);
cairo_private int
_cairo_array_size (cairo_array_t *array);
typedef struct {
const cairo_user_data_key_t *key;
void *user_data;
cairo_destroy_func_t destroy;
} cairo_user_data_slot_t;
cairo_private void
_cairo_user_data_array_init (cairo_user_data_array_t *array);
@ -532,12 +524,6 @@ struct _cairo_font_face_backend {
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font);
cairo_font_face_t *
(*get_implementation) (void *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options);
};
extern const cairo_private struct _cairo_font_face_backend _cairo_user_font_face_backend;
@ -923,6 +909,7 @@ struct _cairo_solid_pattern {
cairo_content_t content;
};
extern const cairo_private cairo_solid_pattern_t _cairo_pattern_nil;
extern const cairo_private cairo_solid_pattern_t _cairo_pattern_black;
typedef struct _cairo_surface_pattern {
@ -1052,7 +1039,7 @@ typedef struct _cairo_stroke_face {
/* cairo.c */
static inline double cairo_const
static inline double
_cairo_restrict_value (double value, double min, double max)
{
if (value < min)
@ -1066,14 +1053,14 @@ _cairo_restrict_value (double value, double min, double max)
/* C99 round() rounds to the nearest integral value with halfway cases rounded
* away from 0. _cairo_round rounds halfway cases toward negative infinity.
* This matches the rounding behaviour of _cairo_lround. */
static inline double cairo_const
static inline double
_cairo_round (double r)
{
return floor (r + .5);
}
cairo_private int
_cairo_lround (double d) cairo_const;
_cairo_lround (double d);
/* cairo-gstate.c */
cairo_private cairo_status_t
@ -1367,21 +1354,21 @@ cairo_private cairo_antialias_t
_cairo_gstate_get_antialias (cairo_gstate_t *gstate);
cairo_private cairo_bool_t
_cairo_operator_bounded_by_mask (cairo_operator_t op) cairo_const;
_cairo_operator_bounded_by_mask (cairo_operator_t op) cairo_pure;
cairo_private cairo_bool_t
_cairo_operator_bounded_by_source (cairo_operator_t op) cairo_const;
_cairo_operator_bounded_by_source (cairo_operator_t op) cairo_pure;
/* cairo-color.c */
cairo_private const cairo_color_t *
_cairo_stock_color (cairo_stock_t stock) cairo_pure;
_cairo_stock_color (cairo_stock_t stock);
#define CAIRO_COLOR_WHITE _cairo_stock_color (CAIRO_STOCK_WHITE)
#define CAIRO_COLOR_BLACK _cairo_stock_color (CAIRO_STOCK_BLACK)
#define CAIRO_COLOR_TRANSPARENT _cairo_stock_color (CAIRO_STOCK_TRANSPARENT)
cairo_private uint16_t
_cairo_color_double_to_short (double d) cairo_const;
_cairo_color_double_to_short (double d) cairo_pure;
cairo_private void
_cairo_color_init (cairo_color_t *color);
@ -1415,7 +1402,7 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
cairo_private cairo_bool_t
_cairo_color_equal (const cairo_color_t *color_a,
const cairo_color_t *color_b) cairo_pure;
const cairo_color_t *color_b);
/* cairo-font-face.c */
@ -1439,10 +1426,10 @@ _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_fallback (void);
_cairo_toy_font_face_get_implementation (cairo_font_face_t *font_face);
/* cairo-font-face-twin.c */
cairo_private cairo_status_t
_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
@ -1624,6 +1611,9 @@ cairo_private cairo_bool_t
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
cairo_box_t *box);
cairo_private cairo_bool_t
_cairo_path_fixed_is_region (cairo_path_fixed_t *path);
/* cairo-path-in-fill.c */
cairo_private void
_cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
@ -1994,19 +1984,6 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_private cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface);
cairo_private cairo_status_t
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *snapshot,
cairo_surface_func_t detach_func);
cairo_private cairo_surface_t *
_cairo_surface_has_snapshot (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
cairo_content_t content);
cairo_private void
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
cairo_private cairo_bool_t
_cairo_surface_is_similar (cairo_surface_t *surface_a,
cairo_surface_t *surface_b,
@ -2105,7 +2082,7 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
double sy);
cairo_private cairo_bool_t
_cairo_surface_has_device_transform (cairo_surface_t *surface) cairo_pure;
_cairo_surface_has_device_transform (cairo_surface_t *surface);
/* cairo-image-surface.c */
@ -2154,13 +2131,13 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface) cairo_pure;
== 0))
cairo_private int
_cairo_format_bits_per_pixel (cairo_format_t format) cairo_const;
_cairo_format_bits_per_pixel (cairo_format_t format) cairo_pure;
cairo_private cairo_format_t
_cairo_format_from_content (cairo_content_t content) cairo_const;
_cairo_format_from_content (cairo_content_t content) cairo_pure;
cairo_private cairo_content_t
_cairo_content_from_format (cairo_format_t format) cairo_const;
_cairo_content_from_format (cairo_format_t format) cairo_pure;
cairo_private cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
@ -2230,10 +2207,10 @@ cairo_private cairo_image_transparency_t
_cairo_image_analyze_transparency (cairo_image_surface_t *image);
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface) cairo_pure;
_cairo_surface_is_image (const cairo_surface_t *surface);
cairo_private cairo_bool_t
_cairo_surface_is_meta (const cairo_surface_t *surface) cairo_pure;
_cairo_surface_is_meta (const cairo_surface_t *surface);
/* cairo-pen.c */
cairo_private cairo_status_t
@ -2358,31 +2335,31 @@ _cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
cairo_bool_t *is_tight);
cairo_private cairo_bool_t
_cairo_matrix_is_invertible (const cairo_matrix_t *matrix) cairo_pure;
_cairo_matrix_is_invertible (const cairo_matrix_t *matrix);
cairo_private double
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix) cairo_pure;
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix);
cairo_private cairo_status_t
_cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix,
double *sx, double *sy, int x_major);
cairo_private cairo_bool_t
_cairo_matrix_is_identity (const cairo_matrix_t *matrix) cairo_pure;
_cairo_matrix_is_identity (const cairo_matrix_t *matrix);
cairo_private cairo_bool_t
_cairo_matrix_is_translation (const cairo_matrix_t *matrix) cairo_pure;
_cairo_matrix_is_translation (const cairo_matrix_t *matrix);
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_pure;
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix);
cairo_private double
_cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
double radius) cairo_pure;
double radius);
cairo_private void
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
@ -2470,14 +2447,10 @@ _cairo_slope_init (cairo_slope_t *slope,
const cairo_point_t *b);
cairo_private int
_cairo_slope_compare (const cairo_slope_t *a,
const cairo_slope_t *b) cairo_pure;
_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b);
/* cairo-pattern.c */
cairo_private cairo_pattern_t *
_cairo_pattern_create_in_error (cairo_status_t status);
cairo_private cairo_status_t
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
const cairo_pattern_t *other);
@ -2486,10 +2459,6 @@ cairo_private cairo_status_t
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other);
cairo_private void
_cairo_pattern_init_static_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);
@ -2515,9 +2484,6 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
cairo_private void
_cairo_pattern_fini (cairo_pattern_t *pattern);
cairo_private void
_cairo_pattern_fini_snapshot (cairo_pattern_t *pattern);
cairo_private cairo_pattern_t *
_cairo_pattern_create_solid (const cairo_color_t *color,
cairo_content_t content);
@ -2532,10 +2498,6 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
cairo_private cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
enum {
CAIRO_PATTERN_ACQUIRE_NONE = 0x0,
CAIRO_PATTERN_ACQUIRE_NO_REFLECT = 0x1,
};
cairo_private cairo_int_status_t
_cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_surface_t *dst,
@ -2544,7 +2506,6 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
int y,
unsigned int width,
unsigned int height,
unsigned int flags,
cairo_surface_t **surface_out,
cairo_surface_attributes_t *attributes);
@ -2564,7 +2525,6 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
int mask_y,
unsigned int width,
unsigned int height,
unsigned int flags,
cairo_surface_t **src_out,
cairo_surface_t **mask_out,
cairo_surface_attributes_t *src_attributes,
@ -2728,7 +2688,6 @@ 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_rgb);
slim_hidden_proto (cairo_set_source_surface);
slim_hidden_proto (cairo_set_tolerance);
slim_hidden_proto (cairo_status);
@ -2768,7 +2727,6 @@ slim_hidden_proto (cairo_user_to_device_distance);
slim_hidden_proto (cairo_version_string);
slim_hidden_proto (cairo_region_create);
slim_hidden_proto (cairo_region_create_rectangle);
slim_hidden_proto (cairo_region_create_rectangles);
slim_hidden_proto (cairo_region_copy);
slim_hidden_proto (cairo_region_destroy);
slim_hidden_proto (cairo_region_status);
@ -2801,16 +2759,12 @@ CAIRO_END_DECLS
#include "cairo-hash-private.h"
#if HAVE_VALGRIND
#include <memcheck.h>
#define VG(x) x
cairo_private void
_cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface);
#else
#define VG(x)
#define _cairo_debug_check_image_surface_is_defined(X)
#endif