Commit 78626cdb authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Support caching glyphs by character code and not only by glyph index.

parent b4ef8a0e
...@@ -33,6 +33,13 @@ struct cached_glyph ...@@ -33,6 +33,13 @@ struct cached_glyph
BYTE bits[1]; BYTE bits[1];
}; };
enum glyph_type
{
GLYPH_INDEX,
GLYPH_WCHAR,
GLYPH_NBTYPES
};
struct cached_font struct cached_font
{ {
struct list entry; struct list entry;
...@@ -41,8 +48,8 @@ struct cached_font ...@@ -41,8 +48,8 @@ struct cached_font
LOGFONTW lf; LOGFONTW lf;
XFORM xform; XFORM xform;
UINT aa_flags; UINT aa_flags;
UINT nb_glyphs; UINT nb_glyphs[GLYPH_NBTYPES];
struct cached_glyph **glyphs; struct cached_glyph **glyphs[GLYPH_NBTYPES];
}; };
static struct list font_cache = LIST_INIT( font_cache ); 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 ...@@ -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 ) static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags )
{ {
struct cached_font font, *ptr, *last_unused = NULL; struct cached_font font, *ptr, *last_unused = NULL;
UINT i = 0; UINT i = 0, j;
GetObjectW( hfont, sizeof(font.lf), &font.lf ); GetObjectW( hfont, sizeof(font.lf), &font.lf );
GetTransform( hdc, 0x204, &font.xform ); GetTransform( hdc, 0x204, &font.xform );
...@@ -517,8 +524,11 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags ...@@ -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 */ if (i > 5) /* keep at least 5 of the most-recently used fonts around */
{ {
ptr = last_unused; ptr = last_unused;
for (i = 0; i < ptr->nb_glyphs; i++) HeapFree( GetProcessHeap(), 0, ptr->glyphs[i] ); for (i = 0; i < GLYPH_NBTYPES; i++)
HeapFree( GetProcessHeap(), 0, ptr->glyphs ); {
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 ); list_remove( &ptr->entry );
} }
else if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) 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 ...@@ -529,9 +539,11 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags
*ptr = font; *ptr = font;
ptr->ref = 1; ptr->ref = 1;
ptr->glyphs = NULL; for (i = 0; i < GLYPH_NBTYPES; i++)
ptr->nb_glyphs = 0; {
ptr->glyphs[i] = NULL;
ptr->nb_glyphs[i] = 0;
}
done: done:
list_add_head( &font_cache, &ptr->entry ); list_add_head( &font_cache, &ptr->entry );
LeaveCriticalSection( &font_cache_cs ); LeaveCriticalSection( &font_cache_cs );
...@@ -544,28 +556,32 @@ void release_cached_font( struct cached_font *font ) ...@@ -544,28 +556,32 @@ void release_cached_font( struct cached_font *font )
if (font) InterlockedDecrement( &font->ref ); 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; UINT new_count = (index + 128) & ~127;
struct cached_glyph **new; struct cached_glyph **new;
if (font->glyphs) if (font->glyphs[type])
new = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
font->glyphs, new_count * sizeof(*new) ); font->glyphs[type], new_count * sizeof(*new) );
else else
new = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new) ); new = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new) );
if (!new) return; if (!new) return;
font->glyphs = new; font->glyphs[type] = new;
font->nb_glyphs = new_count; 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; return NULL;
} }
...@@ -654,9 +670,9 @@ static const int padding[4] = {0, 3, 2, 1}; ...@@ -654,9 +670,9 @@ static const int padding[4] = {0, 3, 2, 1};
* For non-antialiased bitmaps convert them to the 17-level format * For non-antialiased bitmaps convert them to the 17-level format
* using only values 0 or 16. * 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} }; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
UINT indices[3] = {0, 0, 0x20}; UINT indices[3] = {0, 0, 0x20};
int i, x, y; int i, x, y;
...@@ -666,6 +682,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon ...@@ -666,6 +682,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon
GLYPHMETRICS metrics; GLYPHMETRICS metrics;
struct cached_glyph *glyph; struct cached_glyph *glyph;
if (flags & ETO_GLYPH_INDEX) ggo_flags |= GGO_GLYPH_INDEX;
indices[0] = index; indices[0] = index;
for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++) 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 ...@@ -712,7 +729,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon
done: done:
glyph->metrics = metrics; glyph->metrics = metrics;
add_cached_glyph( font, index, glyph ); add_cached_glyph( font, index, flags, glyph );
return glyph; return glyph;
} }
...@@ -740,8 +757,8 @@ static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT ...@@ -740,8 +757,8 @@ static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT
EnterCriticalSection( &font_cache_cs ); EnterCriticalSection( &font_cache_cs );
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
if (!(glyph = get_cached_glyph( font, str[i] )) && if (!(glyph = get_cached_glyph( font, str[i], flags )) &&
!(glyph = cache_glyph_bitmap( hdc, font, str[i] ))) continue; !(glyph = cache_glyph_bitmap( hdc, font, str[i], flags ))) continue;
glyph_dib.width = glyph->metrics.gmBlackBoxX; glyph_dib.width = glyph->metrics.gmBlackBoxX;
glyph_dib.height = glyph->metrics.gmBlackBoxY; glyph_dib.height = glyph->metrics.gmBlackBoxY;
......
...@@ -1710,10 +1710,9 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar, ...@@ -1710,10 +1710,9 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
/* helper for nulldrv_ExtTextOut */ /* 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 ) 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} }; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
UINT indices[3] = {0, 0, 0x20}; UINT indices[3] = {0, 0, 0x20};
int i; int i;
...@@ -1721,11 +1720,12 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, ...@@ -1721,11 +1720,12 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
int stride; int stride;
indices[0] = index; indices[0] = index;
if (flags & ETO_GLYPH_INDEX) aa_flags |= GGO_GLYPH_INDEX;
for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++) for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
{ {
index = indices[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; if (ret != GDI_ERROR) break;
} }
...@@ -1743,7 +1743,7 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, ...@@ -1743,7 +1743,7 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
image->is_copy = TRUE; image->is_copy = TRUE;
image->free = free_heap_bits; 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) if (ret == GDI_ERROR)
{ {
HeapFree( GetProcessHeap(), 0, image->ptr ); 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, ...@@ -1764,7 +1764,7 @@ static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
{ {
GLYPHMETRICS metrics; 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.left = x + metrics.gmptGlyphOrigin.x;
rect.top = y - metrics.gmptGlyphOrigin.y; rect.top = y - metrics.gmptGlyphOrigin.y;
...@@ -1949,7 +1949,7 @@ BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect ...@@ -1949,7 +1949,7 @@ BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect
GLYPHMETRICS metrics; GLYPHMETRICS metrics;
struct gdi_image_bits image; 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 (err) continue;
if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL ); if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment