From: Dmitry Timoshkov Subject: [2/2] gdi32: Add support for emulating bold faces of bitmap fonts. Take 2. Resend. Message-Id: <20120430185213.ab9a0031.dmitry@baikal.ru> Date: Mon, 30 Apr 2012 18:52:13 +0900 --- 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