Akihiro Sagawa : gdi32: Fix text metrics used in EnumFonts families.

Alexandre Julliard julliard at winehq.org
Wed Apr 7 15:48:31 CDT 2021


Module: wine
Branch: master
Commit: 837c4f4b87b4a810e57d7e50af2023b38d03b5cd
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=837c4f4b87b4a810e57d7e50af2023b38d03b5cd

Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date:   Tue Apr  6 21:34:21 2021 +0900

gdi32: Fix text metrics used in EnumFonts families.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50818
Signed-off-by: Akihiro Sagawa <sagawa.aki at gmail.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/font.c       | 36 ++++++++++++++++++++++++++++++++++--
 dlls/gdi32/tests/font.c | 19 +++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index de50bf0de42..fd03580a754 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -2685,7 +2685,9 @@ static UINT get_font_type( const NEWTEXTMETRICEXW *ntm )
 static BOOL get_face_enum_data( struct gdi_font_face *face, ENUMLOGFONTEXW *elf, NEWTEXTMETRICEXW *ntm )
 {
     struct gdi_font *font;
-    LOGFONTW lf = { .lfHeight = 100 };
+    LOGFONTW lf = { .lfHeight = -4096 /* preferable EM Square size */ };
+
+    if (!face->scalable) lf.lfHeight = 0;
 
     if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE;
 
@@ -2695,12 +2697,42 @@ static BOOL get_face_enum_data( struct gdi_font_face *face, ENUMLOGFONTEXW *elf,
         return FALSE;
     }
 
+    if (font->scalable && -lf.lfHeight % font->otm.otmEMSquare != 0)
+    {
+        /* reload with the original EM Square size */
+        lf.lfHeight = -font->otm.otmEMSquare;
+        free_gdi_font( font );
+
+        if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE;
+        if (!font_funcs->load_font( font ))
+        {
+            free_gdi_font( font );
+            return FALSE;
+        }
+    }
+
     if (font_funcs->set_outline_text_metrics( font ))
     {
-        memcpy( &ntm->ntmTm, &font->otm.otmTextMetrics, sizeof(TEXTMETRICW) );
+        static const DWORD ntm_ppem = 32;
+
+#define TM font->otm.otmTextMetrics
+#define SCALE_NTM(value) (MulDiv( ntm->ntmTm.tmHeight, (value), TM.tmHeight ))
+        ntm->ntmTm.tmHeight = MulDiv( ntm_ppem, font->ntmCellHeight, font->otm.otmEMSquare );
+        ntm->ntmTm.tmAscent = SCALE_NTM( TM.tmAscent );
+        ntm->ntmTm.tmDescent = ntm->ntmTm.tmHeight - ntm->ntmTm.tmAscent;
+        ntm->ntmTm.tmInternalLeading = SCALE_NTM( TM.tmInternalLeading );
+        ntm->ntmTm.tmExternalLeading = SCALE_NTM( TM.tmExternalLeading );
+        ntm->ntmTm.tmAveCharWidth = SCALE_NTM( TM.tmAveCharWidth );
+        ntm->ntmTm.tmMaxCharWidth = SCALE_NTM( TM.tmMaxCharWidth );
+
+        memcpy((char *)&ntm->ntmTm + offsetof( TEXTMETRICW, tmWeight ),
+               (const char *)&TM + offsetof( TEXTMETRICW, tmWeight ),
+               sizeof(TEXTMETRICW) - offsetof( TEXTMETRICW, tmWeight ));
         ntm->ntmTm.ntmSizeEM = font->otm.otmEMSquare;
         ntm->ntmTm.ntmCellHeight = font->ntmCellHeight;
         ntm->ntmTm.ntmAvgWidth = font->ntmAvgWidth;
+#undef SCALE_NTM
+#undef TM
     }
     else if (font_funcs->set_bitmap_text_metrics( font ))
     {
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index d5ae526d536..ed0acf8243a 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -3923,6 +3923,25 @@ static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
         ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
            font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
 
+        /* NEWTEXTMETRIC's scaling method is different from TEXTMETRIC's */
+#define SCALE_NTM(value) (MulDiv(ntm->tmHeight, (value), cell_height))
+        size = MulDiv(32, ntm->ntmCellHeight, ntm->ntmSizeEM);
+        ok(ntm->tmHeight == size, "%s: ntm->tmHeight %d != %d (%u/%u)\n",
+           font_name, ntm->tmHeight, size, ntm->ntmCellHeight, ntm->ntmSizeEM);
+        size = SCALE_NTM(ntm->ntmAvgWidth);
+        ok(ntm->tmAveCharWidth == size, "%s: ntm->tmAveCharWidth %d != %d (%u/%u,%d)\n",
+           font_name, ntm->tmAveCharWidth, size, ntm->ntmAvgWidth, cell_height, ntm->tmHeight);
+        size = SCALE_NTM(ascent);
+        ok(ntm->tmAscent == size, "%s: ntm->tmAscent %d != %d (%u/%u,%d)\n",
+           font_name, ntm->tmAscent, size, ascent, cell_height, ntm->tmHeight);
+        size = ntm->tmHeight - ntm->tmAscent;
+        ok(ntm->tmDescent == size, "%s: ntm->tmDescent %d != %d (%u/%u,%d)\n",
+           font_name, ntm->tmDescent, size, descent, cell_height, ntm->tmHeight);
+        size = SCALE_NTM(cell_height - ntm->ntmSizeEM);
+        ok(ntm->tmInternalLeading == size, "%s: ntm->tmInternalLeading %d != %d (%u/%u,%d)\n",
+           font_name, ntm->tmInternalLeading, size, cell_height - ntm->ntmSizeEM, cell_height, ntm->tmHeight);
+#undef SCALE_NTM
+
         version = GET_BE_WORD(tt_os2.version);
 
         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);




More information about the wine-cvs mailing list