mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 17:28:02 +02:00
[scaled-font] Avoid repeated lookup of the same unicode during text->glyphs
Performing the unicode to index is quite expensive, the FcFreeTypeCharIndex() taking over 12% in the cairo-perf text benchmarks. By adding a simple cache of translated unicode indices, we save around 25% of the lookups during benchmarks, with a relative reduction in runtime.
This commit is contained in:
parent
49eca78a42
commit
afce1cfe98
1 changed files with 41 additions and 22 deletions
|
|
@ -1534,6 +1534,12 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
cairo_status_t status;
|
||||
cairo_glyph_t *orig_glyphs;
|
||||
cairo_text_cluster_t *orig_clusters;
|
||||
struct glyph_lut_elt {
|
||||
uint32_t unicode;
|
||||
unsigned long index;
|
||||
double x_advance;
|
||||
double y_advance;
|
||||
} glyph_lut[256];
|
||||
|
||||
status = scaled_font->status;
|
||||
if (unlikely (status))
|
||||
|
|
@ -1608,17 +1614,13 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
orig_clusters = clusters ? *clusters : NULL;
|
||||
|
||||
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_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. */
|
||||
|
|
@ -1633,7 +1635,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
if (clusters) {
|
||||
|
||||
if (*num_clusters < 0) {
|
||||
status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT);
|
||||
goto DONE;
|
||||
|
|
@ -1643,11 +1644,12 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
goto DONE;
|
||||
}
|
||||
|
||||
/* Dont trust the backend, validate clusters! */
|
||||
status = _cairo_validate_text_clusters (utf8, utf8_len,
|
||||
*glyphs, *num_glyphs,
|
||||
*clusters, *num_clusters,
|
||||
*cluster_flags);
|
||||
/* Don't trust the backend, validate clusters! */
|
||||
status =
|
||||
_cairo_validate_text_clusters (utf8, utf8_len,
|
||||
*glyphs, *num_glyphs,
|
||||
*clusters, *num_clusters,
|
||||
*cluster_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1675,34 +1677,51 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
*num_clusters = num_chars;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (glyph_lut); i++)
|
||||
glyph_lut[i].unicode = ~0U;
|
||||
|
||||
p = utf8;
|
||||
for (i = 0; i < num_chars; i++) {
|
||||
int 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].index = (*scaled_font->backend->ucs4_to_index) (scaled_font, unicode);
|
||||
(*glyphs)[i].x = x;
|
||||
(*glyphs)[i].y = y;
|
||||
|
||||
glyph_slot = &glyph_lut[unicode % ARRAY_LENGTH (glyph_lut)];
|
||||
if (glyph_slot->unicode == unicode) {
|
||||
(*glyphs)[i].index = glyph_slot->index;
|
||||
x += glyph_slot->x_advance;
|
||||
y += glyph_slot->y_advance;
|
||||
} else {
|
||||
(*glyphs)[i].index =
|
||||
(*scaled_font->backend->ucs4_to_index) (scaled_font, unicode);
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
(*glyphs)[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||
&scaled_glyph);
|
||||
if (unlikely (status))
|
||||
goto DONE;
|
||||
|
||||
x += scaled_glyph->metrics.x_advance;
|
||||
y += scaled_glyph->metrics.y_advance;
|
||||
|
||||
glyph_slot->unicode = unicode;
|
||||
glyph_slot->index = (*glyphs)[i].index;
|
||||
glyph_slot->x_advance = scaled_glyph->metrics.x_advance;
|
||||
glyph_slot->y_advance = scaled_glyph->metrics.y_advance;
|
||||
}
|
||||
|
||||
if (clusters) {
|
||||
(*clusters)[i].num_bytes = num_bytes;
|
||||
(*clusters)[i].num_glyphs = 1;
|
||||
}
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
(*glyphs)[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||
&scaled_glyph);
|
||||
if (unlikely (status)) {
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
x += scaled_glyph->metrics.x_advance;
|
||||
y += scaled_glyph->metrics.y_advance;
|
||||
}
|
||||
|
||||
DONE: /* error that should be logged on scaled_font happened */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue