diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-04-28 20:33:55 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-05-28 13:26:20 -0400 |
commit | 2276b3c495bbe438b337730bd2d01f90b9f6cfd9 (patch) | |
tree | d723d0c68a4cc655d6ca2c9bccf1bf64921213f6 | |
parent | 838763b3d7d674db50c4ac5c44f33f66b944b21b (diff) |
Faster glyphs
-rw-r--r-- | glyphs.txt | 2 | ||||
-rw-r--r-- | pixman/pixman-glyph.c | 92 | ||||
-rw-r--r-- | pixman/pixman-private.h | 12 | ||||
-rw-r--r-- | pixman/pixman.c | 12 |
4 files changed, 86 insertions, 32 deletions
@@ -1,4 +1,4 @@ -TODO: +done: - uploading glyphs should be done through pixman images - this is convenient for both cairo and X. And in fact easier within pixman as well. diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c index 444c3d1b..db790c4d 100644 --- a/pixman/pixman-glyph.c +++ b/pixman/pixman-glyph.c @@ -258,10 +258,10 @@ pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, height = image->bits.height; if (cache->n_glyphs >= HASH_SIZE) - return FALSE; + return NULL; if (!(glyph = malloc (sizeof *glyph))) - return FALSE; + return NULL; glyph->font_key = font_key; glyph->glyph_key = glyph_key; @@ -270,7 +270,7 @@ pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, image->bits.format, width, height, NULL, -1))) { free (glyph); - return FALSE; + return NULL; } pixman_image_composite32 (PIXMAN_OP_SRC, @@ -285,6 +285,7 @@ pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, pixman_list_prepend (&cache->mru, &glyph->mru_link); + _pixman_image_validate (glyph->image); insert_glyph (cache, glyph); return glyph; @@ -323,12 +324,12 @@ pixman_composite_glyphs_no_mask (pixman_op_t op, { glyph_t *glyph = (glyph_t *)glyphs[i].glyph; - pixman_image_composite (op, src, glyph->image, dest, - src_x + glyphs[i].x, src_y + glyphs[i].y, - 0, 0, - dest_x + glyphs[i].x, dest_y + glyphs[i].y, - glyph->image->bits.width, - glyph->image->bits.height); + pixman_image_composite32 (op, src, glyph->image, dest, + src_x + glyphs[i].x, src_y + glyphs[i].y, + 0, 0, + dest_x + glyphs[i].x, dest_y + glyphs[i].y, + glyph->image->bits.width, + glyph->image->bits.height); pixman_list_move_to_front (&cache->mru, &glyph->mru_link); } @@ -419,18 +420,69 @@ pixman_composite_glyphs (pixman_op_t op, pixman_image_set_component_alpha (mask, TRUE); } - for (i = 0; i < n_glyphs; ++i) { - glyph_t *glyph = (glyph_t *)glyphs[i].glyph; - - pixman_image_composite32 ( - PIXMAN_OP_ADD, glyph->image, NULL, mask, - 0, 0, 0, 0, - glyphs[i].x - extents.x1, glyphs[i].y - extents.y1, - glyph->image->bits.width, - glyph->image->bits.height); - - pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + uint32_t glyph_flags = 0; + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t dest_flags; + pixman_format_code_t dest_format; + pixman_implementation_t *implementation; + pixman_composite_func_t func = NULL; + pixman_composite_info_t info; + uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + + _pixman_image_validate (mask); + + dest_flags = mask->common.flags; + dest_format = mask->common.extended_format_code; + + info.op = PIXMAN_OP_ADD; + info.mask_image = NULL; + info.dest_image = mask; + info.src_flags = glyph_flags | extra; + info.mask_flags = FAST_PATH_IS_OPAQUE; + info.dest_flags = dest_flags; + info.src_x = 0; + info.src_y = 0; + info.mask_x = 0; + info.mask_y = 0; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + _pixman_lookup_composite_function ( + get_implementation(), PIXMAN_OP_ADD, + glyph_format, glyph_flags | extra, + PIXMAN_null, FAST_PATH_IS_OPAQUE, + dest_format, dest_flags, + &implementation, &func); + } + + if (func) + { + info.src_image = glyph_img; + info.dest_x = glyphs[i].x - extents.x1; + info.dest_y = glyphs[i].y - extents.y1; + info.width = glyph->image->bits.width; + info.height = glyph->image->bits.height; + + if (info.dest_x + info.width > mask->bits.width) + info.width = mask->bits.width - info.dest_x; + if (info.dest_y + info.height > mask->bits.height) + info.height = mask->bits.height - info.dest_y; + + func (implementation, &info); + } + + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } } #if 0 diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 4683174b..c2ed9e1f 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -684,6 +684,18 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); dest, FAST_PATH_STD_DEST_FLAGS, \ func) } +extern pixman_implementation_t *global_implementation; + +static force_inline pixman_implementation_t * +get_implementation (void) +{ +#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR + if (!global_implementation) + global_implementation = _pixman_choose_implementation (); +#endif + return global_implementation; +} + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); diff --git a/pixman/pixman.c b/pixman/pixman.c index 8fb53568..7d841d3d 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -30,7 +30,7 @@ #include <stdlib.h> -static pixman_implementation_t *global_implementation; +pixman_implementation_t *global_implementation; #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR static void __attribute__((constructor)) @@ -40,16 +40,6 @@ pixman_constructor (void) } #endif -static force_inline pixman_implementation_t * -get_implementation (void) -{ -#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR - if (!global_implementation) - global_implementation = _pixman_choose_implementation (); -#endif - return global_implementation; -} - typedef struct operator_info_t operator_info_t; struct operator_info_t |