Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3958 → Rev 3959

/programs/develop/libraries/cairo/src/cairo-scaled-font.c
40,7 → 40,11
 
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-list-inline.h"
#include "cairo-pattern-private.h"
#include "cairo-scaled-font-private.h"
#include "cairo-surface-backend-private.h"
 
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
#define ISFINITE(x) isfinite (x)
56,8 → 60,11
*
* #cairo_scaled_font_t represents a realization of a font face at a particular
* size and transformation and a certain set of font options.
*/
**/
 
static uint32_t
_cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font);
 
/* Global Glyph Cache
*
* We maintain a global pool of glyphs split between all active fonts. This
197,10 → 204,15
_cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
const cairo_surface_backend_t *surface_backend = scaled_font->surface_backend;
while (! cairo_list_is_empty (&scaled_glyph->dev_privates)) {
cairo_scaled_glyph_private_t *private =
cairo_list_first_entry (&scaled_glyph->dev_privates,
cairo_scaled_glyph_private_t,
link);
private->destroy (private, scaled_glyph, scaled_font);
}
 
if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL)
surface_backend->scaled_glyph_fini (scaled_glyph, scaled_font);
_cairo_image_scaled_glyph_fini (scaled_font, scaled_glyph);
 
if (scaled_glyph->surface != NULL)
cairo_surface_destroy (&scaled_glyph->surface->base);
241,8 → 253,7
{ NULL, NULL }, /* pages */
FALSE, /* cache_frozen */
FALSE, /* global_cache_frozen */
NULL, /* surface_backend */
NULL, /* surface_private */
{ NULL, NULL }, /* privates */
NULL /* backend */
};
 
309,6 → 320,8
*
* Return value: %CAIRO_STATUS_SUCCESS or another error such as
* %CAIRO_STATUS_NO_MEMORY.
*
* Since: 1.0
**/
cairo_status_t
cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
436,14 → 449,16
CLEANUP_MUTEX_LOCK:
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
 
static void
_cairo_scaled_glyph_page_destroy (void *closure)
_cairo_scaled_glyph_page_destroy (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_page_t *page)
{
cairo_scaled_glyph_page_t *page = closure;
cairo_scaled_font_t *scaled_font;
unsigned int n;
 
scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
assert (!scaled_font->cache_frozen);
assert (!scaled_font->global_cache_frozen);
 
for (n = 0; n < page->num_glyphs; n++) {
_cairo_hash_table_remove (scaled_font->glyphs,
&page->glyphs[n].hash_entry);
451,10 → 466,24
}
 
cairo_list_del (&page->link);
 
free (page);
}
 
static void
_cairo_scaled_glyph_page_pluck (void *closure)
{
cairo_scaled_glyph_page_t *page = closure;
cairo_scaled_font_t *scaled_font;
 
assert (! cairo_list_is_empty (&page->link));
 
scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
 
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_glyph_page_destroy (scaled_font, page);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
 
/* If a scaled font wants to unlock the font map while still being
* created (needed for user-fonts), we need to take extra care not
* ending up with multiple identical scaled fonts being created.
499,6 → 528,8
 
placeholder_scaled_font->placeholder = TRUE;
 
placeholder_scaled_font->hash_entry.hash
= _cairo_scaled_font_compute_hash (placeholder_scaled_font);
status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
&placeholder_scaled_font->hash_entry);
if (unlikely (status))
524,6 → 555,9
 
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
 
/* temporary hash value to match the placeholder */
scaled_font->hash_entry.hash
= _cairo_scaled_font_compute_hash (scaled_font);
placeholder_scaled_font =
_cairo_hash_table_lookup (cairo_scaled_font_map->hash_table,
&scaled_font->hash_entry);
595,6 → 629,26
return hash;
}
 
static uint32_t
_cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font)
{
uint32_t hash = FNV1_32_INIT;
 
/* We do a bytewise hash on the font matrices */
hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash);
hash = _hash_matrix_fnv (&scaled_font->ctm, hash);
hash = _hash_mix_bits (hash);
 
hash ^= (unsigned long) scaled_font->original_font_face;
hash ^= cairo_font_options_hash (&scaled_font->options);
 
/* final mixing of bits */
hash = _hash_mix_bits (hash);
assert (hash != ZOMBIE);
 
