Nikolay Sivov : gdi32/freetype: Handle fonts with broken usWinDescent values.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Oct 1 10:57:01 CDT 2015


Module: wine
Branch: master
Commit: af5884ffe5a8ba50630cf8e180ddb4d700d8117a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=af5884ffe5a8ba50630cf8e180ddb4d700d8117a

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Sep 27 22:52:56 2015 +0300

gdi32/freetype: Handle fonts with broken usWinDescent values.

---

 dlls/gdi32/freetype.c   | 20 +++++++++++++++-----
 dlls/gdi32/tests/font.c |  2 +-
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 60ffc45..8e89cc5 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -4185,6 +4185,13 @@ BOOL WineEngInit(void)
     return TRUE;
 }
 
+/* Some fonts have large usWinDescent values, as a result of storing signed short
+   in unsigned field. That's probably caused by sTypoDescent vs usWinDescent confusion in
+   some font generation tools. */
+static inline USHORT get_fixed_windescent(USHORT windescent)
+{
+    return abs((SHORT)windescent);
+}
 
 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
 {
@@ -4214,12 +4221,13 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
      */
 
     if(height > 0) {
-        if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
+        USHORT windescent = get_fixed_windescent(pOS2->usWinDescent);
+        if(pOS2->usWinAscent + windescent == 0)
             ppem = MulDiv(ft_face->units_per_EM, height,
                           pHori->Ascender - pHori->Descender);
         else
             ppem = MulDiv(ft_face->units_per_EM, height,
-                          pOS2->usWinAscent + pOS2->usWinDescent);
+                          pOS2->usWinAscent + windescent);
         if(ppem > MAX_PPEM) {
             WARN("Ignoring too large height %d, ppem %d\n", height, ppem);
             ppem = 1;
@@ -7340,6 +7348,7 @@ static BOOL get_outline_text_metrics(GdiFont *font)
     WCHAR *family_nameW, *style_nameW, *face_nameW, *full_nameW;
     char *cp;
     INT ascent, descent;
+    USHORT windescent;
 
     TRACE("font=%p\n", font);
 
@@ -7408,7 +7417,7 @@ static BOOL get_outline_text_metrics(GdiFont *font)
 
     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
 
-    TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d avgW %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
+    TRACE("OS/2 winA = %u winD = %u typoA = %d typoD = %d typoLG = %d avgW %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
 	  pOS2->usWinAscent, pOS2->usWinDescent,
 	  pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
 	  pOS2->xAvgCharWidth,
@@ -7421,12 +7430,13 @@ static BOOL get_outline_text_metrics(GdiFont *font)
 
 #define TM font->potm->otmTextMetrics
 
-    if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
+    windescent = get_fixed_windescent(pOS2->usWinDescent);
+    if(pOS2->usWinAscent + windescent == 0) {
         ascent = pHori->Ascender;
         descent = -pHori->Descender;
     } else {
         ascent = pOS2->usWinAscent;
-        descent = pOS2->usWinDescent;
+        descent = windescent;
     }
 
     font->ntmCellHeight = ascent + descent;
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index cdc7726..e04ee1e 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -3718,7 +3718,7 @@ static void test_text_metrics(const LOGFONTA *lf, const NEWTEXTMETRICA *ntm)
         TEXTMETRICW tmW;
 
         ascent = GET_BE_WORD(tt_os2.usWinAscent);
-        descent = GET_BE_WORD(tt_os2.usWinDescent);
+        descent = abs((SHORT)GET_BE_WORD(tt_os2.usWinDescent));
         cell_height = ascent + descent;
         ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
            font_name, ntm->ntmCellHeight, cell_height, ascent, descent);




More information about the wine-cvs mailing list