[cairo-commit] src/cairo-scaled-font.c
Chris Wilson
ickle at kemper.freedesktop.org
Mon Jun 14 07:44:04 PDT 2010
src/cairo-scaled-font.c | 61 +++++++++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 16 deletions(-)
New commits:
commit 4a0bd91ff77c8afddde6d09495bc9ca7242f953d
Author: Dmitri Vorobiev <dmitri.vorobiev at movial.com>
Date: Mon Jun 14 16:40:39 2010 +0300
scaled-font: fine-tune caching
This patch implements the ideas outlined by Behdad Esfahbod in the following
mailing list message:
http://lists.cairographics.org/archives/cairo/2010-June/020065.html
Specifically, two things have been adjusted. First, the size of the look-up
table was reduced to 64. Second, cache codepath is now bypassed for strings
that are shorter than 16, not only for one-character strings. This allowed
us to reduce the LUT initialization overhead while still retaining the
advantage of caching for common-case string sizes.
We have experimented with different LUT sizes, and it came out that the size
of 64 is the best one in view of speed, at least for our language-neutral
benchmark, which generated random strings of printable ASCII characters.
Below is a table presenting benchmark results for different values of LUT
size:
===============================================================================
Benchmark | [1] | [2] | [3] | [4] | [5] | [6] | [7]
===============================================================================
8px text, 1 chars | 0.41 | 0.41 | 0 | 0.41 | 0 | 0.41 | 0
8px text, 10 chars | 2.13 | 2.21 | 3.76 | 2.19 | 2.82 | 2.09 | -1.88
8px text, 20 chars | 2.97 | 3.04 | 2.36 | 3.01 | 1.35 | 2.98 | 0.34
12px text, 1 chars | 0.94 | 0.94 | 0 | 0.95 | 1.06 | 0.94 | 0
12px text, 10 chars | 4.73 | 4.89 | 3.38 | 4.9 | 3.59 | 4.82 | 1.9
12px text, 20 chars | 6.32 | 6.42 | 1.58 | 6.46 | 2.22 | 6.32 | 0
16px text, 1 chars | 1.75 | 1.76 | 0.57 | 1.77 | 1.14 | 1.76 | 0.57
16px text, 10 chars | 8.13 | 8.45 | 3.94 | 8.43 | 3.69 | 8.44 | 3.81
16px text, 20 chars | 10.41 | 10.69 | 2.69 | 10.64 | 2.21 | 10.65 | 2.31
24px text, 1 chars | 3.3 | 3.3 | 0 | 3.32 | 0.61 | 3.3 | 0
24px text, 10 chars | 14.68 | 14.97 | 1.98 | 14.97 | 1.98 | 14.87 | 1.29
24px text, 20 chars | 17.93 | 18.01 | 0.45 | 18.06 | 0.73 | 17.81 | -0.67
96px text, 1 chars | 23.65 | 23.38 | -1.14 | 23.74 | 0.38 | 23.65 | 0
96px text, 5 chars | 50.52 | 51.34 | 1.62 | 51.48 | 1.9 | 51.41 | 1.76
96px text, 10 chars | 57.5 | 58.11 | 1.06 | 58.27 | 1.34 | 58.04 | 0.94
===============================================================================
[1]: Git head, Mpix/s
[2]: {GLYPH_LUT_SIZE = 32, CACHING_THRESHOLD = 16}
[3]: Gain of {32, 16} w.r.t. Git head
[4]: {GLYPH_LUT_SIZE = 64, CACHING_THRESHOLD = 16}
[5]: Gain of {64, 16} w.r.t. Git head
[6]: {GLYPH_LUT_SIZE = 128, CACHING_THRESHOLD = 16}
[7]: Gain of {128, 16} w.r.t. Git head
The benchmark itself can be found from this mailing list message:
http://lists.cairographics.org/archives/cairo/2010-June/020064.html
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index d70c555..418f90a 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1570,9 +1570,9 @@ ZERO_EXTENTS:
}
slim_hidden_def (cairo_scaled_font_glyph_extents);
-#define GLYPH_LUT_SIZE 256
+#define GLYPH_LUT_SIZE 64
static cairo_status_t
-cairo_scaled_font_text_to_glyphs_internal_multiple (cairo_scaled_font_t *scaled_font,
+cairo_scaled_font_text_to_glyphs_internal_cached (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
@@ -1644,7 +1644,7 @@ cairo_scaled_font_text_to_glyphs_internal_multiple (cairo_scaled_font_t *scale
}
static cairo_status_t
-cairo_scaled_font_text_to_glyphs_internal_single (cairo_scaled_font_t *scaled_font,
+cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
@@ -1652,19 +1652,47 @@ cairo_scaled_font_text_to_glyphs_internal_single (cairo_scaled_font_t *scaled_f
cairo_text_cluster_t **clusters,
int num_chars)
{
- uint32_t unicode;
- int num_bytes;
+ const char *p;
+ int i;
- glyphs[0].x = x;
- glyphs[0].y = y;
+ p = utf8;
+ for (i = 0; i < num_chars; i++) {
+ unsigned long g;
+ int num_bytes;
+ uint32_t unicode;
+ cairo_scaled_glyph_t *scaled_glyph;
+ cairo_status_t status;
- num_bytes = _cairo_utf8_get_char_validated (utf8, &unicode);
- glyphs[0].index =
- scaled_font->backend->ucs4_to_index (scaled_font, unicode);
+ num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
+ p += num_bytes;
- if (clusters) {
- (*clusters)[0].num_bytes = num_bytes;
- (*clusters)[0].num_glyphs = 1;
+ glyphs[i].x = x;
+ glyphs[i].y = y;
+
+ g = scaled_font->backend->ucs4_to_index (scaled_font, unicode);
+
+ /*
+ * No advance needed for a single character string. So, let's speed up
+ * one-character strings by skipping glyph lookup.
+ */
+ if (num_chars > 1) {
+ status = _cairo_scaled_glyph_lookup (scaled_font,
+ g,
+ CAIRO_SCALED_GLYPH_INFO_METRICS,
+ &scaled_glyph);
+ if (unlikely (status))
+ return status;
+
+ x += scaled_glyph->metrics.x_advance;
+ y += scaled_glyph->metrics.y_advance;
+ }
+
+ glyphs[i].index = g;
+
+ if (clusters) {
+ (*clusters)[i].num_bytes = num_bytes;
+ (*clusters)[i].num_glyphs = 1;
+ }
}
return CAIRO_STATUS_SUCCESS;
@@ -1805,6 +1833,7 @@ cairo_scaled_font_text_to_glyphs_internal_single (cairo_scaled_font_t *scaled_f
*
* Since: 1.8
**/
+#define CACHING_THRESHOLD 16
cairo_status_t
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x,
@@ -1958,15 +1987,15 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
*num_clusters = num_chars;
}
- if (num_chars > 1)
- status = cairo_scaled_font_text_to_glyphs_internal_multiple (scaled_font,
+ 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_single (scaled_font,
+ status = cairo_scaled_font_text_to_glyphs_internal_uncached (scaled_font,
x, y,
utf8,
*glyphs,
More information about the cairo-commit
mailing list