return hash;
}
 
static void
_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
cairo_font_face_t *font_face,
602,11 → 656,10
const cairo_matrix_t *ctm,
const cairo_font_options_t *options)
{
uint32_t hash = FNV1_32_INIT;
 
scaled_font->status = CAIRO_STATUS_SUCCESS;
scaled_font->placeholder = FALSE;
scaled_font->font_face = font_face;
scaled_font->original_font_face = font_face;
scaled_font->font_matrix = *font_matrix;
scaled_font->ctm = *ctm;
/* ignore translation values in the ctm */
614,19 → 667,8
scaled_font->ctm.y0 = 0.;
_cairo_font_options_init_copy (&scaled_font->options, options);
 
/* We do a bytewise hash on the font matrices */
hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash);
hash = _hash_matrix_fnv (&scaled_font->ctm, hash);
hash = _hash_mix_bits (hash);
 
hash ^= (unsigned long) scaled_font->font_face;
hash ^= cairo_font_options_hash (&scaled_font->options);
 
/* final mixing of bits */
hash = _hash_mix_bits (hash);
 
assert (hash != ZOMBIE);
scaled_font->hash_entry.hash = hash;
scaled_font->hash_entry.hash =
_cairo_scaled_font_compute_hash (scaled_font);
}
 
static cairo_bool_t
636,10 → 678,7
const cairo_scaled_font_t *key_a = abstract_key_a;
const cairo_scaled_font_t *key_b = abstract_key_b;
 
if (key_a->hash_entry.hash != key_b->hash_entry.hash)
return FALSE;
 
return key_a->font_face == key_b->font_face &&
return key_a->original_font_face == key_b->original_font_face &&
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
(unsigned char *)(&key_b->font_matrix.xx),
sizeof(cairo_matrix_t)) == 0 &&
666,15 → 705,6
cairo_font_options_equal (&scaled_font->options, options);
}
 
static cairo_bool_t
_cairo_scaled_glyphs_equal (const void *abstract_a, const void *abstract_b)
{
const cairo_scaled_glyph_t *a = abstract_a;
const cairo_scaled_glyph_t *b = abstract_b;
 
return a->hash_entry.hash == b->hash_entry.hash;
}
 
/*
* Basic #cairo_scaled_font_t object management
*/
693,8 → 723,16
if (unlikely (status))
return status;
 
_cairo_scaled_font_init_key (scaled_font, font_face,
font_matrix, ctm, options);
scaled_font->status = CAIRO_STATUS_SUCCESS;
scaled_font->placeholder = FALSE;
scaled_font->font_face = font_face;
scaled_font->original_font_face = font_face;
scaled_font->font_matrix = *font_matrix;
scaled_font->ctm = *ctm;
/* ignore translation values in the ctm */
scaled_font->ctm.x0 = 0.;
scaled_font->ctm.y0 = 0.;
_cairo_font_options_init_copy (&scaled_font->options, options);
 
cairo_matrix_multiply (&scaled_font->scale,
&scaled_font->font_matrix,
723,7 → 761,7
return status;
}
 
