gdi32: Add an extensive EnumFontFamilies test,
fix some failures when running under Wine
Dmitry Timoshkov
dmitry at codeweavers.com
Tue Mar 6 05:14:25 CST 2007
Hello,
Changelog:
gdi32: Add an extensive EnumFontFamilies test, fix some failures
when running under Wine.
---
dlls/gdi32/font.c | 18 +++-
dlls/gdi32/tests/font.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 286 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 3fc4420..1b1d8b4 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -877,7 +877,11 @@ INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
LOGFONT16 lf;
lf.lfCharSet = DEFAULT_CHARSET;
- if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ if (lpFamily)
+ {
+ if (!*lpFamily) return 1;
+ lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ }
else lf.lfFaceName[0] = '\0';
return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
@@ -892,7 +896,11 @@ INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
LOGFONTA lf;
lf.lfCharSet = DEFAULT_CHARSET;
- if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ if (lpFamily)
+ {
+ if (!*lpFamily) return 1;
+ lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ }
else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
@@ -907,7 +915,11 @@ INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
LOGFONTW lf;
lf.lfCharSet = DEFAULT_CHARSET;
- if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ if (lpFamily)
+ {
+ if (!*lpFamily) return 1;
+ lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
+ }
else lf.lfFaceName[0] = 0;
return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index ce8d2fa..43e9c3a 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -49,6 +49,25 @@ static void init(void)
pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
}
+static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
+{
+ if (type != TRUETYPE_FONTTYPE) return 1;
+
+ return 0;
+}
+
+static BOOL is_truetype_font_installed(const char *name)
+{
+ HDC hdc = GetDC(0);
+ BOOL ret = FALSE;
+
+ if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
+ ret = TRUE;
+
+ ReleaseDC(0, hdc);
+ return ret;
+}
+
static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
{
return 0;
@@ -1104,7 +1123,7 @@ static void test_GetFontUnicodeRanges(void)
LOGFONTA lf;
HDC hdc;
HFONT hfont, hfont_old;
- DWORD size, i;
+ DWORD size;
GLYPHSET *gs;
if (!pGetFontUnicodeRanges)
@@ -1130,9 +1149,10 @@ static void test_GetFontUnicodeRanges(void)
size = pGetFontUnicodeRanges(hdc, gs);
ok(size, "GetFontUnicodeRanges failed\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);
+#endif
trace("found %u ranges\n", gs->cRanges);
HeapFree(GetProcessHeap(), 0, gs);
@@ -1142,6 +1162,241 @@ static void test_GetFontUnicodeRanges(void)
ReleaseDC(NULL, hdc);
}
+#define MAX_ENUM_FONTS 256
+
+struct enum_font_data
+{
+ int total;
+ LOGFONT lf[MAX_ENUM_FONTS];
+};
+
+static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
+{
+ struct enum_font_data *efd = (struct enum_font_data *)lParam;
+
+ if (type != TRUETYPE_FONTTYPE) return 1;
+#if 0
+ trace("enumed font \"%s\", charset %d, weight %d, italic %d\n",
+ lf->lfFaceName, lf->lfCharSet, lf->lfWeight, lf->lfItalic);
+#endif
+ if (efd->total < MAX_ENUM_FONTS)
+ efd->lf[efd->total++] = *lf;
+
+ return 1;
+}
+
+static void get_charset_stats(struct enum_font_data *efd,
+ int *ansi_charset, int *symbol_charset,
+ int *russian_charset)
+{
+ int i;
+
+ *ansi_charset = 0;
+ *symbol_charset = 0;
+ *russian_charset = 0;
+
+ for (i = 0; i < efd->total; i++)
+ {
+ switch (efd->lf[i].lfCharSet)
+ {
+ case ANSI_CHARSET:
+ (*ansi_charset)++;
+ break;
+ case SYMBOL_CHARSET:
+ (*symbol_charset)++;
+ break;
+ case RUSSIAN_CHARSET:
+ (*russian_charset)++;
+ break;
+ }
+ }
+}
+
+static void test_EnumFontFamilies(const char *font_name, INT font_charset)
+{
+ struct enum_font_data efd;
+ LOGFONT lf;
+ HDC hdc;
+ int i, ret, ansi_charset, symbol_charset, russian_charset;
+
+ trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
+
+ if (*font_name && !is_truetype_font_installed(font_name))
+ {
+ skip("%s is not installed\n", font_name);
+ return;
+ }
+
+ hdc = GetDC(0);
+
+ /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
+ * while EnumFontFamiliesEx doesn't.
+ */
+ if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
+ {
+ efd.total = 0;
+ SetLastError(0xdeadbeef);
+ ret = EnumFontFamilies(hdc, NULL, arial_enum_proc, (LPARAM)&efd);
+ ok(ret, "EnumFontFamilies error %u\n", GetLastError());
+ get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+ trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
+ ansi_charset, symbol_charset, russian_charset);
+ ok(efd.total > 0, "no fonts enumerated: NULL\n");
+ ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
+ ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
+ ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
+ }
+
+ efd.total = 0;
+ SetLastError(0xdeadbeef);
+ ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
+ ok(ret, "EnumFontFamilies error %u\n", GetLastError());
+ get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+ trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
+ ansi_charset, symbol_charset, russian_charset,
+ *font_name ? font_name : "<empty>");
+ if (*font_name)
+ ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
+ else
+ ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
+ for (i = 0; i < efd.total; i++)
+ {
+/* FIXME: remove completely once Wine is fixed */
+if (efd.lf[i].lfCharSet != font_charset)
+{
+todo_wine
+ ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
+}
+else
+ ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
+ ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
+ font_name, efd.lf[i].lfFaceName);
+ }
+
+ memset(&lf, 0, sizeof(lf));
+ lf.lfCharSet = ANSI_CHARSET;
+ lstrcpy(lf.lfFaceName, font_name);
+ efd.total = 0;
+ SetLastError(0xdeadbeef);
+ ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
+ ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
+ get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+ trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
+ ansi_charset, symbol_charset, russian_charset,
+ *font_name ? font_name : "<empty>");
+ if (font_charset == SYMBOL_CHARSET)
+ {
+ if (*font_name)
+ ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
+ else
+ ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
+ }
+ else
+ {
+ ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
+ for (i = 0; i < efd.total; i++)
+ {
+ ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
+ if (*font_name)
+ ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
+ font_name, efd.lf[i].lfFaceName);
+ }
+ }
+
+ /* DEFAULT_CHARSET should enumerate all available charsets */
+ memset(&lf, 0, sizeof(lf));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lstrcpy(lf.lfFaceName, font_name);
+ efd.total = 0;
+ SetLastError(0xdeadbeef);
+ EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
+ ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
+ get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+ trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
+ ansi_charset, symbol_charset, russian_charset,
+ *font_name ? font_name : "<empty>");
+ ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
+ for (i = 0; i < efd.total; i++)
+ {
+ if (*font_name)
+ ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
+ font_name, efd.lf[i].lfFaceName);
+ }
+ if (*font_name)
+ {
+ switch (font_charset)
+ {
+ case ANSI_CHARSET:
+ ok(ansi_charset > 0,
+ "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
+ ok(!symbol_charset,
+ "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
+ ok(russian_charset > 0,
+ "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
+ break;
+ case SYMBOL_CHARSET:
+ ok(!ansi_charset,
+ "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
+ ok(symbol_charset,
+ "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
+ ok(!russian_charset,
+ "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
+ break;
+ case DEFAULT_CHARSET:
+ ok(ansi_charset > 0,
+ "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
+ ok(symbol_charset > 0,
+ "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
+ ok(russian_charset > 0,
+ "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
+ break;
+ }
+ }
+ else
+ {
+ ok(ansi_charset > 0,
+ "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ ok(symbol_charset > 0,
+ "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ ok(russian_charset > 0,
+ "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ }
+
+ memset(&lf, 0, sizeof(lf));
+ lf.lfCharSet = SYMBOL_CHARSET;
+ lstrcpy(lf.lfFaceName, font_name);
+ efd.total = 0;
+ SetLastError(0xdeadbeef);
+ EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
+ ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
+ get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+ trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
+ ansi_charset, symbol_charset, russian_charset,
+ *font_name ? font_name : "<empty>");
+ if (*font_name && font_charset == ANSI_CHARSET)
+ ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
+ else
+ {
+ ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
+ for (i = 0; i < efd.total; i++)
+ {
+ ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
+ if (*font_name)
+ ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
+ font_name, efd.lf[i].lfFaceName);
+ }
+
+ ok(!ansi_charset,
+ "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ ok(symbol_charset > 0,
+ "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ ok(!russian_charset,
+ "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
+ }
+
+ ReleaseDC(0, hdc);
+}
+
START_TEST(font)
{
init();
@@ -1158,4 +1413,18 @@ START_TEST(font)
test_SetTextJustification();
test_font_charset();
test_GetFontUnicodeRanges();
+ /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
+ * I'd like to avoid them in this test.
+ */
+ test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
+ test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
+ if (is_truetype_font_installed("Arial Black") &&
+ (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
+ {
+ test_EnumFontFamilies("", ANSI_CHARSET);
+ test_EnumFontFamilies("", SYMBOL_CHARSET);
+ test_EnumFontFamilies("", DEFAULT_CHARSET);
+ }
+ else
+ skip("Arial Black or Symbol/Wingdings is not installed\n");
}
--
1.5.0.2
More information about the wine-patches
mailing list