gdi32: Add support for emulating bold faces of bitmap fonts.

Dmitry Timoshkov dmitry at baikal.ru
Mon Apr 16 02:37:39 CDT 2012


---
 dlls/gdi32/freetype.c   |   28 ++++++++++++++++++++++++++-
 dlls/gdi32/tests/font.c |   48 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 0a5d3c3..eb3f9b5 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -5669,12 +5669,27 @@ static inline BYTE get_max_level( UINT format )
     return 255;
 }
 
-static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+static void emulate_bold_glyph(BYTE *buf, int pitch, int height)
+{
+    int x, y;
+    BYTE *p = buf;
+
+    for (y = 0; y < height; y++)
+    {
+        for (x = pitch - 1; x >= 0; x--)
+        {
+            p[x] |= p[x] >> 1;
+            if (x > 0) p[x] |= p[x - 1] << 7;
+        }
+        p += pitch;
+    }
+}
 
 static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
                                LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
                                const MAT2* lpmat)
 {
+    static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
     FT_Face ft_face = incoming_font->ft_face;
     GdiFont *font = incoming_font;
@@ -5917,6 +5932,9 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
 	return GDI_ERROR;
     }
 
+    if (font->fake_bold && !FT_IS_SCALABLE(ft_face) && ft_face->glyph->format == ft_glyph_format_bitmap)
+        emulate_bold_glyph(ft_face->glyph->bitmap.buffer, ft_face->glyph->bitmap.pitch, ft_face->glyph->bitmap.rows);
+
     switch(format) {
     case GGO_BITMAP:
         width = lpgm->gmBlackBoxX;
@@ -6425,6 +6443,14 @@ static BOOL get_bitmap_text_metrics(GdiFont *font)
         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
         TM.tmCharSet = font->charset;
     }
+    if (font->fake_bold && TM.tmWeight == FW_NORMAL)
+    {
+        TM.tmWeight = FW_BOLD;
+        TM.tmAveCharWidth++;
+        TM.tmMaxCharWidth++;
+        TM.tmOverhang++;
+        if (font->aveWidth) font->aveWidth++; /* avoid metrics rescaling */
+    }
 #undef TM
 
     return TRUE;
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 9bd5f1c..c330b33 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -957,6 +957,7 @@ static void test_bitmap_font_metrics(void)
                        that make the max width bigger */
                     if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
                         ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %d != %d\n", fd[i].face_name, height, tm.tmMaxCharWidth, fd[i].max_char_width);
+                    ok(tm.tmOverhang == 0, "%s(%d): tm.tmOverhang %d != 0\n", fd[i].face_name, height, tm.tmOverhang);
                 }
                 else
                     skip("Skipping font metrics test for system langid 0x%x\n",
@@ -964,6 +965,53 @@ static void test_bitmap_font_metrics(void)
             }
             SelectObject(hdc, old_hfont);
             DeleteObject(hfont);
+
+            lf.lfWeight = FW_BOLD;
+            hfont = create_font(lf.lfFaceName, &lf);
+            old_hfont = SelectObject(hdc, hfont);
+            bRet = GetTextMetrics(hdc, &tm);
+            ok(bRet, "GetTextMetrics error %d\n", GetLastError());
+            if (fd[i].dpi == tm.tmDigitizedAspectX)
+            {
+                trace("matched %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
+                if (fd[i].skip_lang_id == 0 || system_lang_id != fd[i].skip_lang_id)
+                {
+                    if (fd[i].weight == FW_NORMAL)
+                        ok(tm.tmWeight == FW_BOLD, "%s(%d): tm.tmWeight %d != FW_BOLD\n", fd[i].face_name, height, tm.tmWeight);
+                    else
+                        ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, height, tm.tmWeight, fd[i].weight);
+                    if (fd[i].height & FH_SCALE)
+                        ok(tm.tmHeight == fd[i].scaled_height, "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, height, tm.tmHeight, fd[i].scaled_height);
+                    else
+                        ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height);
+                    ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, height, tm.tmAscent, fd[i].ascent);
+                    ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, height, tm.tmDescent, fd[i].descent);
+                    ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, height, tm.tmInternalLeading, fd[i].int_leading);
+                    ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, height, tm.tmExternalLeading, fd[i].ext_leading);
+                    if (fd[i].weight == FW_NORMAL)
+                    {
+                        ok(tm.tmAveCharWidth == fd[i].ave_char_width + 1, "%s(%d): tm.tmAveCharWidth %d != %d\n", fd[i].face_name, height, tm.tmAveCharWidth, fd[i].ave_char_width + 1);
+                        /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
+                           that make the max width bigger */
+                        if (strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
+                            ok(tm.tmMaxCharWidth == fd[i].max_char_width + 1, "%s(%d): tm.tmMaxCharWidth %d != %d\n", fd[i].face_name, height, tm.tmMaxCharWidth, fd[i].max_char_width + 1);
+                        ok(tm.tmOverhang == 1, "%s(%d): tm.tmOverhang %d != 1\n", fd[i].face_name, height, tm.tmOverhang);
+                    }
+                    else
+                    {
+                        ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %d != %d\n", fd[i].face_name, height, tm.tmAveCharWidth, fd[i].ave_char_width);
+                        /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
+                           that make the max width bigger */
+                        if (strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
+                            ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %d != %d\n", fd[i].face_name, height, tm.tmMaxCharWidth, fd[i].max_char_width);
+                        ok(tm.tmOverhang == 0, "%s(%d): tm.tmOverhang %d != 0\n", fd[i].face_name, height, tm.tmOverhang);
+                    }
+                }
+                else
+                    skip("Skipping font metrics test for system langid 0x%x\n", system_lang_id);
+            }
+            SelectObject(hdc, old_hfont);
+            DeleteObject(hfont);
         }
     }
 
-- 
1.7.9.4




More information about the wine-patches mailing list