scaled_font->glyphs = _cairo_hash_table_create (_cairo_scaled_glyphs_equal);
scaled_font->glyphs = _cairo_hash_table_create (NULL);
if (unlikely (scaled_font->glyphs == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
743,8 → 781,7
 
CAIRO_MUTEX_INIT (scaled_font->mutex);
 
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
cairo_list_init (&scaled_font->dev_privates);
 
scaled_font->backend = backend;
cairo_list_init (&scaled_font->link);
765,16 → 802,16
void
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
{
scaled_font->cache_frozen = FALSE;
assert (scaled_font->cache_frozen);
 
if (scaled_font->global_cache_frozen) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
_cairo_cache_thaw (&cairo_scaled_glyph_page_cache);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
 
scaled_font->global_cache_frozen = FALSE;
}
 
scaled_font->cache_frozen = FALSE;
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
 
781,16 → 818,24
void
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
{
CAIRO_MUTEX_LOCK (scaled_font->mutex);
assert (! scaled_font->cache_frozen);
 
assert (! scaled_font->global_cache_frozen);
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
while (! cairo_list_is_empty (&scaled_font->glyph_pages)) {
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&cairo_list_first_entry (&scaled_font->glyph_pages,
cairo_scaled_glyph_page_t *page =
cairo_list_first_entry (&scaled_font->glyph_pages,
cairo_scaled_glyph_page_t,
link)->cache_entry);
link);
 
cairo_scaled_glyph_page_cache.size -= page->cache_entry.size;
_cairo_hash_table_remove (cairo_scaled_glyph_page_cache.hash_table,
(cairo_hash_entry_t *) &page->cache_entry);
 
_cairo_scaled_glyph_page_destroy (scaled_font, page);
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
 
cairo_status_t
825,6 → 870,8
static void
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
{
assert (! scaled_font->cache_frozen);
assert (! scaled_font->global_cache_frozen);
scaled_font->finished = TRUE;
 
_cairo_scaled_font_reset_cache (scaled_font);
835,9 → 882,13
 
CAIRO_MUTEX_FINI (scaled_font->mutex);
 
if (scaled_font->surface_backend != NULL &&
scaled_font->surface_backend->scaled_font_fini != NULL)
scaled_font->surface_backend->scaled_font_fini (scaled_font);
while (! cairo_list_is_empty (&scaled_font->dev_privates)) {
cairo_scaled_font_private_t *private =
cairo_list_first_entry (&scaled_font->dev_privates,
cairo_scaled_font_private_t,
link);
private->destroy (private, scaled_font);
}
 
if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL)
scaled_font->backend->fini (scaled_font);
845,32 → 896,79
_cairo_user_data_array_fini (&scaled_font->user_data);
}
 
/* XXX: allow multiple backends to share the font */
void
_cairo_scaled_font_revoke_ownership (cairo_scaled_font_t *scaled_font)
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
if (scaled_font->surface_backend == NULL)
return;
/* Release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called. */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini_internal (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
 
_cairo_scaled_font_reset_cache (scaled_font);
void
_cairo_scaled_font_attach_private (cairo_scaled_font_t *scaled_font,
cairo_scaled_font_private_t *private,
const void *key,
void (*destroy) (cairo_scaled_font_private_t *,
cairo_scaled_font_t *))
{
private->key = key;
private->destroy = destroy;
cairo_list_add (&private->link, &scaled_font->dev_privates);
}
 
if (scaled_font->surface_backend->scaled_font_fini != NULL)
scaled_font->surface_backend->scaled_font_fini (scaled_font);
cairo_scaled_font_private_t *
_cairo_scaled_font_find_private (cairo_scaled_font_t *scaled_font,
const void *key)
{
cairo_scaled_font_private_t *priv;
 
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
cairo_list_foreach_entry (priv, cairo_scaled_font_private_t,
&scaled_font->dev_privates, link)
{
if (priv->key == key) {
if (priv->link.prev != &scaled_font->dev_privates)
cairo_list_move (&priv->link, &scaled_font->dev_privates);
return priv;
}
}
 
return NULL;
}
 
void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
_cairo_scaled_glyph_attach_private (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_private_t *private,
const void *key,
void (*destroy) (cairo_scaled_glyph_private_t *,
cairo_scaled_glyph_t *,
cairo_scaled_font_t *))
{
/* Release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called. */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini_internal (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
private->key = key;
private->destroy = destroy;
cairo_list_add (&private->link, &scaled_glyph->dev_privates);
}
 
cairo_scaled_glyph_private_t *
_cairo_scaled_glyph_find_private (cairo_scaled_glyph_t *scaled_glyph,
const void *key)
{
cairo_scaled_glyph_private_t *priv;
 
cairo_list_foreach_entry (priv, cairo_scaled_glyph_private_t,
&scaled_glyph->dev_privates, link)
{
if (priv->key == key) {
if (priv->link.prev != &scaled_glyph->dev_privates)
cairo_list_move (&priv->link, &scaled_glyph->dev_privates);
return priv;
}
}
 
return NULL;
}
 
/**
* cairo_scaled_font_create:
* @font_face: a #cairo_font_face_t
890,6 → 988,8
*
* Return value: a newly created #cairo_scaled_font_t. Destroy with
* cairo_scaled_font_destroy()
*
* Since: 1.0
**/
cairo_scaled_font_t *
cairo_scaled_font_create (cairo_font_face_t *font_face,
950,38 → 1050,10
scaled_font->hash_entry.hash = ZOMBIE;
dead = scaled_font;
font_map->mru_scaled_font = NULL;
 
if (font_face->backend->get_implementation != NULL) {
font_face = font_face->backend->get_implementation (font_face,
font_matrix,
ctm,
options);
if (unlikely (font_face->status)) {
_cairo_scaled_font_map_unlock ();
cairo_scaled_font_destroy (scaled_font);
return _cairo_scaled_font_create_in_error (font_face->status);
}
}
 
_cairo_scaled_font_init_key (&key, 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);
if (unlikely (font_face->status)) {
_cairo_scaled_font_map_unlock ();
return _cairo_scaled_font_create_in_error (font_face->status);
}
}
_cairo_scaled_font_init_key (&key, 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)))
{
993,7 → 1065,6
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
}
 
/* Return existing scaled_font if it exists in the hash table. */
if (scaled_font != NULL) {
/* If the original reference count is 0, then this font must have
* been found in font_map->holdovers, (which means this caching is
1047,9 → 1118,20
&scaled_font->hash_entry);
scaled_font->hash_entry.hash = ZOMBIE;
}
 
 
/* Otherwise create it and insert it into the hash table. */
if (font_face->backend->get_implementation != NULL) {
font_face = font_face->backend->get_implementation (font_face,
font_matrix,
ctm,
options);
if (unlikely (font_face->status)) {
_cairo_scaled_font_map_unlock ();
return _cairo_scaled_font_create_in_error (font_face->status);
}
}
 
/* Otherwise create it and insert it into the hash table. */
status = font_face->backend->scaled_font_create (font_face, font_matrix,
ctm, options, &scaled_font);
/* Did we leave the backend in an error state? */
1081,10 → 1163,14
* ft-font-faces
*/
assert (scaled_font->font_face == font_face);
assert (! scaled_font->cache_frozen);
assert (! scaled_font->global_cache_frozen);
 
scaled_font->original_font_face =
cairo_font_face_reference (original_font_face);
 
scaled_font->hash_entry.hash = _cairo_scaled_font_compute_hash(scaled_font);
 
status = _cairo_hash_table_insert (font_map->hash_table,
&scaled_font->hash_entry);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
1157,11 → 1243,9
status <= CAIRO_STATUS_LAST_STATUS;
status++)
{
if (_cairo_scaled_font_nil_objects[status] != NULL) {
free (_cairo_scaled_font_nil_objects[status]);
_cairo_scaled_font_nil_objects[status] = NULL;
}
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
 
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
1185,6 → 1269,8
* cairo_scaled_font_get_reference_count().
*
* Returns: the referenced #cairo_scaled_font_t
*
* Since: 1.0
**/
cairo_scaled_font_t *
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
1208,6 → 1294,8
* Decreases the reference count on @font by one. If the result
* is zero, then @font and all associated resources are freed.
* See cairo_scaled_font_reference().
*
* Since: 1.0
**/
void
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
1226,6 → 1314,9
if (! _cairo_reference_count_dec_and_test (&scaled_font->ref_count))
return;
 
assert (! scaled_font->cache_frozen);
assert (! scaled_font->global_cache_frozen);
 
font_map = _cairo_scaled_font_map_lock ();
assert (font_map != NULL);
 
1364,6 → 1455,8
* @extents: a #cairo_font_extents_t which to store the retrieved extents.
*
* Gets the metrics for a #cairo_scaled_font_t.
*
* Since: 1.0
**/
void
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
1461,6 → 1554,8
*
* Note that whitespace glyphs do not contribute to the size of the
* rectangle (extents.width and extents.height).
*
* Since: 1.0
**/
void
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
1856,7 → 1951,7
cairo_text_cluster_flags_t *cluster_flags)
{
int num_chars = 0;
cairo_status_t status;
cairo_int_status_t status;
cairo_glyph_t *orig_glyphs;
cairo_text_cluster_t *orig_clusters;
 
1939,7 → 2034,7
clusters, num_clusters,
cluster_flags);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
if (status == CAIRO_STATUS_SUCCESS) {
if (status == CAIRO_INT_STATUS_SUCCESS) {
/* The checks here are crude; we only should do them in
* user-font backend, but they don't hurt here. This stuff
* can be hard to get right. */
2051,6 → 2146,9
cairo_fixed_t right,
cairo_fixed_t bottom)
{
if (left == right || top == bottom)
return FALSE;
 
return right > extents->p1.x &&
left < extents->p2.x &&
bottom > extents->p1.y &&
2057,6 → 2155,44
top < extents->p2.y;
}
 
static cairo_status_t
_cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyph,
cairo_rectangle_int_t *extents)
{
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
 
_cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph->index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
cairo_bool_t round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options) == CAIRO_ROUND_GLYPH_POS_ON;
cairo_box_t box;
cairo_fixed_t v;
 
if (round_xy)
v = _cairo_fixed_from_int (_cairo_lround (glyph->x));
else
v = _cairo_fixed_from_double (glyph->x);
box.p1.x = v + scaled_glyph->bbox.p1.x;
box.p2.x = v + scaled_glyph->bbox.p2.x;
 
if (round_xy)
v = _cairo_fixed_from_int (_cairo_lround (glyph->y));
else
v = _cairo_fixed_from_double (glyph->y);
box.p1.y = v + scaled_glyph->bbox.p1.y;
box.p2.y = v + scaled_glyph->bbox.p2.y;
 
_cairo_box_round_to_rectangle (&box, extents);
}
_cairo_scaled_font_thaw_cache (scaled_font);
return status;
}
 
