gdi32: Add a GetTextMetrics test, make it pass under Wine
Dmitry Timoshkov
dmitry at codeweavers.com
Fri Mar 9 06:46:00 CST 2007
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
More information about the wine-patches
mailing list