[PATCH 1/6] gdi32: Use the DC aa_flags when GGO_METRICS case.

Byeongsik Jeon bsjeon at hanmail.net
Mon Feb 11 02:20:16 CST 2019


Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=46512
Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
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




More information about the wine-devel mailing list