/*
* Compute a device-space bounding box for the glyphs.
*/
2071,11 → 2207,20
cairo_box_t box = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN }};
cairo_scaled_glyph_t *glyph_cache[64];
cairo_bool_t overlap = overlap_out ? FALSE : TRUE;
cairo_round_glyph_positions_t round_glyph_positions = _cairo_font_options_get_round_glyph_positions (&scaled_font->options);
int i;
 
if (unlikely (scaled_font->status))
return scaled_font->status;
 
if (num_glyphs == 1) {
if (overlap_out)
*overlap_out = FALSE;
return _cairo_scaled_font_single_glyph_device_extents (scaled_font,
glyphs,
extents);
}
 
_cairo_scaled_font_freeze_cache (scaled_font);
 
memset (glyph_cache, 0, sizeof (glyph_cache));
2099,10 → 2244,16
glyph_cache[cache_index] = scaled_glyph;
}
 
if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON)
x = _cairo_fixed_from_int (_cairo_lround (glyphs[i].x));
else
x = _cairo_fixed_from_double (glyphs[i].x);
x1 = x + scaled_glyph->bbox.p1.x;
x2 = x + scaled_glyph->bbox.p2.x;
 
if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON)
y = _cairo_fixed_from_int (_cairo_lround (glyphs[i].y));
else
y = _cairo_fixed_from_double (glyphs[i].y);
y1 = y + scaled_glyph->bbox.p1.y;
y2 = y + scaled_glyph->bbox.p2.y;
2133,17 → 2284,28
return CAIRO_STATUS_SUCCESS;
}
 
