Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- Since previous patches have modified the glyph metrics consistency problem, we can caching the glyph metrics by GGO format.
dlls/gdi32/freetype.c | 137 +++++++++++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 41 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 8c5eb11e66..d3d9e391f7 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -306,6 +306,17 @@ typedef struct tagFamily { struct list *replacement; } Family;
+enum GM_type +{ + GM_TYPE_MONO, + GM_TYPE_GRAY, + GM_TYPE_LCD, + GM_TYPE_LCD_V, + GM_TYPE_OUTLINE, + GM_TYPE_NONE +}; +#define GM_NBTYPES GM_TYPE_NONE + typedef struct { GLYPHMETRICS gm; ABC abc; /* metrics of the unrotated char */ @@ -404,8 +415,8 @@ struct tagGdiFont { struct list entry; struct list unused_entry; unsigned int refcount; - GM **gm; - DWORD gmsize; + GM **gm[GM_NBTYPES]; + DWORD gmsize[GM_NBTYPES]; OUTLINETEXTMETRICW *potm; DWORD total_kern_pairs; KERNINGPAIR *kern_pairs; @@ -4665,11 +4676,16 @@ static int get_nearest_charset(const WCHAR *family_name, Face *face, int *cp)
static GdiFont *alloc_font(void) { + DWORD type; + GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); ret->refcount = 1; - ret->gmsize = 1; - ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*)); - ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE); + for (type = 0; type < GM_NBTYPES; type++) + { + ret->gmsize[type] = 1; + ret->gm[type] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM *) ); + ret->gm[type][0] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE ); + } ret->potm = NULL; ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0; ret->total_kern_pairs = (DWORD)-1; @@ -4682,7 +4698,7 @@ static GdiFont *alloc_font(void) static void free_font(GdiFont *font) { CHILD_FONT *child, *child_next; - DWORD i; + DWORD type, block;
LIST_FOR_EACH_ENTRY_SAFE( child, child_next, &font->child_fonts, CHILD_FONT, entry ) { @@ -4700,26 +4716,62 @@ static void free_font(GdiFont *font) HeapFree(GetProcessHeap(), 0, font->kern_pairs); HeapFree(GetProcessHeap(), 0, font->potm); HeapFree(GetProcessHeap(), 0, font->name); - for (i = 0; i < font->gmsize; i++) - HeapFree(GetProcessHeap(),0,font->gm[i]); - HeapFree(GetProcessHeap(), 0, font->gm); + + for (type = 0; type < GM_NBTYPES; type++) + { + for (block = 0; block < font->gmsize[type]; block++) + HeapFree( GetProcessHeap(), 0, font->gm[type][block] ); + HeapFree( GetProcessHeap(), 0, font->gm[type] ); + } + HeapFree(GetProcessHeap(), 0, font->GSUB_Table); HeapFree(GetProcessHeap(), 0, font); }
-/* TODO: ggo format support */ -static GM *get_cached_gm_abc_metrics( GdiFont *font, UINT index, +static UINT get_GM_type( UINT format ) +{ + switch (format) + { + case GGO_BITMAP: + return GM_TYPE_MONO; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + return GM_TYPE_GRAY; + + case WINE_GGO_HRGB_BITMAP: + case WINE_GGO_HBGR_BITMAP: + return GM_TYPE_LCD; + + case WINE_GGO_VRGB_BITMAP: + case WINE_GGO_VBGR_BITMAP: + return GM_TYPE_LCD_V; + + case GGO_NATIVE: + case GGO_BEZIER: + return GM_TYPE_OUTLINE; + + default: + return GM_TYPE_NONE; + } +} + +static GM *get_cached_gm_abc_metrics( GdiFont *font, UINT index, UINT format, GLYPHMETRICS *gm, ABC *abc ) { + UINT type = get_GM_type( format ); UINT block = index / GM_BLOCK_SIZE; UINT entry = index % GM_BLOCK_SIZE; GM *ret = NULL;
- if (block < font->gmsize && font->gm[block] && font->gm[block][entry].init) + if (type == GM_TYPE_NONE) return NULL; + + if (block < font->gmsize[type] && font->gm[type][block] && font->gm[type][block][entry].init) { - *gm = font->gm[block][entry].gm; - *abc = font->gm[block][entry].abc; - ret = &font->gm[block][entry]; + *gm = font->gm[type][block][entry].gm; + *abc = font->gm[type][block][entry].abc; + ret = &font->gm[type][block][entry];
TRACE( "cached gm: %u,%u,%s,%d,%d\n", gm->gmBlackBoxX, gm->gmBlackBoxY, wine_dbgstr_point( &gm->gmptGlyphOrigin ), @@ -4730,32 +4782,37 @@ static GM *get_cached_gm_abc_metrics( GdiFont *font, UINT index, return ret; }
-static void cache_gm_abc_metrics( GdiFont *font, UINT index, +static void cache_gm_abc_metrics( GdiFont *font, UINT index, UINT format, const GLYPHMETRICS *gm, const ABC *abc ) { + UINT type = get_GM_type( format ); UINT block = index / GM_BLOCK_SIZE; UINT entry = index % GM_BLOCK_SIZE;
- if (block >= font->gmsize) + if (type == GM_TYPE_NONE) return; + + if (block >= font->gmsize[type]) { GM **ptr = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - font->gm, (block + 1) * sizeof(GM*) ); + font->gm[type], (block + 1) * sizeof(GM*) ); if (!ptr) return;
- font->gmsize = block + 1; - font->gm = ptr; + font->gmsize[type] = block + 1; + font->gm[type] = ptr; }
- if (!font->gm[block]) + if (!font->gm[type][block]) { - font->gm[block] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(GM) * GM_BLOCK_SIZE ); - if (!font->gm[block]) return; + font->gm[type][block] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(GM) * GM_BLOCK_SIZE ); + if (!font->gm[type][block]) return; }
- font->gm[block][entry].gm = *gm; - font->gm[block][entry].abc = *abc; - font->gm[block][entry].init = TRUE; + if (font->gm[type][block][entry].init) return; + + font->gm[type][block][entry].gm = *gm; + font->gm[type][block][entry].abc = *abc; + font->gm[type][block][entry].init = TRUE; }
static DWORD get_font_data( GdiFont *font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData) @@ -7551,17 +7608,13 @@ static DWORD get_ggo_glyph_from_bitmap( FT_GlyphSlot glyph, UINT format, FT_BBox return needed; }
-static FT_Int get_load_flags( UINT format, GdiFont *font ) +static FT_Int get_load_flags( UINT format, BOOL ggo_unhinted, BOOL natural_width ) { - BOOL natural_width; FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
- if (format & GGO_UNHINTED) + if (ggo_unhinted) return load_flags | FT_LOAD_NO_HINTING;
- natural_width = font->font_desc.lf.lfQuality == CLEARTYPE_NATURAL_QUALITY; - - format &= ~(GGO_GLYPH_INDEX | WINE_GGO_METRICS); switch (format) { case WINE_GGO_HRGB_BITMAP: @@ -7593,7 +7646,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, DWORD needed = 0; FT_Error err; FT_BBox bbox; - FT_Int load_flags = get_load_flags(format, incoming_font); + FT_Int load_flags; FT_Matrix transMat = identityMat; FT_Matrix transMatUnrotated; FT_Matrix transMatTategaki; @@ -7601,6 +7654,9 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL tategaki = (font->name[0] == '@'); BOOL vertical_metrics; BOOL ggo_metrics = format & WINE_GGO_METRICS; + BOOL ggo_unhinted = format & GGO_UNHINTED; + BOOL natural_width = incoming_font->font_desc.lf.lfQuality == CLEARTYPE_NATURAL_QUALITY; + BOOL can_use_cache = is_identity_MAT2(lpmat) && !(ggo_unhinted || natural_width);
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); @@ -7617,7 +7673,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, TRACE("translate glyph index %04x -> %04x\n", glyph, glyph_index); } else glyph_index = glyph; - format &= ~GGO_GLYPH_INDEX; /* TODO: Window also turns off tategaki for glyphs passed in by index if their unicode code points fall outside of the range that is rotated. */ @@ -7629,10 +7684,10 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, tategaki = check_unicode_tategaki(glyph); }
- format &= ~(WINE_GGO_METRICS | GGO_UNHINTED); + format &= ~(WINE_GGO_METRICS | GGO_UNHINTED | GGO_GLYPH_INDEX);
- if (ggo_metrics && is_identity_MAT2(lpmat) && - get_cached_gm_abc_metrics( font, glyph_index, lpgm, abc )) + if (ggo_metrics && can_use_cache && + get_cached_gm_abc_metrics( font, glyph_index, format, lpgm, abc )) return 1; /* FIXME */
needsTransform = get_transform_matrix( font, tategaki, lpmat, @@ -7644,6 +7699,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, if (vertical_metrics && FT_SimpleVersion < FT_VERSION_VALUE(2, 4 ,0)) vertical_metrics = FALSE;
+ load_flags = get_load_flags( format, ggo_unhinted, natural_width ); if (needsTransform || format != GGO_BITMAP) load_flags |= FT_LOAD_NO_BITMAP; if (vertical_metrics) load_flags |= FT_LOAD_VERTICAL_LAYOUT;
@@ -7698,9 +7754,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, &transMat, &transMatTategaki, &transMatUnrotated, &gm, abc );
- if ((ggo_metrics || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && - is_identity_MAT2(lpmat)) /* don't cache custom transforms */ - cache_gm_abc_metrics( font, glyph_index, &gm, abc ); + if (can_use_cache && needed != GDI_ERROR) + cache_gm_abc_metrics( font, glyph_index, format, &gm, abc );
if (ggo_metrics || needed != GDI_ERROR) *lpgm = gm;