/* XXX: This number is arbitrary---we've never done any measurement of this. */ #define MAX_GLYPH_PAGES_CACHED 512 static cairo_cache_t cairo_scaled_glyph_page_cache;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&scaled_font->status, status);
/* Here we keep a unique mapping from *font_face/matrix/ctm/font_options=>#cairo_scaled_font_t. * *Herearethethingsthatwewanttomap: * *a)Allotherwisereferenced#cairo_scaled_font_t's *b)Somenumberofnototherwisereferenced#cairo_scaled_font_t's * *Theimplementationusesahashtablewhichcovers(a) *completely.Then,for(b)wehaveanarrayofotherwise *unreferencedfonts(holdovers)whichareexpiredin *least-recently-usedorder. * *Thecairo_scaled_font_create()codegetstotreatthislikearegular *hashtable.Allofthemagicforthelittleholdovercacheisin *cairo_scaled_font_reference()andcairo_scaled_font_destroy().
*/
/* This defines the size of the holdover array ... that is, the number *ofscaledfontswekeeparoundevenwhennototherwisereferenced
*/ #define CAIRO_SCALED_FONT_MAX_HOLDOVERS 256
/* remove scaled_fonts starting from the end so that font_map->holdovers
* is always in a consistent state when we release the mutex. */ while (font_map->num_holdovers) {
scaled_font = font_map->holdovers[font_map->num_holdovers-1];
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
font_map->num_holdovers--;
/* This releases the font_map lock to avoid the possibility of a *recursivedeadlockwhenthescaledfontdestroyclosuregets *called
*/
_cairo_scaled_font_fini (scaled_font);
/* The font is locked in _cairo_scaled_glyph_page_can_remove () */
_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(neededforuser-fonts),weneedtotakeextracarenot *endingupwithmultipleidenticalscaledfontsbeingcreated. * *Whatwedois,wecreateafakeidenticalscaledfont,andmark *itasplaceholder,lockitsmutex,andinsertthatinthefontmap *hashtable.Thismakesothercodetryingtocreateanidentical *scaledfonttojustwaitandretry. * *Thereasonwehavetocreateafakescaledfontinsteadofjustusing *scaled_fontisforlifecyclemanagement:weneedto(orrather, *othercodeneedsto)referencethescaled_fontinthehashtable. *Wecan'tdothatontheinputscaled_fontasitmaybefreedby *fontbackenduponerror.
*/
/* full initialization is wasteful, but who cares... */
status = _cairo_scaled_font_init (placeholder_scaled_font,
scaled_font->font_face,
&scaled_font->font_matrix,
&scaled_font->ctm,
&scaled_font->options,
NULL); if (unlikely (status)) goto FREE_PLACEHOLDER;
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)) goto FINI_PLACEHOLDER;
staticvoid
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font)
{ /* reference the place holder so it doesn't go away */
cairo_scaled_font_reference (placeholder_scaled_font);
/* now unlock the fontmap mutex so creation has a chance to finish */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
/* wait on placeholder mutex until we are awaken */
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
/* ok, creation done. just clean up and back out */
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
cairo_scaled_font_destroy (placeholder_scaled_font);
/* 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);
staticvoid _cairo_scaled_font_free_recording_surfaces (cairo_scaled_font_t *scaled_font)
{ int num_recording_surfaces;
cairo_surface_t *surface;
num_recording_surfaces = _cairo_array_num_elements (&scaled_font->recording_surfaces_to_free); if (num_recording_surfaces > 0) { for (int i = 0; i < num_recording_surfaces; i++) {
_cairo_array_copy_element (&scaled_font->recording_surfaces_to_free, i, &surface);
cairo_surface_finish (surface);
cairo_surface_destroy (surface);
}
_cairo_array_truncate (&scaled_font->recording_surfaces_to_free, 0);
}
}
void
_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
{ /* ensure we do not modify an error object */
assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
/* Destroy scaled_font's pages while holding its lock only, and not the *globalpagecachelock.Thedestructorcancauseustorecurseand
* end up back here for a different scaled_font. */
void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{ /* Release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called. */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini_internal (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) { /* We increment the reference count manually here, (rather *thancallingintocairo_scaled_font_reference),sincewe *mustmodifythereferencecountwhileourlockisstill
* held. */
_cairo_reference_count_inc (&scaled_font->ref_count);
_cairo_scaled_font_map_unlock (); return scaled_font;
}
/* the font has been put into an error status - abandon the cache */
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
scaled_font->hash_entry.hash = ZOMBIE;
dead = scaled_font;
font_map->mru_scaled_font = NULL;
}
while ((scaled_font = _cairo_hash_table_lookup (font_map->hash_table,
&key.hash_entry)))
{ if (! scaled_font->placeholder) break;
/* If the scaled font is being created (happens for user-font),
* just wait until it's done, then retry */
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
}
_cairo_scaled_font_fini_key (&key);
if (scaled_font != NULL) { /* If the original reference count is 0, then this font must have *beenfoundinfont_map->holdovers,(whichmeansthiscachingis *actuallyworking).Sonowweremoveitfromtheholdovers *array,unlesswecaughtthefontinthemiddleofdestruction.
*/ if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) { if (scaled_font->holdover) { 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;
}
}
scaled_font->holdover = FALSE;
}
/* reset any error status */
scaled_font->status = CAIRO_STATUS_SUCCESS;
}
if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) { /* We increment the reference count manually here, (rather *thancallingintocairo_scaled_font_reference),sincewe *mustmodifythereferencecountwhileourlockisstill
* held. */
old = font_map->mru_scaled_font;
font_map->mru_scaled_font = scaled_font; /* increment reference count for the mru cache */
_cairo_reference_count_inc (&scaled_font->ref_count); /* and increment for the returned reference */
_cairo_reference_count_inc (&scaled_font->ref_count);
_cairo_scaled_font_map_unlock ();
cairo_scaled_font_destroy (old); if (font_face != original_font_face)
cairo_font_face_destroy (font_face);
return scaled_font;
}
/* the font has been put into an error status - abandon the cache */
_cairo_hash_table_remove (font_map->hash_table,
&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);
}
}
status = font_face->backend->scaled_font_create (font_face, font_matrix,
ctm, options, &scaled_font); if (unlikely (status)) {
_cairo_scaled_font_map_unlock (); if (font_face != original_font_face)
cairo_font_face_destroy (font_face);
if (dead != NULL)
cairo_scaled_font_destroy (dead);
return _cairo_scaled_font_create_in_error (status);
} /* Or did we encounter an error whilst constructing the scaled font? */ if (unlikely (scaled_font->status)) {
_cairo_scaled_font_map_unlock (); if (font_face != original_font_face)
cairo_font_face_destroy (font_face);
if (dead != NULL)
cairo_scaled_font_destroy (dead);
return scaled_font;
}
/* Our caching above is defeated if the backend switches fonts on us - *e.g.oldincarnationsoftoy-font-faceandlazilyresolved *ft-font-faces
*/
assert (scaled_font->font_face == font_face);
assert (! scaled_font->cache_frozen);
assert (! scaled_font->global_cache_frozen);
/* XXX This should disappear in favour of a common pool of error objects. */
cairo_scaled_font_t *
_cairo_scaled_font_create_in_error (cairo_status_t status)
{
cairo_scaled_font_t *scaled_font;
assert (status != CAIRO_STATUS_SUCCESS);
if (status == CAIRO_STATUS_NO_MEMORY) return (cairo_scaled_font_t *) &_cairo_scaled_font_nil;
/* Another thread may have resurrected the font whilst we waited */ if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&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 *thefont_map->holdoversarrayincaseitwillgetusedagain *soon(andiswhywemustholdthelockovertheatomicopon *thereferencecount).Tomakeroomforit,wedoactually *destroytheleast-recently-usedholdover.
*/
/* If we pulled an item from the holdovers array, (while the font *maplockwasheld,ofcourse),thenthereisnowaythatanyone *elsecouldhaveacquiredareferencetoit.Sowecannow *safelycallfinionitwithoutanylockheld.Thisisdesirable *asweneverwanttocallintoanybackendfunctionwithalock
* held. */ if (lru != NULL) {
_cairo_scaled_font_fini_internal (lru);
free (lru);
}
}
for (i = 0; i < num_glyphs; i++) { double left, top, right, bottom;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
NULL, /* foreground color */
&scaled_glyph); if (unlikely (status)) {
status = _cairo_scaled_font_set_error (scaled_font, status); goto UNLOCK;
}
/* "Ink" extents should skip "invisible" glyphs */ if (scaled_glyph->metrics.width == 0 || scaled_glyph->metrics.height == 0) continue;
left = scaled_glyph->metrics.x_bearing + glyphs[i].x;
right = left + scaled_glyph->metrics.width;
top = scaled_glyph->metrics.y_bearing + glyphs[i].y;
bottom = top + scaled_glyph->metrics.height;
for (i = 0; i < GLYPH_LUT_SIZE; i++)
glyph_lut_unicode[i] = ~0U;
p = utf8; for (i = 0; i < num_chars; i++) { int idx, num_bytes;
uint32_t unicode;
cairo_scaled_glyph_t *scaled_glyph; struct glyph_lut_elt *glyph_slot;
num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
p += num_bytes;
glyphs[i].x = x;
glyphs[i].y = y;
idx = unicode % ARRAY_LENGTH (glyph_lut);
glyph_slot = &glyph_lut[idx]; if (glyph_lut_unicode[idx] == unicode) {
glyphs[i].index = glyph_slot->index;
x += glyph_slot->x_advance;
y += glyph_slot->y_advance;
} else { unsignedlong g;
g = scaled_font->backend->ucs4_to_index (scaled_font, unicode);
status = _cairo_scaled_glyph_lookup (scaled_font,
g,
CAIRO_SCALED_GLYPH_INFO_METRICS,
NULL, /* foreground color */
&scaled_glyph); if (unlikely (status)) return status;
x += scaled_glyph->metrics.x_advance;
y += scaled_glyph->metrics.y_advance;
static cairo_status_t
cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t *scaled_font, double x, double y, constchar *utf8,
cairo_glyph_t *glyphs,
cairo_text_cluster_t **clusters, int num_chars)
{ constchar *p; int i;
p = utf8; for (i = 0; i < num_chars; i++) { unsignedlong g; int num_bytes;
uint32_t unicode;
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
p += num_bytes;
glyphs[i].x = x;
glyphs[i].y = y;
g = scaled_font->backend->ucs4_to_index (scaled_font, unicode);
/* *Noadvanceneededforasinglecharacterstring.So,let'sspeedup *one-characterstringsbyskippingglyphlookup.
*/ if (num_chars > 1) {
status = _cairo_scaled_glyph_lookup (scaled_font,
g,
CAIRO_SCALED_GLYPH_INFO_METRICS,
NULL, /* foreground color */
&scaled_glyph); if (unlikely (status)) return status;
x += scaled_glyph->metrics.x_advance;
y += scaled_glyph->metrics.y_advance;
}
if (scaled_font->backend->text_to_glyphs) {
status = scaled_font->backend->text_to_glyphs (scaled_font, x, y,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
cluster_flags); if (status != CAIRO_INT_STATUS_UNSUPPORTED) { if (status == CAIRO_INT_STATUS_SUCCESS) { /* The checks here are crude; we only should do them in *user-fontbackend,buttheydon'thurthere.Thisstuff
* can be hard to get right. */
if (*num_glyphs < 0) {
status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT); goto DONE;
} if (*num_glyphs != 0 && *glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NULL_POINTER); goto DONE;
}
if (clusters) { if (*num_clusters < 0) {
status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT); goto DONE;
} if (*num_clusters != 0 && *clusters == NULL) {
status = _cairo_error (CAIRO_STATUS_NULL_POINTER); goto DONE;
}
/* Don't trust the backend, validate clusters! */
status =
_cairo_validate_text_clusters (utf8, utf8_len,
*glyphs, *num_glyphs,
*clusters, *num_clusters,
*cluster_flags);
}
}
goto DONE;
}
}
if (*num_glyphs < num_chars) {
*glyphs = cairo_glyph_allocate (num_chars); if (unlikely (*glyphs == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto DONE;
}
}
*num_glyphs = num_chars;
if (clusters) { if (*num_clusters < num_chars) {
*clusters = cairo_text_cluster_allocate (num_chars); if (unlikely (*clusters == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto DONE;
}
}
*num_clusters = num_chars;
}
if (num_chars > CACHING_THRESHOLD)
status = cairo_scaled_font_text_to_glyphs_internal_cached (scaled_font,
x, y,
utf8,
*glyphs,
clusters,
num_chars); else
status = cairo_scaled_font_text_to_glyphs_internal_uncached (scaled_font,
x, y,
utf8,
*glyphs,
clusters,
num_chars);
DONE: /* error that should be logged on scaled_font happened */
_cairo_scaled_font_thaw_cache (scaled_font);
if (unlikely (status)) {
*num_glyphs = 0; if (*glyphs != orig_glyphs) {
cairo_glyph_free (*glyphs);
*glyphs = orig_glyphs;
}
if (clusters) {
*num_clusters = 0; if (*clusters != orig_clusters) {
cairo_text_cluster_free (*clusters);
*clusters = orig_clusters;
}
}
}
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;
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));
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
cairo_fixed_t x, y, x1, y1, x2, y2; 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,
NULL, /* foreground color */
&scaled_glyph); if (unlikely (status)) break;
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;
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, x1, y0, y1, pad; int 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)
{ returnFALSE;
}
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; if (g < x0) x0 = g; if (g > x1) x1 = g;
g = glyphs[i].y; if (g < y0) y0 = g; if (g > y1) y1 = g;
}
pad = MAX(scaled_font->fs_extents.max_x_advance,
scaled_font->fs_extents.height);
pad *= scaled_font->max_scale;
byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (byte); for (bit = 1 << 7; bit && x < mask->width; bit >>= 1, x++) { if (byte & bit) {
px = _cairo_fixed_from_int (x);
status = _add_unit_rectangle_to_path (path,
px + x0,
py + y0); if (unlikely (status)) goto BAIL;
}
}
}
}
BAIL:
cairo_surface_destroy (&mask->base);
return status;
}
cairo_status_t
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs,
cairo_path_fixed_t *path)
{
cairo_int_status_t status; int i;
status = scaled_font->status; if (unlikely (status)) return status;
_cairo_scaled_font_freeze_cache (scaled_font); for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
NULL, /* foreground color */
&scaled_glyph); if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_path_fixed_append (path,
scaled_glyph->path,
_cairo_fixed_from_double (glyphs[i].x),
_cairo_fixed_from_double (glyphs[i].y));
} elseif (status == CAIRO_INT_STATUS_UNSUPPORTED) { /* If the font is incapable of providing a path, then we'll *havetotraceourownfromasurface.
*/
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
NULL, /* foreground color */
&scaled_glyph); if (unlikely (status)) goto BAIL;
status = _trace_mask_to_path (scaled_glyph->surface, path,
glyphs[i].x, glyphs[i].y);
}
if (unlikely (status)) goto BAIL;
}
BAIL:
_cairo_scaled_font_thaw_cache (scaled_font);
/* Transform this corner to user space */
x = fs_metrics->x_bearing + fs_metrics->width * wm;
y = fs_metrics->y_bearing + fs_metrics->height * hm;
cairo_matrix_transform_point (&scaled_font->font_matrix,
&x, &y); if (first) {
min_user_x = max_user_x = x;
min_user_y = max_user_y = y;
} else { if (x < min_user_x) min_user_x = x; if (x > max_user_x) max_user_x = x; if (y < min_user_y) min_user_y = y; if (y > max_user_y) max_user_y = y;
}
/* Transform this corner to device space from glyph origin */
x = fs_metrics->x_bearing + fs_metrics->width * wm;
y = fs_metrics->y_bearing + fs_metrics->height * hm;
cairo_matrix_transform_distance (&scaled_font->scale,
&x, &y);
/* 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,
cairo_scaled_glyph_page_t,
link); if (page->num_glyphs < CAIRO_SCALED_GLYPH_PAGE_SIZE) {
*scaled_glyph = &page->glyphs[page->num_glyphs++]; return CAIRO_STATUS_SUCCESS;
}
}
/* ask backend to initialize metrics and shape fields */
status =
scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
info | CAIRO_SCALED_GLYPH_INFO_METRICS,
foreground_color); if (unlikely (status)) {
_cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph); goto err;
}
status = _cairo_hash_table_insert (scaled_font->glyphs,
&scaled_glyph->hash_entry); if (unlikely (status)) {
_cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph); goto err;
}
}
/* *Checkandseeiftheglyph,asprovided, *alreadyhastherequesteddataandamenditifnot
*/
need_info = info & ~scaled_glyph->has_info;
/* If this is not a color glyph, don't try loading the color surface again. */ if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) &&
scaled_glyph->color_glyph_set && !scaled_glyph->color_glyph) return CAIRO_INT_STATUS_UNSUPPORTED;
/* If requesting a color surface or recording for a glyph that has *usedtheforegroundcolortorendertherecording,andthe
* foreground color has changed, request a new recording. */ if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) &&
scaled_glyph->recording_uses_foreground_color &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
}
/* If requesting a color surface for a glyph that has *usedtheforegroundcolortorenderthecolor_surface,andthe
* foreground color has changed, request a new image. */ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE &&
(scaled_glyph->recording_uses_foreground_marker || scaled_glyph->recording_uses_foreground_color) &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
}
if (need_info) {
status = scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
need_info,
foreground_color); if (unlikely (status)) goto err;
/* Don't trust the scaled_glyph_init() return value, the font *backendmaynotevenknowaboutsomeoftheinfo.Forexample, *nobackendotherthantheuser-fontsknowsaboutrecording-surface
* glyph info. */ if (info & ~scaled_glyph->has_info) return CAIRO_INT_STATUS_UNSUPPORTED;
}
err: /* It's not an error for the backend to not support the info we want. */ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
status = _cairo_scaled_font_set_error (scaled_font, status); return status;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.122Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.