[PATCH 6/6] gdi32: Support GGO format when caching the glyph metrics.
Byeongsik Jeon
bsjeon at hanmail.net
Mon Feb 11 02:20:21 CST 2019
Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
Since previous patches have modified the glyph metrics unstable problem,
we can caching the glyph metrics by GGO format.
dlls/gdi32/freetype.c | 114 ++++++++++++++++++++++++++++++------------
1 file changed, 81 insertions(+), 33 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 375d4bc059..27a233687d 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -305,6 +305,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 */
@@ -403,8 +414,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;
@@ -4656,11 +4667,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;
@@ -4673,7 +4689,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 )
{
@@ -4691,23 +4707,52 @@ 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 BOOL get_cached_metrics( GdiFont *font, UINT index, GLYPHMETRICS *gm, ABC *abc )
+static UINT get_cached_metrics_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 BOOL get_cached_metrics( GdiFont *font, UINT index, UINT format,
+ GLYPHMETRICS *gm, ABC *abc )
+{
+ UINT type = get_cached_metrics_type( format );
UINT block = index / GM_BLOCK_SIZE;
UINT entry = index % GM_BLOCK_SIZE;
- if (block < font->gmsize && font->gm[block] && font->gm[block][entry].init)
+ if (type == GM_TYPE_NONE) return FALSE;
+
+ 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;
+ *gm = font->gm[type][block][entry].gm;
+ *abc = font->gm[type][block][entry].abc;
TRACE( "cached gm: %u, %u, %s, %d, %d abc: %d, %u, %d\n",
gm->gmBlackBoxX, gm->gmBlackBoxY, wine_dbgstr_point( &gm->gmptGlyphOrigin ),
@@ -4718,31 +4763,35 @@ static BOOL get_cached_metrics( GdiFont *font, UINT index, GLYPHMETRICS *gm, ABC
return FALSE;
}
-static void set_cached_metrics( GdiFont *font, UINT index, const GLYPHMETRICS *gm, const ABC *abc )
+static void set_cached_metrics( GdiFont *font, UINT index, UINT format,
+ const GLYPHMETRICS *gm, const ABC *abc )
{
+ UINT type = get_cached_metrics_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;
+ 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)
@@ -7547,6 +7596,7 @@ 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 can_use_cache = is_identity_MAT2(lpmat) && !(format & GGO_UNHINTED);
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
buflen, buf, lpmat);
@@ -7563,7 +7613,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. */
@@ -7575,10 +7624,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_metrics( font, glyph_index, lpgm, abc ))
+ if (ggo_metrics && can_use_cache &&
+ get_cached_metrics( font, glyph_index, format, lpgm, abc ))
return 1; /* FIXME */
needsTransform = get_transform_matrices( font, tategaki, lpmat, matrices );
@@ -7703,9 +7752,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
tategaki, vertical_metrics, needsTransform, matrices,
&gm, abc );
- if ((ggo_metrics || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) &&
- is_identity_MAT2(lpmat)) /* don't cache custom transforms */
- set_cached_metrics( font, glyph_index, &gm, abc );
+ if (can_use_cache && needed != GDI_ERROR)
+ set_cached_metrics( font, glyph_index, format, &gm, abc );
if (ggo_metrics || needed != GDI_ERROR)
*lpgm = gm;
--
2.20.1
More information about the wine-devel
mailing list