void
cairo_bool_t
_cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_rectangle_int_t *extents)
{
double x0 = HUGE_VAL, x1 = -HUGE_VAL;
double y0 = HUGE_VAL, y1 = -HUGE_VAL;
double x0, x1, y0, y1, pad;
int i;
 
for (i = 0; i < num_glyphs; i++) {
/* If any of the factors are suspect (i.e. the font is broken), bail */
if (scaled_font->fs_extents.max_x_advance == 0 ||
scaled_font->fs_extents.height == 0 ||
scaled_font->max_scale == 0)
{
return FALSE;
}
 
assert (num_glyphs);
 
x0 = x1 = glyphs[0].x;
y0 = y1 = glyphs[0].y;
for (i = 1; i < num_glyphs; i++) {
double g;
 
g = glyphs[i].x;
2155,20 → 2317,19
if (g > y1) y1 = g;
}
 
if (x0 <= x1 && y0 <= y1) {
extents->x = floor (x0 - scaled_font->extents.max_x_advance);
extents->width = ceil (x1 + scaled_font->extents.max_x_advance);
extents->width -= extents->x;
pad = MAX(scaled_font->fs_extents.max_x_advance,
scaled_font->fs_extents.height);
pad *= scaled_font->max_scale;
 
extents->y = floor (y0 - scaled_font->extents.ascent);
extents->height = ceil (y1 + scaled_font->extents.descent);
extents->height -= extents->y;
} else {
extents->x = extents->y = 0;
extents->width = extents->height = 0;
extents->x = floor (x0 - pad);
extents->width = ceil (x1 + pad) - extents->x;
extents->y = floor (y0 - pad);
extents->height = ceil (y1 + pad) - extents->y;
return TRUE;
}
}
 
#if 0
/* XXX win32 */
cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
2184,7 → 2345,7
int num_glyphs,
cairo_region_t *clip_region)
{
cairo_status_t status;
cairo_int_status_t status;
cairo_surface_t *mask = NULL;
cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */
cairo_surface_pattern_t mask_pattern;
2215,7 → 2376,7
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
status = CAIRO_STATUS_SUCCESS;
status = CAIRO_INT_STATUS_SUCCESS;
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_scaled_font_set_error (scaled_font, status);
}
2265,6 → 2426,7
break;
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
2358,6 → 2520,7
cairo_surface_destroy (mask);
return _cairo_scaled_font_set_error (scaled_font, status);
}
#endif
 
