From e7ed9eee767c85853d6d2fb823ff3317c490948c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 11 Dec 2006 03:13:34 -0500 Subject: [PATCH] [cairo-gstate] Use a local buffer on the stack for small glyph operations We duplicate the incoming glyph array for two reasons: 1) applying transformations, and 2) to let the lower level functions have a glyph array they can modify. By using a 2kb array on the stack we can avoid malloc() for requests of less than 100 glyphs. The size of the array can be tuned by setting CAIRO_STACK_BUFFER_SIZE. --- src/cairo-gstate.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index ab3254559..f1b589711 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1464,6 +1464,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, return CAIRO_STATUS_SUCCESS; } +#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t))) cairo_status_t _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, const cairo_glyph_t *glyphs, @@ -1472,6 +1473,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, cairo_status_t status; cairo_pattern_union_t source_pattern; cairo_glyph_t *transformed_glyphs; + cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN]; + if (gstate->source->status) return gstate->source->status; @@ -1484,9 +1487,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (status) return status; - transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); - if (transformed_glyphs == NULL) - return CAIRO_STATUS_NO_MEMORY; + if (num_glyphs <= STACK_GLYPHS_LEN) { + transformed_glyphs = stack_transformed_glyphs; + } else { + transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); + if (transformed_glyphs == NULL) + return CAIRO_STATUS_NO_MEMORY; + } _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, transformed_glyphs); @@ -1501,7 +1508,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, gstate->scaled_font); _cairo_pattern_fini (&source_pattern.base); - free (transformed_glyphs); + + if (transformed_glyphs != stack_transformed_glyphs) + free (transformed_glyphs); return status; } @@ -1513,13 +1522,17 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, cairo_path_fixed_t *path) { cairo_status_t status; - cairo_glyph_t *transformed_glyphs = NULL; + cairo_glyph_t *transformed_glyphs; + cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN]; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; - transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); + if (num_glyphs < STACK_GLYPHS_LEN) + transformed_glyphs = stack_transformed_glyphs; + else + transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); if (transformed_glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; @@ -1530,9 +1543,12 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, transformed_glyphs, num_glyphs, path); - free (transformed_glyphs); + if (transformed_glyphs != stack_transformed_glyphs) + free (transformed_glyphs); + return status; } +#undef STACK_GLYPHS_LEN cairo_status_t _cairo_gstate_set_antialias (cairo_gstate_t *gstate,