From: Byeongsik Jeon Subject: [PATCH 1/6] gdi32: Use the DC aa_flags when GGO_METRICS case. Message-Id: <20190211082021.12986-1-bsjeon@hanmail.net> Date: Mon, 11 Feb 2019 17:20:16 +0900 Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=46512 Signed-off-by: Byeongsik Jeon --- GGO_METRICS does not assume a specific GGO format but applies the current DC aa_flags. [PATCH 1-6] fixes some problems in bug#46512: 'letter cut off' and 'text layout unstable in runtime' I'll post the other issues later: FreeType 'strong' autohinter, v40 FT_LOAD_TARGET_MONO, ClearType compatable advance width. dlls/gdi32/freetype.c | 45 +++++++++++++++++++++++++++-------------- dlls/gdi32/tests/font.c | 1 + include/wingdi.h | 2 ++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 0fc41f3902..f5c292235e 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -7489,7 +7489,8 @@ static FT_Int get_load_flags( UINT format ) if (format & GGO_UNHINTED) return load_flags | FT_LOAD_NO_HINTING; - switch (format & ~GGO_GLYPH_INDEX) + format &= ~(GGO_GLYPH_INDEX | WINE_GGO_METRICS); + switch (format) { case GGO_BITMAP: load_flags |= FT_LOAD_TARGET_MONO; @@ -7530,6 +7531,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL needsTransform = FALSE; BOOL tategaki = (font->name[0] == '@'); BOOL vertical_metrics; + BOOL ggo_metrics = format & WINE_GGO_METRICS; TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); @@ -7558,9 +7560,9 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, tategaki = check_unicode_tategaki(glyph); } - format &= ~GGO_UNHINTED; + format &= ~(WINE_GGO_METRICS | GGO_UNHINTED); - if (format == GGO_METRICS && is_identity_MAT2(lpmat) && + if (ggo_metrics && is_identity_MAT2(lpmat) && get_cached_metrics( font, glyph_index, lpgm, abc )) return 1; /* FIXME */ @@ -7608,11 +7610,11 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, tategaki, vertical_metrics, needsTransform, matrices, &gm, abc ); - if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && + 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(format == GGO_METRICS) + if (ggo_metrics) { *lpgm = gm; return 1; /* FIXME */ @@ -8232,7 +8234,11 @@ static DWORD freetype_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format, GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); + + if (GGO_METRICS == (format & ~(GGO_UNHINTED | GGO_GLYPH_INDEX))) + format |= get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS; ret = get_glyph_outline( physdev->font, glyph, format, lpgm, &abc, buflen, buf, lpmat ); + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -8388,7 +8394,7 @@ done: static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer ) { static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; - UINT c; + UINT c, format; GLYPHMETRICS gm; ABC abc; struct freetype_physdev *physdev = get_freetype_dev( dev ); @@ -8403,10 +8409,14 @@ static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, L GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); - for(c = firstChar; c <= lastChar; c++) { - get_glyph_outline( physdev->font, c, GGO_METRICS, &gm, &abc, 0, NULL, &identity ); + + format = get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS; + for (c = firstChar; c <= lastChar; c++) + { + get_glyph_outline( physdev->font, c, format, &gm, &abc, 0, NULL, &identity ); buffer[c - firstChar] = abc.abcA + abc.abcB + abc.abcC; } + LeaveCriticalSection( &freetype_cs ); return TRUE; } @@ -8417,7 +8427,7 @@ static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, L static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastChar, LPABC buffer ) { static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; - UINT c; + UINT c, format; GLYPHMETRICS gm; struct freetype_physdev *physdev = get_freetype_dev( dev ); @@ -8432,8 +8442,9 @@ static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastCha GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); + format = get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS; for(c = firstChar; c <= lastChar; c++, buffer++) - get_glyph_outline( physdev->font, c, GGO_METRICS, &gm, buffer, 0, NULL, &identity ); + get_glyph_outline( physdev->font, c, format, &gm, buffer, 0, NULL, &identity ); LeaveCriticalSection( &freetype_cs ); return TRUE; @@ -8445,7 +8456,7 @@ static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastCha static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer ) { static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; - UINT c; + UINT c, format; GLYPHMETRICS gm; struct freetype_physdev *physdev = get_freetype_dev( dev ); @@ -8461,8 +8472,9 @@ static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); + format = get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS | GGO_GLYPH_INDEX; for(c = 0; c < count; c++, buffer++) - get_glyph_outline( physdev->font, pgi ? pgi[c] : firstChar + c, GGO_METRICS | GGO_GLYPH_INDEX, + get_glyph_outline( physdev->font, pgi ? pgi[c] : firstChar + c, format, &gm, buffer, 0, NULL, &identity ); LeaveCriticalSection( &freetype_cs ); @@ -8476,6 +8488,7 @@ static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count, { static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; INT idx, pos; + UINT format; ABC abc; GLYPHMETRICS gm; struct freetype_physdev *physdev = get_freetype_dev( dev ); @@ -8491,9 +8504,10 @@ static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count, GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); + format = get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS; for (idx = pos = 0; idx < count; idx++) { - get_glyph_outline( physdev->font, wstr[idx], GGO_METRICS, &gm, &abc, 0, NULL, &identity ); + get_glyph_outline( physdev->font, wstr[idx], format, &gm, &abc, 0, NULL, &identity ); pos += abc.abcA + abc.abcB + abc.abcC; dxs[idx] = pos; } @@ -8509,6 +8523,7 @@ static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, IN { static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; INT idx, pos; + UINT format; ABC abc; GLYPHMETRICS gm; struct freetype_physdev *physdev = get_freetype_dev( dev ); @@ -8524,10 +8539,10 @@ static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, IN GDI_CheckNotLock(); EnterCriticalSection( &freetype_cs ); + format = get_physdev_dc( dev )->aa_flags | WINE_GGO_METRICS | GGO_GLYPH_INDEX; for (idx = pos = 0; idx < count; idx++) { - get_glyph_outline( physdev->font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, - &gm, &abc, 0, NULL, &identity ); + get_glyph_outline( physdev->font, indices[idx], format, &gm, &abc, 0, NULL, &identity ); pos += abc.abcA + abc.abcB + abc.abcC; dxs[idx] = pos; } diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 67e8941b5e..6e7ac1e8e5 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4839,6 +4839,7 @@ static void test_GetGlyphOutline(void) ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError()); trace("Tests with height=%d,avg=%d,full=%d,face=%s,charset=%d\n", -lf.lfHeight, tm.tmAveCharWidth, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet); + todo_wine ok(gm2.gmCellIncX == tm.tmAveCharWidth * 2 || broken(gm2.gmCellIncX == -lf.lfHeight), "expected %d, got %d (%s:%d)\n", tm.tmAveCharWidth * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet); diff --git a/include/wingdi.h b/include/wingdi.h index 1851654194..8a7453e92c 100644 --- a/include/wingdi.h +++ b/include/wingdi.h @@ -1337,6 +1337,8 @@ typedef struct #define WINE_GGO_HBGR_BITMAP 0x12 #define WINE_GGO_VRGB_BITMAP 0x13 #define WINE_GGO_VBGR_BITMAP 0x14 + +#define WINE_GGO_METRICS 0x40 #endif typedef struct -- 2.20.1