I tested it out on a couple machines and found many failure cases. (output attached) As a sanity check, I copied the deja vu family of fonts to a windows box and they passed the tests there.
On 3/9/07, Dmitry Timoshkov dmitry@codeweavers.com wrote:
Hello,
this patch should partially resolve a problem reported in the bug 5783.
In Wine GetTextMetricsW returns wrong tmFirstChar/tmLastChar, and GetFontUnicodeRanges returns wrong ranges for fonts with SYMBOL_CHARSET.
Changelog: gdi32: Add a GetTextMetrics test, make it pass under Wine.
dlls/gdi32/font.c | 9 ++- dlls/gdi32/freetype.c | 4 +- dlls/gdi32/tests/font.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 149 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 1b1d8b4..785a990 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -287,10 +287,12 @@ static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA ) ptmA->tmOverhang = ptmW->tmOverhang; ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX; ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
- ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
- ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
- /* This appears to be what Windows does */
- ptmA->tmFirstChar = ptmW->tmBreakChar;
- if (ptmA->tmFirstChar >= 2) ptmA->tmFirstChar -= 2; ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar; ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
- ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar; ptmA->tmItalic = ptmW->tmItalic; ptmA->tmUnderlined = ptmW->tmUnderlined; ptmA->tmStruckOut = ptmW->tmStruckOut;
@@ -1366,6 +1368,9 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics ) /* device layer returns values in device units * therefore we have to convert them to logical */
metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
#define WDPTOLP(x) ((x<0)? \ (-abs(INTERNAL_XDSTOWS(dc, (x)))): \ (abs(INTERNAL_XDSTOWS(dc, (x))))) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index db990fa..03adfe5 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -4480,7 +4480,7 @@ static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs) { DWORD num_ranges = 0;
- if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
- if (pFT_Get_First_Char) { FT_UInt glyph_code; FT_ULong char_code, char_code_prev;
@@ -4488,7 +4488,7 @@ static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs) glyph_code = 0; char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
TRACE("number of glyphs %ld, first glyph %u, first char %04lx\n", face->num_glyphs, glyph_code, char_code); if (!glyph_code) return 0;
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 43e9c3a..a996ff0 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -408,7 +408,7 @@ static void test_GdiGetCharDimensions(void)
if (!pGdiGetCharDimensions) {
skip("GetFontUnicodeRanges not available on this platform\n");
}skip("GdiGetCharDimensions not available on this platform\n"); return;
@@ -1149,6 +1149,7 @@ static void test_GetFontUnicodeRanges(void)
size = pGetFontUnicodeRanges(hdc, gs); ok(size, "GetFontUnicodeRanges failed\n");
- ok(gs->cRanges != 0, "GetFontUnicodeRanges returned empty ranges\n");
#if 0 for (i = 0; i < gs->cRanges; i++) trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs); @@ -1397,6 +1398,143 @@ else ReleaseDC(0, hdc); }
+static void test_text_metrics(const LOGFONTA *lf) +{
- HDC hdc;
- HFONT hfont, hfont_old;
- TEXTMETRICA tmA;
- TEXTMETRICW tmW;
- UINT first_unicode_char = 0, last_unicode_char = 0;
- INT ret, test_char;
- const char *font_name = lf->lfFaceName;
- trace("Testing font metrics for %s, charset %d\n", font_name, lf->lfCharSet);
- hdc = GetDC(0);
- SetLastError(0xdeadbeef);
- hfont = CreateFontIndirectA(lf);
- ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
- hfont_old = SelectObject(hdc, hfont);
- if (pGetFontUnicodeRanges)
- {
DWORD size;
GLYPHSET *gs;
size = pGetFontUnicodeRanges(hdc, NULL);
ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
gs = HeapAlloc(GetProcessHeap(), 0, size);
size = pGetFontUnicodeRanges(hdc, gs);
ok(size, "GetFontUnicodeRanges failed\n");
ok(gs->cRanges != 0, "GetFontUnicodeRanges returned empty ranges\n");
first_unicode_char = gs->ranges[0].wcLow;
last_unicode_char = gs->ranges[gs->cRanges - 1].wcLow + gs->ranges[gs->cRanges - 1].cGlyphs - 1;
trace("for %s first char %x, last char %x\n", font_name,
first_unicode_char, last_unicode_char);
HeapFree(GetProcessHeap(), 0, gs);
- }
- SetLastError(0xdeadbeef);
- ret = GetTextMetricsA(hdc, &tmA);
- ok(ret, "GetTextMetricsA error %u\n", GetLastError());
- trace("A: first %x, last %x, default %x, break %x\n",
tmA.tmFirstChar, tmA.tmLastChar, tmA.tmDefaultChar, tmA.tmBreakChar);
- SetLastError(0xdeadbeef);
- ret = GetTextMetricsW(hdc, &tmW);
- ok(ret, "GetTextMetricsA error %u\n", GetLastError());
- trace("W: first %x, last %x, default %x, break %x\n",
tmW.tmFirstChar, tmW.tmLastChar, tmW.tmDefaultChar, tmW.tmBreakChar);
- /* This appears to be what Windows does */
- test_char = tmW.tmBreakChar;
- if (test_char >= 2) test_char -= 2;
- if (test_char > 255) test_char = 255;
- ok(tmA.tmFirstChar == test_char, "tmFirstChar for %s %02x != %02x\n",
font_name, tmA.tmFirstChar, test_char);
- /* This test failes for Marlett, Wingdings 2 and Wingdings 3, but succeeds
* for all other 327 truetype fonts on my system.
*/
+#if 0
- test_char = tmW.tmLastChar > 255 ? 255 : tmW.tmLastChar;
- ok(tmA.tmLastChar == test_char, "tmLastChar for %s %02x != %02x\n",
font_name, tmA.tmLastChar, test_char);
+#endif
- if (pGetFontUnicodeRanges)
- {
ok(tmW.tmFirstChar == first_unicode_char, "tmFirstChar for %s %02x != %02x\n",
font_name, tmW.tmFirstChar, first_unicode_char);
+/* FIXME: remove completely once Wine is fixed
- GetFontUnicodeRanges in Wine returns wrong data for fonts with
- SYMBOL_CHARSET.
- */
+if (tmW.tmLastChar != last_unicode_char) +todo_wine ok(tmW.tmLastChar == last_unicode_char, "tmLastChar for %s %02x != %02x\n",
font_name, tmW.tmLastChar, last_unicode_char);
+else
ok(tmW.tmLastChar == last_unicode_char, "tmLastChar for %s %02x != %02x\n",
font_name, tmW.tmLastChar, last_unicode_char);
- }
- ret = GetDeviceCaps(hdc, LOGPIXELSX);
- ok(tmW.tmDigitizedAspectX == ret, "tmDigitizedAspectX %u != %u\n",
tmW.tmDigitizedAspectX, ret);
- ret = GetDeviceCaps(hdc, LOGPIXELSY);
- ok(tmW.tmDigitizedAspectX == ret, "tmDigitizedAspectY %u != %u\n",
tmW.tmDigitizedAspectX, ret);
- SelectObject(hdc, hfont_old);
- DeleteObject(hfont);
- ReleaseDC(0, hdc);
+}
+static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) +{
- INT *enumed = (INT *)lParam;
- if (type == TRUETYPE_FONTTYPE)
- {
(*enumed)++;
test_text_metrics(lf);
- }
- return 1;
+}
+static void test_GetTextMetrics(void) +{
- LOGFONTA lf;
- HDC hdc;
- INT enumed;
- SetLastError(0xdeadbeef);
- GetTextMetricsW(0, NULL);
- if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
skip("Skipping GetTextMetrics test on a Win9x platform\n");
return;
- }
- hdc = GetDC(0);
- memset(&lf, 0, sizeof(lf));
- lf.lfCharSet = DEFAULT_CHARSET;
- enumed = 0;
- EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
- trace("Tested metrics of %d truetype fonts\n", enumed);
- ReleaseDC(0, hdc);
+}
START_TEST(font) { init(); @@ -1427,4 +1565,5 @@ START_TEST(font) } else skip("Arial Black or Symbol/Wingdings is not installed\n");
- test_GetTextMetrics();
}
1.5.0.2