gdi32: Support caching glyphs by character code and not only by glyph index.
This commit is contained in:
parent
b4ef8a0ee1
commit
78626cdbaa
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue