summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-03-30 15:24:08 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-03-30 15:28:37 +0100
commit1c76e3e9ad1437662bf91ed1d21c4bda8fd50fb4 (patch)
treee1ac787cf1625a2eeb69ecb544524435ebfd70b4
parentd2ec151e490b227e7f3d6879bf7a893577dfefa5 (diff)
scaled-font: Optimize cairo_scaled_font_lookup()
By tracking which fields of information are already available on the scaled_glyph we can more efficiently determine if we already have the requested fields. This reduces from about 6 conditionals to one, and reduces the function overhead by ~20% -- which has a measurable improvement on glyph benchmarks.
-rw-r--r--src/cairo-scaled-font.c73
-rw-r--r--src/cairo-types-private.h1
2 files changed, 21 insertions, 53 deletions
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index c2ba4070..70e8805b 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2483,6 +2483,8 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->x_advance = _cairo_lround (device_x_advance);
scaled_glyph->y_advance = _cairo_lround (device_y_advance);
+
+ scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_METRICS;
}
void
@@ -2496,6 +2498,7 @@ _cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
/* sanity check the backend glyph contents */
_cairo_debug_check_image_surface_is_defined (&surface->base);
scaled_glyph->surface = surface;
+ scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
}
void
@@ -2506,6 +2509,7 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
if (scaled_glyph->path != NULL)
_cairo_path_fixed_destroy (scaled_glyph->path);
scaled_glyph->path = path;
+ scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
}
void
@@ -2519,6 +2523,7 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
}
scaled_glyph->recording_surface = recording_surface;
+ scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
}
static cairo_bool_t
@@ -2645,6 +2650,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph;
cairo_scaled_glyph_info_t need_info;
+ *scaled_glyph_ret = NULL;
+
if (unlikely (scaled_font->status))
return scaled_font->status;
@@ -2659,7 +2666,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
if (scaled_glyph == NULL) {
status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph);
if (unlikely (status))
- goto CLEANUP;
+ goto err;
memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t));
_cairo_scaled_glyph_set_index (scaled_glyph, index);
@@ -2671,14 +2678,14 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
info | CAIRO_SCALED_GLYPH_INFO_METRICS);
if (unlikely (status)) {
_cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
- goto CLEANUP;
+ 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 CLEANUP;
+ goto err;
}
}
@@ -2686,69 +2693,29 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
* Check and see if the glyph, as provided,
* already has the requested data and amend it if not
*/
- need_info = 0;
- if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
- scaled_glyph->surface == NULL)
- {
- need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
- }
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
- scaled_glyph->path == NULL)
- {
- need_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
- }
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) != 0 &&
- scaled_glyph->recording_surface == NULL)
- {
- need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
- }
-
+ need_info = info & ~scaled_glyph->has_info;
if (need_info) {
status = scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
need_info);
if (unlikely (status))
- goto CLEANUP;
+ goto err;
/* Don't trust the scaled_glyph_init() return value, the font
* backend may not even know about some of the info. For example,
* no backend other than the user-fonts knows about recording-surface
* glyph info. */
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
- scaled_glyph->surface == NULL)
- {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto CLEANUP;
- }
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
- scaled_glyph->path == NULL)
- {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto CLEANUP;
- }
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) != 0 &&
- scaled_glyph->recording_surface == NULL)
- {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto CLEANUP;
- }
+ if (info & ~scaled_glyph->has_info)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
- CLEANUP:
- if (unlikely (status)) {
- /* 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);
- *scaled_glyph_ret = NULL;
- } else {
- *scaled_glyph_ret = scaled_glyph;
- }
+ *scaled_glyph_ret = scaled_glyph;
+ return CAIRO_STATUS_SUCCESS;
+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;
}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index f3d14b31..0b8f4dbb 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -415,6 +415,7 @@ typedef struct _cairo_scaled_glyph {
int16_t x_advance; /* device-space rounded X advance */
int16_t y_advance; /* device-space rounded Y advance */
+ unsigned int has_info;
cairo_image_surface_t *surface; /* device-space image */
cairo_path_fixed_t *path; /* device-space outline */
cairo_surface_t *recording_surface; /* device-space recording-surface */