/* Add a single-device-unit rectangle to a path. */
static cairo_status_t
2470,7 → 2633,7
int num_glyphs,
cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_int_status_t status;
int i;
 
status = scaled_font->status;
2485,9 → 2648,9
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status == CAIRO_STATUS_SUCCESS) {
if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_path_fixed_append (path,
scaled_glyph->path, CAIRO_DIRECTION_FORWARD,
scaled_glyph->path,
_cairo_fixed_from_double (glyphs[i].x),
_cairo_fixed_from_double (glyphs[i].y));
 
2672,6 → 2835,8
cairo_scaled_glyph_page_t *page;
cairo_status_t status;
 
assert (scaled_font->cache_frozen);
 
/* only the first page in the list may contain available slots */
if (! cairo_list_is_empty (&scaled_font->glyph_pages)) {
page = cairo_list_last_entry (&scaled_font->glyph_pages,
2697,7 → 2862,7
status = _cairo_cache_init (&cairo_scaled_glyph_page_cache,
NULL,
_cairo_scaled_glyph_page_can_remove,
_cairo_scaled_glyph_page_destroy,
_cairo_scaled_glyph_page_pluck,
MAX_GLYPH_PAGES_CACHED);
if (unlikely (status)) {
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
2739,8 → 2904,14
_cairo_scaled_glyph_fini (scaled_font, scaled_glyph);
 
if (--page->num_glyphs == 0) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
/* Temporarily disconnect callback to avoid recursive locking */
cairo_scaled_glyph_page_cache.entry_destroy = NULL;
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&page->cache_entry);
_cairo_scaled_glyph_page_destroy (scaled_font, page);
cairo_scaled_glyph_page_cache.entry_destroy = _cairo_scaled_glyph_page_pluck;
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
}
 
2777,7 → 2948,7
cairo_scaled_glyph_info_t info,
cairo_scaled_glyph_t **scaled_glyph_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
cairo_scaled_glyph_info_t need_info;
 
2786,6 → 2957,9
if (unlikely (scaled_font->status))
return scaled_font->status;
 
assert (CAIRO_MUTEX_IS_LOCKED(scaled_font->mutex));
assert (scaled_font->cache_frozen);
 
if (CAIRO_INJECT_FAULT ())
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2801,6 → 2975,7
 
memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t));
_cairo_scaled_glyph_set_index (scaled_glyph, index);
cairo_list_init (&scaled_glyph->dev_privates);
 
/* ask backend to initialize metrics and shape fields */
status =
2861,11 → 3036,13
* cairo_scaled_font_get_font_face:
* @scaled_font: a #cairo_scaled_font_t
*
* Gets the font face that this scaled font uses. This is the
* font face passed to cairo_scaled_font_create().
* Gets the font face that this scaled font uses. This might be the
* font face passed to cairo_scaled_font_create(), but this does not
* hold true for all possible cases.
*
* Return value: The #cairo_font_face_t with which @scaled_font was
* created.
* created. This object is owned by cairo. To keep a reference to it,
* you must call cairo_scaled_font_reference().
*
* Since: 1.2
**/