[2/2] gdi32: Add support for emulating bold faces of bitmap fonts. Take 2. Resend.
Dmitry Timoshkov
dmitry at baikal.ru
Mon Apr 30 04:52:13 CDT 2012
---
dlls/gdi32/freetype.c | 35 +++++++++++++++++++-
dlls/gdi32/tests/font.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 3de31f6..25dcf42 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -5672,12 +5672,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;
@@ -5894,6 +5909,13 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
lpgm->gmptGlyphOrigin.x = left >> 6;
lpgm->gmptGlyphOrigin.y = top >> 6;
+ if (font->fake_bold && !FT_IS_SCALABLE(ft_face) && ft_face->glyph->format == ft_glyph_format_bitmap)
+ {
+ lpgm->gmBlackBoxX += font->potm->otmTextMetrics.tmOverhang;
+ adv += font->potm->otmTextMetrics.tmOverhang;
+ bbx += font->potm->otmTextMetrics.tmOverhang;
+ }
+
TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
lpgm->gmCellIncX, lpgm->gmCellIncY);
@@ -5920,6 +5942,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;
@@ -6428,6 +6453,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 3ffd112..d709d34 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -823,11 +823,14 @@ static void test_bitmap_font_metrics(void)
/* FIXME: add "Terminal" */
};
static const int font_log_pixels[] = { 96, 120 };
+ static const char hello[] = "Hello World!";
+ int normal_width[12], bold_width[12];
+ SIZE normal_size, bold_size;
HDC hdc;
LOGFONT lf;
HFONT hfont, old_hfont;
TEXTMETRIC tm;
- INT ret, i, expected_cs, screen_log_pixels, diff, font_res;
+ INT ret, i, n, expected_cs, screen_log_pixels, diff, font_res;
WORD system_lang_id;
char face_name[LF_FACESIZE];
CHARSETINFO csi;
@@ -966,6 +969,17 @@ 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);
+
+ SetLastError(0xdeadbeef);
+ ret = GetTextExtentPoint32(hdc, hello, lstrlen(hello), &normal_size);
+ ok(ret, "GetTextExtentPoint error %u\n", GetLastError());
+ trace("normal size %dx%d\n", normal_size.cx, normal_size.cy);
+
+ assert(sizeof(normal_width)/sizeof(normal_width[0]) >= sizeof(hello)-1);
+ memset(normal_width, 0, sizeof(normal_width));
+ for (n = 0; n < lstrlen(hello); n++)
+ GetCharWidth32(hdc, hello[n], hello[n], &normal_width[n]);
}
else
skip("Skipping font metrics test for system langid 0x%x\n",
@@ -973,6 +987,73 @@ 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);
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = GetTextExtentPoint32(hdc, hello, lstrlen(hello), &bold_size);
+ ok(ret, "GetTextExtentPoint error %u\n", GetLastError());
+ trace("bold size %dx%d\n", bold_size.cx, bold_size.cy);
+
+ ok(normal_size.cy == bold_size.cy, "normal cy %d != bold cy %d\n", normal_size.cy, bold_size.cy);
+ ret = normal_size.cx + tm.tmOverhang * lstrlen(hello);
+ if (strcmp(lf.lfFaceName, "Small Fonts") != 0) /* it's broken under Vista */
+ ok(bold_size.cx == ret, "expected cx %d, got %d\n", ret, bold_size.cx);
+
+ assert(sizeof(bold_width)/sizeof(bold_width[0]) >= sizeof(hello)-1);
+ memset(bold_width, 0, sizeof(bold_width));
+ for (n = 0; n < lstrlen(hello); n++)
+ {
+ GetCharWidth32(hdc, hello[n], hello[n], &bold_width[n]);
+ ok(bold_width[n] == normal_width[n] + tm.tmOverhang,
+ "%c: bold_width %d != normal_width %d + overhang %d\n",
+ hello[n], bold_width[n], normal_width[n], 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