From 78626cdbaa0419e78d5bf5537e084b0e8cef9234 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 5 Dec 2012 16:41:08 +0100 Subject: [PATCH] gdi32: Support caching glyphs by character code and not only by glyph index. --- dlls/gdi32/dibdrv/graphics.c | 61 +++++++++++++++++++++++------------- dlls/gdi32/font.c | 12 +++---- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index 0b843fe8b22..d0b7a39cfdd 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -33,6 +33,13 @@ struct cached_glyph BYTE bits[1]; }; +enum glyph_type +{ + GLYPH_INDEX, + GLYPH_WCHAR, + GLYPH_NBTYPES +}; + struct cached_font { struct list entry; @@ -41,8 +48,8 @@ struct cached_font LOGFONTW lf; XFORM xform; UINT aa_flags; - UINT nb_glyphs; - struct cached_glyph **glyphs; + UINT nb_glyphs[GLYPH_NBTYPES]; + struct cached_glyph **glyphs[GLYPH_NBTYPES]; }; static struct list font_cache = LIST_INIT( font_cache ); @@ -487,7 +494,7 @@ static int font_cache_cmp( const struct cached_font *p1, const struct cached_fon static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags ) { struct cached_font font, *ptr, *last_unused = NULL; - UINT i = 0; + UINT i = 0, j; GetObjectW( hfont, sizeof(font.lf), &font.lf ); GetTransform( hdc, 0x204, &font.xform ); @@ -517,8 +524,11 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags if (i > 5) /* keep at least 5 of the most-recently used fonts around */ { ptr = last_unused; - for (i = 0; i < ptr->nb_glyphs; i++) HeapFree( GetProcessHeap(), 0, ptr->glyphs[i] ); - HeapFree( GetProcessHeap(), 0, ptr->glyphs ); + for (i = 0; i < GLYPH_NBTYPES; i++) + { + for (j = 0; j < ptr->nb_glyphs[i]; j++) HeapFree( GetProcessHeap(), 0, ptr->glyphs[i][j] ); + HeapFree( GetProcessHeap(), 0, ptr->glyphs[i] ); + } list_remove( &ptr->entry ); } else if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) @@ -529,9 +539,11 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags *ptr = font; ptr->ref = 1; - ptr->glyphs = NULL; - ptr->nb_glyphs = 0; - + for (i = 0; i < GLYPH_NBTYPES; i++) + { + ptr->glyphs[i] = NULL; + ptr->nb_glyphs[i] = 0; + } done: list_add_head( &font_cache, &ptr->entry ); LeaveCriticalSection( &font_cache_cs ); @@ -544,28 +556,32 @@ void release_cached_font( struct cached_font *font ) if (font) InterlockedDecrement( &font->ref ); } -static void add_cached_glyph( struct cached_font *font, UINT index, struct cached_glyph *glyph ) +static void add_cached_glyph( struct cached_font *font, UINT index, UINT flags, struct cached_glyph *glyph ) { - if (index >= font->nb_glyphs) + enum glyph_type type = (flags & ETO_GLYPH_INDEX) ? GLYPH_INDEX : GLYPH_WCHAR; + + if (index >= font->nb_glyphs[type]) { UINT new_count = (index + 128) & ~127; struct cached_glyph **new; - if (font->glyphs) + if (font->glyphs[type]) new = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - font->glyphs, new_count * sizeof(*new) ); + font->glyphs[type], new_count * sizeof(*new) ); else new = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new) ); if (!new) return; - font->glyphs = new; - font->nb_glyphs = new_count; + font->glyphs[type] = new; + font->nb_glyphs[type] = new_count; } - font->glyphs[index] = glyph; + font->glyphs[type][index] = glyph; } -static struct cached_glyph *get_cached_glyph( struct cached_font *font, UINT index ) +static struct cached_glyph *get_cached_glyph( struct cached_font *font, UINT index, UINT flags ) { - if (index < font->nb_glyphs) return font->glyphs[index]; + enum glyph_type type = (flags & ETO_GLYPH_INDEX) ? GLYPH_INDEX : GLYPH_WCHAR; + + if (index < font->nb_glyphs[type]) return font->glyphs[type][index]; return NULL; } @@ -654,9 +670,9 @@ static const int padding[4] = {0, 3, 2, 1}; * For non-antialiased bitmaps convert them to the 17-level format * using only values 0 or 16. */ -static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *font, UINT index ) +static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *font, UINT index, UINT flags ) { - UINT ggo_flags = font->aa_flags | GGO_GLYPH_INDEX; + UINT ggo_flags = font->aa_flags; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} }; UINT indices[3] = {0, 0, 0x20}; int i, x, y; @@ -666,6 +682,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon GLYPHMETRICS metrics; struct cached_glyph *glyph; + if (flags & ETO_GLYPH_INDEX) ggo_flags |= GGO_GLYPH_INDEX; indices[0] = index; for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++) { @@ -712,7 +729,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon done: glyph->metrics = metrics; - add_cached_glyph( font, index, glyph ); + add_cached_glyph( font, index, flags, glyph ); return glyph; } @@ -740,8 +757,8 @@ static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT EnterCriticalSection( &font_cache_cs ); for (i = 0; i < count; i++) { - if (!(glyph = get_cached_glyph( font, str[i] )) && - !(glyph = cache_glyph_bitmap( hdc, font, str[i] ))) continue; + if (!(glyph = get_cached_glyph( font, str[i], flags )) && + !(glyph = cache_glyph_bitmap( hdc, font, str[i], flags ))) continue; glyph_dib.width = glyph->metrics.gmBlackBoxX; glyph_dib.height = glyph->metrics.gmBlackBoxY; diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 027c39278cd..8580fcb3320 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -1710,10 +1710,9 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar, /* helper for nulldrv_ExtTextOut */ -static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, +static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT flags, UINT aa_flags, GLYPHMETRICS *metrics, struct gdi_image_bits *image ) { - UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} }; UINT indices[3] = {0, 0, 0x20}; int i; @@ -1721,11 +1720,12 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, int stride; indices[0] = index; + if (flags & ETO_GLYPH_INDEX) aa_flags |= GGO_GLYPH_INDEX; for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++) { index = indices[i]; - ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity ); + ret = GetGlyphOutlineW( hdc, index, aa_flags, metrics, 0, NULL, &identity ); if (ret != GDI_ERROR) break; } @@ -1743,7 +1743,7 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, image->is_copy = TRUE; image->free = free_heap_bits; - ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity ); + ret = GetGlyphOutlineW( hdc, index, aa_flags, metrics, size, image->ptr, &identity ); if (ret == GDI_ERROR) { HeapFree( GetProcessHeap(), 0, image->ptr ); @@ -1764,7 +1764,7 @@ static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags, { GLYPHMETRICS metrics; - if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue; + if (get_glyph_bitmap( hdc, str[i], flags, aa_flags, &metrics, NULL )) continue; rect.left = x + metrics.gmptGlyphOrigin.x; rect.top = y - metrics.gmptGlyphOrigin.y; @@ -1949,7 +1949,7 @@ BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect GLYPHMETRICS metrics; struct gdi_image_bits image; - err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image ); + err = get_glyph_bitmap( dev->hdc, str[i], flags, GGO_BITMAP, &metrics, &image ); if (err) continue; if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );