From b7cd46ddc2a2523b4d33b22e07cdbdc09b90fa7d Mon Sep 17 00:00:00 2001 From: Dan Amelang Date: Mon, 20 Nov 2006 14:31:28 -0800 Subject: [PATCH] Add and incorporate _cairo_gstate_transform_glyphs_to_backend After changing _cairo_gstate_show_glyphs and _cairo_gstate_glyph_path to use this function, we see a significant speedup due to the elimination of redundant FP calculations. --- src/cairo-gstate.c | 92 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 856818628..d04c33281 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -61,6 +61,12 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate); static void _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate); +static void +_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_glyph_t *transformed_glyphs); + /** * _cairo_gstate_create: * @target: a #cairo_surface_t, not NULL @@ -1466,7 +1472,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, cairo_status_t status; cairo_pattern_union_t source_pattern; cairo_glyph_t *transformed_glyphs; - int i; if (gstate->source->status) return gstate->source->status; @@ -1483,15 +1488,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (transformed_glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; - for (i = 0; i < num_glyphs; ++i) - { - transformed_glyphs[i].index = glyphs[i].index; - transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; - transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; - _cairo_gstate_user_to_backend (gstate, - &transformed_glyphs[i].x, - &transformed_glyphs[i].y); - } + _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, + transformed_glyphs); _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); @@ -1515,7 +1513,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, cairo_path_fixed_t *path) { cairo_status_t status; - int i; cairo_glyph_t *transformed_glyphs = NULL; status = _cairo_gstate_ensure_scaled_font (gstate); @@ -1526,15 +1523,8 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, if (transformed_glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; - for (i = 0; i < num_glyphs; ++i) - { - transformed_glyphs[i].index = glyphs[i].index; - transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; - transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; - _cairo_gstate_user_to_backend (gstate, - &(transformed_glyphs[i].x), - &(transformed_glyphs[i].y)); - } + _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, + transformed_glyphs); status = _cairo_scaled_font_glyph_path (gstate->scaled_font, transformed_glyphs, num_glyphs, @@ -1558,3 +1548,65 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate) { return gstate->antialias; } + +/** + * _cairo_gstate_transform_glyphs_to_backend: + * @gstate: a #cairo_gstate_t + * @glyphs: the array of #cairo_glyph_t objects to be transformed + * @num_glyphs: the number of elements in @glyphs + * @transformed_glyphs: a pre-allocated array of at least @num_glyphs + * #cairo_glyph_t objects + * + * Transform an array of glyphs to backend space by first adding the offset + * of the font matrix, then transforming from user space to backend space. + * The result of the transformation is placed in @transformed_glyphs. + **/ +static void +_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_glyph_t *transformed_glyphs) +{ + int i; + cairo_matrix_t *ctm = &gstate->ctm; + cairo_matrix_t *device_transform = &gstate->target->device_transform; + + if (_cairo_matrix_is_identity (ctm) && + _cairo_matrix_is_identity (device_transform)) + { + memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t)); + } + else if (_cairo_matrix_is_translation (ctm) && + _cairo_matrix_is_translation (device_transform)) + { + double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0; + double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0; + + for (i = 0; i < num_glyphs; i++) + { + transformed_glyphs[i].index = glyphs[i].index; + transformed_glyphs[i].x = glyphs[i].x + tx; + transformed_glyphs[i].y = glyphs[i].y + ty; + } + } + else + { + cairo_matrix_t aggregate_transform; + + cairo_matrix_init_translate (&aggregate_transform, + gstate->font_matrix.x0, + gstate->font_matrix.y0); + cairo_matrix_multiply (&aggregate_transform, + &aggregate_transform, ctm); + cairo_matrix_multiply (&aggregate_transform, + &aggregate_transform, device_transform); + + for (i = 0; i < num_glyphs; i++) + { + transformed_glyphs[i] = glyphs[i]; + cairo_matrix_transform_point (&aggregate_transform, + &transformed_glyphs[i].x, + &transformed_glyphs[i].y); + } + } +}