usp10: Implement GPOS MarkToBase.
[wine] / dlls / gdi32 / tests / font.c
1 /*
2  * Unit test suite for fonts
3  *
4  * Copyright 2002 Mike McCormack
5  * Copyright 2004 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30
31 #include "wine/test.h"
32
33 /* Do not allow more than 1 deviation here */
34 #define match_off_by_1(a, b) (abs((a) - (b)) <= 1)
35
36 #define near_match(a, b) (abs((a) - (b)) <= 6)
37 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
38
39 static LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
40 static DWORD (WINAPI *pGdiGetCodePage)(HDC hdc);
41 static BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
42 static BOOL  (WINAPI *pGetCharABCWidthsA)(HDC hdc, UINT first, UINT last, LPABC abc);
43 static BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
44 static BOOL  (WINAPI *pGetCharABCWidthsFloatW)(HDC hdc, UINT first, UINT last, LPABCFLOAT abc);
45 static DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
46 static DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
47 static DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
48 static BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
49 static HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDV *);
50 static HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
51 static BOOL  (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
52 static INT   (WINAPI *pAddFontResourceExA)(LPCSTR, DWORD, PVOID);
53 static BOOL  (WINAPI *pRemoveFontResourceExA)(LPCSTR, DWORD, PVOID);
54
55 static HMODULE hgdi32 = 0;
56 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
57
58 static void init(void)
59 {
60     hgdi32 = GetModuleHandleA("gdi32.dll");
61
62     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
63     pGdiGetCodePage = (void *) GetProcAddress(hgdi32,"GdiGetCodePage");
64     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
65     pGetCharABCWidthsA = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsA");
66     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
67     pGetCharABCWidthsFloatW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsFloatW");
68     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
69     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
70     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
71     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
72     pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
73     pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
74     pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
75     pAddFontResourceExA = (void *)GetProcAddress(hgdi32, "AddFontResourceExA");
76     pRemoveFontResourceExA = (void *)GetProcAddress(hgdi32, "RemoveFontResourceExA");
77 }
78
79 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
80 {
81     if (type != TRUETYPE_FONTTYPE) return 1;
82
83     return 0;
84 }
85
86 static BOOL is_truetype_font_installed(const char *name)
87 {
88     HDC hdc = GetDC(0);
89     BOOL ret = FALSE;
90
91     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
92         ret = TRUE;
93
94     ReleaseDC(0, hdc);
95     return ret;
96 }
97
98 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
99 {
100     return 0;
101 }
102
103 static BOOL is_font_installed(const char *name)
104 {
105     HDC hdc = GetDC(0);
106     BOOL ret = FALSE;
107
108     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
109         ret = TRUE;
110
111     ReleaseDC(0, hdc);
112     return ret;
113 }
114
115 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
116 {
117     LOGFONTA getobj_lf;
118     int ret, minlen = 0;
119
120     if (!hfont)
121         return;
122
123     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
124     /* NT4 tries to be clever and only returns the minimum length */
125     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
126         minlen++;
127     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
128     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
129     ok(lf->lfHeight == getobj_lf.lfHeight ||
130        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
131        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
132     ok(lf->lfWidth == getobj_lf.lfWidth ||
133        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
134        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
135     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
136        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
137        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
138     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
139        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
140        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
141     ok(lf->lfWeight == getobj_lf.lfWeight ||
142        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
143        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
144     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
145     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
146     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
147     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
148     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
149     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
150     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
151     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
152     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
153        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
154        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
155 }
156
157 static HFONT create_font(const char* test, const LOGFONTA* lf)
158 {
159     HFONT hfont = CreateFontIndirectA(lf);
160     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
161     if (hfont)
162         check_font(test, lf, hfont);
163     return hfont;
164 }
165
166 static void test_logfont(void)
167 {
168     LOGFONTA lf;
169     HFONT hfont;
170
171     memset(&lf, 0, sizeof lf);
172
173     lf.lfCharSet = ANSI_CHARSET;
174     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
175     lf.lfWeight = FW_DONTCARE;
176     lf.lfHeight = 16;
177     lf.lfWidth = 16;
178     lf.lfQuality = DEFAULT_QUALITY;
179
180     lstrcpyA(lf.lfFaceName, "Arial");
181     hfont = create_font("Arial", &lf);
182     DeleteObject(hfont);
183
184     memset(&lf, 'A', sizeof(lf));
185     hfont = CreateFontIndirectA(&lf);
186     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
187     
188     lf.lfFaceName[LF_FACESIZE - 1] = 0;
189     check_font("AAA...", &lf, hfont);
190     DeleteObject(hfont);
191 }
192
193 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
194 {
195     if (type & RASTER_FONTTYPE)
196     {
197         LOGFONT *lf = (LOGFONT *)lParam;
198         *lf = *elf;
199         return 0; /* stop enumeration */
200     }
201
202     return 1; /* continue enumeration */
203 }
204
205 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
206 {
207     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
208     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
209     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
210     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
211     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
212     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
213     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
214     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
215     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
216     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
217     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
218     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
219     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
220     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
221     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
222     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
223     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
224     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
225     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
226     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
227 }
228
229 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
230                               LONG lfWidth, const char *test_str,
231                               INT test_str_len, const TEXTMETRICA *tm_orig,
232                               const SIZE *size_orig, INT width_of_A_orig,
233                               INT scale_x, INT scale_y)
234 {
235     LOGFONTA lf;
236     OUTLINETEXTMETRIC otm;
237     TEXTMETRICA tm;
238     SIZE size;
239     INT width_of_A, cx, cy;
240     UINT ret;
241
242     if (!hfont)
243         return;
244
245     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
246
247     GetObjectA(hfont, sizeof(lf), &lf);
248
249     if (GetOutlineTextMetricsA(hdc, 0, NULL))
250     {
251         otm.otmSize = sizeof(otm) / 2;
252         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
253         ok(ret == sizeof(otm)/2 /* XP */ ||
254            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
255
256         memset(&otm, 0x1, sizeof(otm));
257         otm.otmSize = sizeof(otm);
258         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
259         ok(ret == sizeof(otm) /* XP */ ||
260            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
261
262         memset(&tm, 0x2, sizeof(tm));
263         ret = GetTextMetricsA(hdc, &tm);
264         ok(ret, "GetTextMetricsA failed\n");
265         /* the structure size is aligned */
266         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
267         {
268             ok(0, "tm != otm\n");
269             compare_tm(&tm, &otm.otmTextMetrics);
270         }
271
272         tm = otm.otmTextMetrics;
273 if (0) /* these metrics are scaled too, but with rounding errors */
274 {
275         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
276         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
277 }
278         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
279         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
280         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
281         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
282         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
283         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
284     }
285     else
286     {
287         ret = GetTextMetricsA(hdc, &tm);
288         ok(ret, "GetTextMetricsA failed\n");
289     }
290
291     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
292     cy = tm.tmHeight / tm_orig->tmHeight;
293     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
294        lfHeight, scale_x, scale_y, cx, cy);
295     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
296     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
297     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
298     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
299     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
300
301     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
302     if (lf.lfHeight)
303     {
304         if (lf.lfWidth)
305             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
306     }
307     else
308         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
309
310     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
311
312     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
313     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
314
315     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
316
317     ok(near_match(width_of_A, width_of_A_orig * scale_x), "width A %d != %d\n", width_of_A, width_of_A_orig * scale_x);
318 }
319
320 /* Test how GDI scales bitmap font metrics */
321 static void test_bitmap_font(void)
322 {
323     static const char test_str[11] = "Test String";
324     HDC hdc;
325     LOGFONTA bitmap_lf;
326     HFONT hfont, old_hfont;
327     TEXTMETRICA tm_orig;
328     SIZE size_orig;
329     INT ret, i, width_orig, height_orig, scale, lfWidth;
330
331     hdc = CreateCompatibleDC(0);
332
333     /* "System" has only 1 pixel size defined, otherwise the test breaks */
334     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
335     if (ret)
336     {
337         ReleaseDC(0, hdc);
338         trace("no bitmap fonts were found, skipping the test\n");
339         return;
340     }
341
342     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
343
344     height_orig = bitmap_lf.lfHeight;
345     lfWidth = bitmap_lf.lfWidth;
346
347     hfont = create_font("bitmap", &bitmap_lf);
348     old_hfont = SelectObject(hdc, hfont);
349     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
350     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
351     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
352     SelectObject(hdc, old_hfont);
353     DeleteObject(hfont);
354
355     bitmap_lf.lfHeight = 0;
356     bitmap_lf.lfWidth = 4;
357     hfont = create_font("bitmap", &bitmap_lf);
358     old_hfont = SelectObject(hdc, hfont);
359     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
360     SelectObject(hdc, old_hfont);
361     DeleteObject(hfont);
362
363     bitmap_lf.lfHeight = height_orig;
364     bitmap_lf.lfWidth = lfWidth;
365
366     /* test fractional scaling */
367     for (i = 1; i <= height_orig * 6; i++)
368     {
369         INT nearest_height;
370
371         bitmap_lf.lfHeight = i;
372         hfont = create_font("fractional", &bitmap_lf);
373         scale = (i + height_orig - 1) / height_orig;
374         nearest_height = scale * height_orig;
375         /* Only jump to the next height if the difference <= 25% original height */
376         if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
377         /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
378            so we'll not test this particular height. */
379         else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
380         else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
381         old_hfont = SelectObject(hdc, hfont);
382         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
383         SelectObject(hdc, old_hfont);
384         DeleteObject(hfont);
385     }
386
387     /* test integer scaling 3x2 */
388     bitmap_lf.lfHeight = height_orig * 2;
389     bitmap_lf.lfWidth *= 3;
390     hfont = create_font("3x2", &bitmap_lf);
391     old_hfont = SelectObject(hdc, hfont);
392     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
393     SelectObject(hdc, old_hfont);
394     DeleteObject(hfont);
395
396     /* test integer scaling 3x3 */
397     bitmap_lf.lfHeight = height_orig * 3;
398     bitmap_lf.lfWidth = 0;
399     hfont = create_font("3x3", &bitmap_lf);
400     old_hfont = SelectObject(hdc, hfont);
401     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
402     SelectObject(hdc, old_hfont);
403     DeleteObject(hfont);
404
405     DeleteDC(hdc);
406 }
407
408 /* Test how GDI scales outline font metrics */
409 static void test_outline_font(void)
410 {
411     static const char test_str[11] = "Test String";
412     HDC hdc, hdc_2;
413     LOGFONTA lf;
414     HFONT hfont, old_hfont, old_hfont_2;
415     OUTLINETEXTMETRICA otm;
416     SIZE size_orig;
417     INT width_orig, height_orig, lfWidth;
418     XFORM xform;
419     GLYPHMETRICS gm;
420     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
421     POINT pt;
422     INT ret;
423
424     if (!is_truetype_font_installed("Arial"))
425     {
426         skip("Arial is not installed\n");
427         return;
428     }
429
430     hdc = CreateCompatibleDC(0);
431
432     memset(&lf, 0, sizeof(lf));
433     strcpy(lf.lfFaceName, "Arial");
434     lf.lfHeight = 72;
435     hfont = create_font("outline", &lf);
436     old_hfont = SelectObject(hdc, hfont);
437     otm.otmSize = sizeof(otm);
438     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
439     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
440     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
441
442     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
443     SelectObject(hdc, old_hfont);
444     DeleteObject(hfont);
445
446     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
447     lf.lfHeight = otm.otmEMSquare;
448     lf.lfHeight = -lf.lfHeight;
449     hfont = create_font("outline", &lf);
450     old_hfont = SelectObject(hdc, hfont);
451     otm.otmSize = sizeof(otm);
452     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
453     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
454     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
455     SelectObject(hdc, old_hfont);
456     DeleteObject(hfont);
457
458     height_orig = otm.otmTextMetrics.tmHeight;
459     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
460
461     /* test integer scaling 3x2 */
462     lf.lfHeight = height_orig * 2;
463     lf.lfWidth = lfWidth * 3;
464     hfont = create_font("3x2", &lf);
465     old_hfont = SelectObject(hdc, hfont);
466     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
467     SelectObject(hdc, old_hfont);
468     DeleteObject(hfont);
469
470     /* test integer scaling 3x3 */
471     lf.lfHeight = height_orig * 3;
472     lf.lfWidth = lfWidth * 3;
473     hfont = create_font("3x3", &lf);
474     old_hfont = SelectObject(hdc, hfont);
475     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
476     SelectObject(hdc, old_hfont);
477     DeleteObject(hfont);
478
479     /* test integer scaling 1x1 */
480     lf.lfHeight = height_orig * 1;
481     lf.lfWidth = lfWidth * 1;
482     hfont = create_font("1x1", &lf);
483     old_hfont = SelectObject(hdc, hfont);
484     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
485     SelectObject(hdc, old_hfont);
486     DeleteObject(hfont);
487
488     /* test integer scaling 1x1 */
489     lf.lfHeight = height_orig;
490     lf.lfWidth = 0;
491     hfont = create_font("1x1", &lf);
492     old_hfont = SelectObject(hdc, hfont);
493     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
494
495     /* with an identity matrix */
496     memset(&gm, 0, sizeof(gm));
497     SetLastError(0xdeadbeef);
498     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
499     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
500     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
501     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
502     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
503     /* with a custom matrix */
504     memset(&gm, 0, sizeof(gm));
505     SetLastError(0xdeadbeef);
506     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
507     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
508     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
509     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
510     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
511
512     /* Test that changing the DC transformation affects only the font
513      * selected on this DC and doesn't affect the same font selected on
514      * another DC.
515      */
516     hdc_2 = CreateCompatibleDC(0);
517     old_hfont_2 = SelectObject(hdc_2, hfont);
518     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
519
520     SetMapMode(hdc, MM_ANISOTROPIC);
521
522     /* font metrics on another DC should be unchanged */
523     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
524
525     /* test restrictions of compatibility mode GM_COMPATIBLE */
526     /*  part 1: rescaling only X should not change font scaling on screen.
527                 So compressing the X axis by 2 is not done, and this
528                 appears as X scaling of 2 that no one requested. */
529     SetWindowExtEx(hdc, 100, 100, NULL);
530     SetViewportExtEx(hdc, 50, 100, NULL);
531     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
532     /* font metrics on another DC should be unchanged */
533     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
534
535     /*  part 2: rescaling only Y should change font scaling.
536                 As also X is scaled by a factor of 2, but this is not
537                 requested by the DC transformation, we get a scaling factor
538                 of 2 in the X coordinate. */
539     SetViewportExtEx(hdc, 100, 200, NULL);
540     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
541     /* font metrics on another DC should be unchanged */
542     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
543
544     /* restore scaling */
545     SetMapMode(hdc, MM_TEXT);
546
547     /* font metrics on another DC should be unchanged */
548     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
549
550     SelectObject(hdc_2, old_hfont_2);
551     DeleteDC(hdc_2);
552
553     if (!SetGraphicsMode(hdc, GM_ADVANCED))
554     {
555         SelectObject(hdc, old_hfont);
556         DeleteObject(hfont);
557         DeleteDC(hdc);
558         skip("GM_ADVANCED is not supported on this platform\n");
559         return;
560     }
561
562     xform.eM11 = 20.0f;
563     xform.eM12 = 0.0f;
564     xform.eM21 = 0.0f;
565     xform.eM22 = 20.0f;
566     xform.eDx = 0.0f;
567     xform.eDy = 0.0f;
568
569     SetLastError(0xdeadbeef);
570     ret = SetWorldTransform(hdc, &xform);
571     ok(ret, "SetWorldTransform error %u\n", GetLastError());
572
573     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
574
575     /* with an identity matrix */
576     memset(&gm, 0, sizeof(gm));
577     SetLastError(0xdeadbeef);
578     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
579     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
580     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
581     pt.x = width_orig; pt.y = 0;
582     LPtoDP(hdc, &pt, 1);
583     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
584     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
585     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
586     /* with a custom matrix */
587     memset(&gm, 0, sizeof(gm));
588     SetLastError(0xdeadbeef);
589     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
590     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
591     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
592     pt.x = width_orig; pt.y = 0;
593     LPtoDP(hdc, &pt, 1);
594     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
595     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
596     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
597
598     SetLastError(0xdeadbeef);
599     ret = SetMapMode(hdc, MM_LOMETRIC);
600     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
601
602     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
603
604     /* with an identity matrix */
605     memset(&gm, 0, sizeof(gm));
606     SetLastError(0xdeadbeef);
607     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
608     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
609     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
610     pt.x = width_orig; pt.y = 0;
611     LPtoDP(hdc, &pt, 1);
612     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
613     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
614     /* with a custom matrix */
615     memset(&gm, 0, sizeof(gm));
616     SetLastError(0xdeadbeef);
617     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
618     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
619     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
620     pt.x = width_orig; pt.y = 0;
621     LPtoDP(hdc, &pt, 1);
622     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
623     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
624
625     SetLastError(0xdeadbeef);
626     ret = SetMapMode(hdc, MM_TEXT);
627     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
628
629     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
630
631     /* with an identity matrix */
632     memset(&gm, 0, sizeof(gm));
633     SetLastError(0xdeadbeef);
634     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
635     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
636     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
637     pt.x = width_orig; pt.y = 0;
638     LPtoDP(hdc, &pt, 1);
639     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
640     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
641     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
642     /* with a custom matrix */
643     memset(&gm, 0, sizeof(gm));
644     SetLastError(0xdeadbeef);
645     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
646     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
647     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
648     pt.x = width_orig; pt.y = 0;
649     LPtoDP(hdc, &pt, 1);
650     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
651     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
652     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
653
654     SelectObject(hdc, old_hfont);
655     DeleteObject(hfont);
656     DeleteDC(hdc);
657 }
658
659 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
660 {
661     LOGFONT *lf = (LOGFONT *)lParam;
662
663     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
664     {
665         *lf = *elf;
666         return 0; /* stop enumeration */
667     }
668     return 1; /* continue enumeration */
669 }
670
671 #define FH_SCALE 0x80000000
672 static void test_bitmap_font_metrics(void)
673 {
674     static const struct font_data
675     {
676         const char face_name[LF_FACESIZE];
677         int weight, height, ascent, descent, int_leading, ext_leading;
678         int ave_char_width, max_char_width, dpi;
679         BYTE first_char, last_char, def_char, break_char;
680         DWORD ansi_bitfield;
681         WORD skip_lang_id;
682         int scaled_height;
683     } fd[] =
684     {
685         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 13 },
686         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
687         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 13 },
688         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
689         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 13 },
690         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
691         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 13 },
692         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 13 },
693         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
694         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
695
696         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
697         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 6, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
698         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
699         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 8, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
700         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
701         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 10, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
702         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
703         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 14, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
704         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2, 0, 16 },
705         { "MS Sans Serif", FW_NORMAL, FH_SCALE | 18, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC, 0, 16 },
706
707         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
708         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
709         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
710         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
711         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
712         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
713         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
714         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
715         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
716         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
717         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
718         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN2 },
719         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
720         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 },
721         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x81, 0x40, FS_LATIN2 },
722         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
723
724         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
725         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
726         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
727         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
728         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
729         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
730         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
731         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
732         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
733         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
734         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x81, 0x20, FS_LATIN1 | FS_LATIN2 },
735         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, 0x20, 0xff, 0x7f, 0x20, FS_CYRILLIC },
736
737         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
738         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
739         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
740         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
741         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
742         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
743         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
744         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
745         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
746         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
747         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
748         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
749         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
750         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
751         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
752         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
753         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
754
755         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
756         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
757         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
758         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
759         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_CYRILLIC },
760         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 },
761         { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
762         { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
763         { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
764         { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
765         { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
766
767         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
768         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
769         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
770
771         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
772         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
773         { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, 0x20, 0xff, 0x40, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
774
775         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
776         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
777         { "System", FW_NORMAL, 18, 16, 2, 0, 2, 8, 16, 96, 0, 0, 0, 0, FS_JISJAPAN },
778
779         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
780         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
781
782         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 },
783         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
784         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, 0, 0, 0, 0, FS_JISJAPAN },
785         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
786         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
787         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, 0, 0, 0, 0, FS_JISJAPAN },
788         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
789         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
790         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, 0, 0, 0, 0, FS_ARABIC },
791         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, 0, 0, 0, 0, FS_JISJAPAN },
792         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1, LANG_ARABIC },
793         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
794         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, 0, 0, 0, 0, FS_ARABIC },
795         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, 0, 0, 0, 0, FS_JISJAPAN },
796         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2, LANG_ARABIC },
797         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
798         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 9, 96, 0, 0, 0, 0, FS_ARABIC },
799         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, 0, 0, 0, 0, FS_JISJAPAN },
800         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC, LANG_ARABIC },
801         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 4, 10, 96, 0, 0, 0, 0, FS_ARABIC },
802         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, 0, 0, 0, 0, FS_JISJAPAN },
803
804         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
805         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
806         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
807         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
808         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_JISJAPAN },
809         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN2 | FS_CYRILLIC },
810         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
811         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
812         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
813         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
814         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
815         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
816
817         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 },
818         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, 0x20, 0xff, 0x80, 0x20, FS_CYRILLIC },
819         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, 0, 0, 0, 0, FS_JISJAPAN },
820
821         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 120, 0x20, 0xff, 0x80, 0x20, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
822
823         /* FIXME: add "Terminal" */
824     };
825     static const int font_log_pixels[] = { 96, 120 };
826     HDC hdc;
827     LOGFONT lf;
828     HFONT hfont, old_hfont;
829     TEXTMETRIC tm;
830     INT ret, i, expected_cs, screen_log_pixels, diff, font_res;
831     WORD system_lang_id;
832     char face_name[LF_FACESIZE];
833     CHARSETINFO csi;
834
835     system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
836     trace("system language id %04x\n", system_lang_id);
837
838     expected_cs = GetACP();
839     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
840     {
841         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
842         return;
843     }
844     expected_cs = csi.ciCharset;
845     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
846
847     hdc = CreateCompatibleDC(0);
848     assert(hdc);
849
850     trace("logpixelsX %d, logpixelsY %d\n", GetDeviceCaps(hdc, LOGPIXELSX),
851           GetDeviceCaps(hdc, LOGPIXELSY));
852
853     screen_log_pixels = GetDeviceCaps(hdc, LOGPIXELSY);
854     diff = 32768;
855     font_res = 0;
856     for (i = 0; i < sizeof(font_log_pixels)/sizeof(font_log_pixels[0]); i++)
857     {
858         int new_diff = abs(font_log_pixels[i] - screen_log_pixels);
859         if (new_diff < diff)
860         {
861             diff = new_diff;
862             font_res = font_log_pixels[i];
863         }
864     }
865     trace("best font resolution is %d\n", font_res);
866
867     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
868     {
869         int bit, height;
870
871         memset(&lf, 0, sizeof(lf));
872
873         height = fd[i].height & ~FH_SCALE;
874         lf.lfHeight = height;
875         strcpy(lf.lfFaceName, fd[i].face_name);
876
877         for(bit = 0; bit < 32; bit++)
878         {
879             GLYPHMETRICS gm;
880             DWORD fs[2];
881             BOOL bRet;
882
883             fs[0] = 1L << bit;
884             fs[1] = 0;
885             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
886             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
887
888             lf.lfCharSet = csi.ciCharset;
889             trace("looking for %s height %d charset %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet);
890             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
891             if (fd[i].height & FH_SCALE)
892                 ok(ret, "scaled font height %d should not be enumerated\n", height);
893             else
894             {
895                 if (font_res == fd[i].dpi && lf.lfCharSet == expected_cs)
896                 {
897                     if (ret) /* FIXME: Remove once Wine is fixed */
898                         todo_wine ok(!ret, "%s height %d charset %d dpi %d should be enumerated\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
899                     else
900                         ok(!ret, "%s height %d charset %d dpi %d should be enumerated\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
901                 }
902             }
903             if (ret && !(fd[i].height & FH_SCALE))
904                 continue;
905
906             hfont = create_font(lf.lfFaceName, &lf);
907             old_hfont = SelectObject(hdc, hfont);
908
909             SetLastError(0xdeadbeef);
910             ret = GetTextFace(hdc, sizeof(face_name), face_name);
911             ok(ret, "GetTextFace error %u\n", GetLastError());
912
913             if (lstrcmp(face_name, fd[i].face_name) != 0)
914             {
915                 ok(ret != ANSI_CHARSET, "font charset should not be ANSI_CHARSET\n");
916                 ok(ret != expected_cs, "font charset %d should not be %d\n", ret, expected_cs);
917                 trace("Skipping replacement %s height %d charset %d\n", face_name, tm.tmHeight, tm.tmCharSet);
918                 SelectObject(hdc, old_hfont);
919                 DeleteObject(hfont);
920                 continue;
921             }
922
923             memset(&gm, 0, sizeof(gm));
924             SetLastError(0xdeadbeef);
925             ret = GetGlyphOutline(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
926             todo_wine {
927             ok(ret == GDI_ERROR, "GetGlyphOutline should fail for a bitmap font\n");
928             ok(GetLastError() == ERROR_CAN_NOT_COMPLETE, "expected ERROR_CAN_NOT_COMPLETE, got %u\n", GetLastError());
929             }
930
931             bRet = GetTextMetrics(hdc, &tm);
932             ok(bRet, "GetTextMetrics error %d\n", GetLastError());
933
934             SetLastError(0xdeadbeef);
935             ret = GetTextCharset(hdc);
936             ok(ret == expected_cs, "got charset %d, expected %d\n", ret, expected_cs);
937
938             trace("created %s, height %d charset %x dpi %d\n", face_name, tm.tmHeight, tm.tmCharSet, tm.tmDigitizedAspectX);
939             trace("expected %s, height %d scaled_hight %d, dpi %d\n", fd[i].face_name, height, fd[i].scaled_height, fd[i].dpi);
940
941             if(fd[i].dpi == tm.tmDigitizedAspectX)
942             {
943                 trace("matched %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
944                 if (fd[i].skip_lang_id == 0 || system_lang_id != fd[i].skip_lang_id)
945                 {
946                     ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, height, tm.tmWeight, fd[i].weight);
947                     if (fd[i].height & FH_SCALE)
948                         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);
949                     else
950                         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);
951                     ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, height, tm.tmAscent, fd[i].ascent);
952                     ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, height, tm.tmDescent, fd[i].descent);
953                     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);
954                     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);
955                     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);
956                     ok(tm.tmFirstChar == fd[i].first_char, "%s(%d): tm.tmFirstChar = %02x\n", fd[i].face_name, height, tm.tmFirstChar);
957                     ok(tm.tmLastChar == fd[i].last_char, "%s(%d): tm.tmLastChar = %02x\n", fd[i].face_name, height, tm.tmLastChar);
958                     /* Substitutions like MS Sans Serif,0=MS Sans Serif,204
959                        make default char test fail */
960                     if (tm.tmCharSet == lf.lfCharSet)
961                         ok(tm.tmDefaultChar == fd[i].def_char, "%s(%d): tm.tmDefaultChar = %02x\n", fd[i].face_name, height, tm.tmDefaultChar);
962                     ok(tm.tmBreakChar == fd[i].break_char, "%s(%d): tm.tmBreakChar = %02x\n", fd[i].face_name, height, tm.tmBreakChar);
963                     ok(tm.tmCharSet == expected_cs || tm.tmCharSet == ANSI_CHARSET, "%s(%d): tm.tmCharSet %d != %d\n", fd[i].face_name, height, tm.tmCharSet, expected_cs);
964
965                     /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
966                        that make the max width bigger */
967                     if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
968                         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);
969                 }
970                 else
971                     skip("Skipping font metrics test for system langid 0x%x\n",
972                          system_lang_id);
973             }
974             SelectObject(hdc, old_hfont);
975             DeleteObject(hfont);
976         }
977     }
978
979     DeleteDC(hdc);
980 }
981
982 static void test_GdiGetCharDimensions(void)
983 {
984     HDC hdc;
985     TEXTMETRICW tm;
986     LONG ret;
987     SIZE size;
988     LONG avgwidth, height;
989     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
990
991     if (!pGdiGetCharDimensions)
992     {
993         win_skip("GdiGetCharDimensions not available on this platform\n");
994         return;
995     }
996
997     hdc = CreateCompatibleDC(NULL);
998
999     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
1000     avgwidth = ((size.cx / 26) + 1) / 2;
1001
1002     ret = pGdiGetCharDimensions(hdc, &tm, &height);
1003     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1004     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
1005
1006     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
1007     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1008
1009     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
1010     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1011
1012     height = 0;
1013     ret = pGdiGetCharDimensions(hdc, NULL, &height);
1014     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
1015     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
1016
1017     DeleteDC(hdc);
1018 }
1019
1020 static int CALLBACK create_font_proc(const LOGFONT *lpelfe,
1021                                      const TEXTMETRIC *lpntme,
1022                                      DWORD FontType, LPARAM lParam)
1023 {
1024     if (FontType & TRUETYPE_FONTTYPE)
1025     {
1026         HFONT hfont;
1027
1028         hfont = CreateFontIndirect(lpelfe);
1029         if (hfont)
1030         {
1031             *(HFONT *)lParam = hfont;
1032             return 0;
1033         }
1034     }
1035
1036     return 1;
1037 }
1038
1039 static void test_GetCharABCWidths(void)
1040 {
1041     static const WCHAR str[] = {'a',0};
1042     BOOL ret;
1043     HDC hdc;
1044     LOGFONTA lf;
1045     HFONT hfont;
1046     ABC abc[1];
1047     ABCFLOAT abcf[1];
1048     WORD glyphs[1];
1049     DWORD nb;
1050     static const struct
1051     {
1052         UINT first;
1053         UINT last;
1054     } range[] =
1055     {
1056         {0xff, 0xff},
1057         {0x100, 0x100},
1058         {0xff, 0x100},
1059         {0x1ff, 0xff00},
1060         {0xffff, 0xffff},
1061         {0x10000, 0x10000},
1062         {0xffff, 0x10000},
1063         {0xffffff, 0xffffff},
1064         {0x1000000, 0x1000000},
1065         {0xffffff, 0x1000000},
1066         {0xffffffff, 0xffffffff},
1067         {0x00, 0xff}
1068     };
1069     static const struct
1070     {
1071         UINT cs;
1072         UINT a;
1073         UINT w;
1074         BOOL r[sizeof range / sizeof range[0]];
1075     } c[] =
1076     {
1077         {ANSI_CHARSET, 0x30, 0x30,
1078          {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1079         {SHIFTJIS_CHARSET, 0x82a0, 0x3042,
1080          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1081         {HANGEUL_CHARSET, 0x8141, 0xac02,
1082          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1083         {JOHAB_CHARSET, 0x8446, 0x3135,
1084          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1085         {GB2312_CHARSET, 0x8141, 0x4e04,
1086          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}},
1087         {CHINESEBIG5_CHARSET, 0xa142, 0x3001,
1088          {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}}
1089     };
1090     UINT i;
1091
1092     if (!pGetCharABCWidthsA || !pGetCharABCWidthsW || !pGetCharABCWidthsFloatW || !pGetCharABCWidthsI)
1093     {
1094         win_skip("GetCharABCWidthsA/W/I not available on this platform\n");
1095         return;
1096     }
1097
1098     memset(&lf, 0, sizeof(lf));
1099     strcpy(lf.lfFaceName, "System");
1100     lf.lfHeight = 20;
1101
1102     hfont = CreateFontIndirectA(&lf);
1103     hdc = GetDC(0);
1104     hfont = SelectObject(hdc, hfont);
1105
1106     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
1107     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
1108
1109     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
1110     ok(!ret, "GetCharABCWidthsI should have failed\n");
1111
1112     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
1113     ok(!ret, "GetCharABCWidthsI should have failed\n");
1114
1115     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
1116     ok(ret, "GetCharABCWidthsI should have succeeded\n");
1117
1118     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
1119     ok(!ret, "GetCharABCWidthsW should have failed\n");
1120
1121     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
1122     ok(!ret, "GetCharABCWidthsW should have failed\n");
1123
1124     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
1125     ok(!ret, "GetCharABCWidthsW should have failed\n");
1126
1127     ret = pGetCharABCWidthsFloatW(NULL, 'a', 'a', abcf);
1128     ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1129
1130     ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', NULL);
1131     ok(!ret, "GetCharABCWidthsFloatW should have failed\n");
1132
1133     ret = pGetCharABCWidthsFloatW(hdc, 'a', 'a', abcf);
1134     ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
1135
1136     hfont = SelectObject(hdc, hfont);
1137     DeleteObject(hfont);
1138
1139     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
1140     {
1141         ABC a[2], w[2];
1142         ABC full[256];
1143         UINT code = 0x41, j;
1144
1145         lf.lfFaceName[0] = '\0';
1146         lf.lfCharSet = c[i].cs;
1147         lf.lfPitchAndFamily = 0;
1148         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
1149         {
1150             skip("TrueType font for charset %u is not installed\n", c[i].cs);
1151             continue;
1152         }
1153
1154         memset(a, 0, sizeof a);
1155         memset(w, 0, sizeof w);
1156         hfont = SelectObject(hdc, hfont);
1157         ok(pGetCharABCWidthsA(hdc, c[i].a, c[i].a + 1, a) &&
1158            pGetCharABCWidthsW(hdc, c[i].w, c[i].w + 1, w) &&
1159            memcmp(a, w, sizeof a) == 0,
1160            "GetCharABCWidthsA and GetCharABCWidthsW should return same widths. charset = %u\n", c[i].cs);
1161
1162         memset(a, 0xbb, sizeof a);
1163         ret = pGetCharABCWidthsA(hdc, code, code, a);
1164         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1165         memset(full, 0xcc, sizeof full);
1166         ret = pGetCharABCWidthsA(hdc, 0x00, code, full);
1167         ok(ret, "GetCharABCWidthsA should have succeeded\n");
1168         ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
1169            "GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
1170
1171         for (j = 0; j < sizeof range / sizeof range[0]; ++j)
1172         {
1173             memset(full, 0xdd, sizeof full);
1174             ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
1175             ok(ret == c[i].r[j], "GetCharABCWidthsA %x - %x should have %s\n",
1176                range[j].first, range[j].last, c[i].r[j] ? "succeeded" : "failed");
1177             if (ret)
1178             {
1179                 UINT last = range[j].last - range[j].first;
1180                 ret = pGetCharABCWidthsA(hdc, range[j].last, range[j].last, a);
1181                 ok(ret && memcmp(&full[last], &a[0], sizeof(ABC)) == 0,
1182                    "GetCharABCWidthsA %x should match. codepage = %u\n",
1183                    range[j].last, c[i].cs);
1184             }
1185         }
1186
1187         hfont = SelectObject(hdc, hfont);
1188         DeleteObject(hfont);
1189     }
1190
1191     ReleaseDC(NULL, hdc);
1192 }
1193
1194 static void test_text_extents(void)
1195 {
1196     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
1197     LPINT extents;
1198     INT i, len, fit1, fit2;
1199     LOGFONTA lf;
1200     TEXTMETRICA tm;
1201     HDC hdc;
1202     HFONT hfont;
1203     SIZE sz;
1204     SIZE sz1, sz2;
1205     BOOL ret;
1206
1207     memset(&lf, 0, sizeof(lf));
1208     strcpy(lf.lfFaceName, "Arial");
1209     lf.lfHeight = 20;
1210
1211     hfont = CreateFontIndirectA(&lf);
1212     hdc = GetDC(0);
1213     hfont = SelectObject(hdc, hfont);
1214     GetTextMetricsA(hdc, &tm);
1215     GetTextExtentPointA(hdc, "o", 1, &sz);
1216     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
1217
1218     SetLastError(0xdeadbeef);
1219     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
1220     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1221     {
1222         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
1223         hfont = SelectObject(hdc, hfont);
1224         DeleteObject(hfont);
1225         ReleaseDC(0, hdc);
1226         return;
1227     }
1228
1229     len = lstrlenW(wt);
1230     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
1231     extents[0] = 1;         /* So that the increasing sequence test will fail
1232                                if the extents array is untouched.  */
1233     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
1234     GetTextExtentPointW(hdc, wt, len, &sz2);
1235     ok(sz1.cy == sz2.cy,
1236        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
1237     /* Because of the '\n' in the string GetTextExtentExPoint and
1238        GetTextExtentPoint return different widths under Win2k, but
1239        under WinXP they return the same width.  So we don't test that
1240        here. */
1241
1242     for (i = 1; i < len; ++i)
1243         ok(extents[i-1] <= extents[i],
1244            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
1245            i);
1246     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
1247     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
1248     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
1249     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
1250     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
1251     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
1252     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
1253     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
1254     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
1255     ok(extents[0] == extents[2] && extents[1] == extents[3],
1256        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
1257     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
1258     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
1259        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
1260     HeapFree(GetProcessHeap(), 0, extents);
1261
1262     /* extents functions fail with -ve counts (the interesting case being -1) */
1263     ret = GetTextExtentPointA(hdc, "o", -1, &sz);
1264     ok(ret == FALSE, "got %d\n", ret);
1265     ret = GetTextExtentExPointA(hdc, "o", -1, 0, NULL, NULL, &sz);
1266     ok(ret == FALSE, "got %d\n", ret);
1267     ret = GetTextExtentExPointW(hdc, wt, -1, 0, NULL, NULL, &sz1);
1268     ok(ret == FALSE, "got %d\n", ret);
1269
1270     /* max_extent = 0 succeeds and returns zero */
1271     fit1 = fit2 = -215;
1272     ret = GetTextExtentExPointA(hdc, NULL, 0, 0, &fit1, NULL, &sz);
1273     ok(ret == TRUE ||
1274        broken(ret == FALSE), /* NT4, 2k */
1275        "got %d\n", ret);
1276     ok(fit1 == 0 ||
1277        broken(fit1 == -215), /* NT4, 2k */
1278        "fit = %d\n", fit1);
1279     ret = GetTextExtentExPointW(hdc, NULL, 0, 0, &fit2, NULL, &sz1);
1280     ok(ret == TRUE, "got %d\n", ret);
1281     ok(fit2 == 0, "fit = %d\n", fit2);
1282
1283     /* max_extent = -1 is interpreted as a very large width that will
1284      * definitely fit our three characters */
1285     fit1 = fit2 = -215;
1286     ret = GetTextExtentExPointA(hdc, "One", 3, -1, &fit1, NULL, &sz);
1287     ok(ret == TRUE, "got %d\n", ret);
1288     todo_wine ok(fit1 == 3, "fit = %d\n", fit1);
1289     ret = GetTextExtentExPointW(hdc, wt, 3, -1, &fit2, NULL, &sz);
1290     ok(ret == TRUE, "got %d\n", ret);
1291     todo_wine ok(fit2 == 3, "fit = %d\n", fit2);
1292
1293     /* max_extent = -2 is interpreted similarly, but the Ansi version
1294      * rejects it while the Unicode one accepts it */
1295     fit1 = fit2 = -215;
1296     ret = GetTextExtentExPointA(hdc, "One", 3, -2, &fit1, NULL, &sz);
1297     todo_wine ok(ret == FALSE, "got %d\n", ret);
1298     todo_wine ok(fit1 == -215, "fit = %d\n", fit1);
1299     ret = GetTextExtentExPointW(hdc, wt, 3, -2, &fit2, NULL, &sz);
1300     ok(ret == TRUE, "got %d\n", ret);
1301     todo_wine ok(fit2 == 3, "fit = %d\n", fit2);
1302
1303     hfont = SelectObject(hdc, hfont);
1304     DeleteObject(hfont);
1305     ReleaseDC(NULL, hdc);
1306 }
1307
1308 static void test_GetGlyphIndices(void)
1309 {
1310     HDC      hdc;
1311     HFONT    hfont;
1312     DWORD    charcount;
1313     LOGFONTA lf;
1314     DWORD    flags = 0;
1315     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1316     WORD     glyphs[(sizeof(testtext)/2)-1];
1317     TEXTMETRIC textm;
1318     HFONT hOldFont;
1319
1320     if (!pGetGlyphIndicesW) {
1321         win_skip("GetGlyphIndicesW not available on platform\n");
1322         return;
1323     }
1324
1325     hdc = GetDC(0);
1326
1327     memset(&lf, 0, sizeof(lf));
1328     strcpy(lf.lfFaceName, "System");
1329     lf.lfHeight = 16;
1330     lf.lfCharSet = ANSI_CHARSET;
1331
1332     hfont = CreateFontIndirectA(&lf);
1333     ok(hfont != 0, "CreateFontIndirectEx failed\n");
1334     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1335     if (textm.tmCharSet == ANSI_CHARSET)
1336     {
1337         flags |= GGI_MARK_NONEXISTING_GLYPHS;
1338         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1339         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1340         ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1341         flags = 0;
1342         charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1343         ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1344         ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1345                         textm.tmDefaultChar, glyphs[4]);
1346     }
1347     else
1348         /* FIXME: Write tests for non-ANSI charsets. */
1349         skip("GetGlyphIndices System font tests only for ANSI_CHARSET\n");
1350
1351     if(!is_font_installed("Tahoma"))
1352     {
1353         skip("Tahoma is not installed so skipping this test\n");
1354         return;
1355     }
1356     memset(&lf, 0, sizeof(lf));
1357     strcpy(lf.lfFaceName, "Tahoma");
1358     lf.lfHeight = 20;
1359
1360     hfont = CreateFontIndirectA(&lf);
1361     hOldFont = SelectObject(hdc, hfont);
1362     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1363     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1364     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1365     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1366     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1367     flags = 0;
1368     testtext[0] = textm.tmDefaultChar;
1369     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1370     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1371     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1372     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1373     DeleteObject(SelectObject(hdc, hOldFont));
1374 }
1375
1376 static void test_GetKerningPairs(void)
1377 {
1378     static const struct kerning_data
1379     {
1380         const char face_name[LF_FACESIZE];
1381         LONG height;
1382         /* some interesting fields from OUTLINETEXTMETRIC */
1383         LONG tmHeight, tmAscent, tmDescent;
1384         UINT otmEMSquare;
1385         INT  otmAscent;
1386         INT  otmDescent;
1387         UINT otmLineGap;
1388         UINT otmsCapEmHeight;
1389         UINT otmsXHeight;
1390         INT  otmMacAscent;
1391         INT  otmMacDescent;
1392         UINT otmMacLineGap;
1393         UINT otmusMinimumPPEM;
1394         /* small subset of kerning pairs to test */
1395         DWORD total_kern_pairs;
1396         const KERNINGPAIR kern_pair[26];
1397     } kd[] =
1398     {
1399         {"Arial", 12, 12, 9, 3,
1400                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1401                   26,
1402             {
1403                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1404                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1405                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1406                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1407                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1408                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1409                 {933,970,+1},{933,972,-1}
1410                 }
1411         },
1412         {"Arial", -34, 39, 32, 7,
1413                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1414                   26,
1415             {
1416                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1417                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1418                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1419                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1420                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1421                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1422                 {933,970,+2},{933,972,-3}
1423             }
1424         },
1425         { "Arial", 120, 120, 97, 23,
1426                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1427                    26,
1428             {
1429                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1430                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1431                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1432                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1433                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1434                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1435                 {933,970,+6},{933,972,-10}
1436             }
1437         },
1438 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1439         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1440                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1441                    26,
1442             {
1443                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1444                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1445                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1446                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1447                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1448                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1449                 {933,970,+54},{933,972,-83}
1450             }
1451         }
1452 #endif
1453     };
1454     LOGFONT lf;
1455     HFONT hfont, hfont_old;
1456     KERNINGPAIR *kern_pair;
1457     HDC hdc;
1458     DWORD total_kern_pairs, ret, i, n, matches;
1459
1460     hdc = GetDC(0);
1461
1462     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1463      * which may render this test unusable, so we're trying to avoid that.
1464      */
1465     SetLastError(0xdeadbeef);
1466     GetKerningPairsW(hdc, 0, NULL);
1467     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1468     {
1469         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1470         ReleaseDC(0, hdc);
1471         return;
1472     }
1473
1474     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1475     {
1476         OUTLINETEXTMETRICW otm;
1477         UINT uiRet;
1478
1479         if (!is_font_installed(kd[i].face_name))
1480         {
1481             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1482             continue;
1483         }
1484
1485         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1486
1487         memset(&lf, 0, sizeof(lf));
1488         strcpy(lf.lfFaceName, kd[i].face_name);
1489         lf.lfHeight = kd[i].height;
1490         hfont = CreateFontIndirect(&lf);
1491         assert(hfont != 0);
1492
1493         hfont_old = SelectObject(hdc, hfont);
1494
1495         SetLastError(0xdeadbeef);
1496         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1497         uiRet = GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
1498         ok(uiRet == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1499
1500         ok(match_off_by_1(kd[i].tmHeight, otm.otmTextMetrics.tmHeight), "expected %d, got %d\n",
1501            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1502         ok(match_off_by_1(kd[i].tmAscent, otm.otmTextMetrics.tmAscent), "expected %d, got %d\n",
1503            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1504         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1505            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1506
1507         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1508            kd[i].otmEMSquare, otm.otmEMSquare);
1509         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1510            kd[i].otmAscent, otm.otmAscent);
1511         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1512            kd[i].otmDescent, otm.otmDescent);
1513         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1514            kd[i].otmLineGap, otm.otmLineGap);
1515         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1516            kd[i].otmMacDescent, otm.otmMacDescent);
1517         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
1518            kd[i].otmMacAscent, otm.otmMacAscent);
1519 todo_wine {
1520         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1521            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1522         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1523            kd[i].otmsXHeight, otm.otmsXHeight);
1524         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1525         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1526            kd[i].otmMacLineGap, otm.otmMacLineGap);
1527         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1528            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1529 }
1530
1531         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1532         trace("total_kern_pairs %u\n", total_kern_pairs);
1533         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1534
1535         /* Win98 (GetKerningPairsA) and XP behave differently here, the test
1536          * passes on XP.
1537          */
1538         SetLastError(0xdeadbeef);
1539         ret = GetKerningPairsW(hdc, 0, kern_pair);
1540         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1541            "got error %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1542         ok(ret == 0, "got %u, expected 0\n", ret);
1543
1544         ret = GetKerningPairsW(hdc, 100, NULL);
1545         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1546
1547         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1548         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1549
1550         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1551         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1552
1553         matches = 0;
1554
1555         for (n = 0; n < ret; n++)
1556         {
1557             DWORD j;
1558             /* Disabled to limit console spam */
1559             if (0 && kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1560                 trace("{'%c','%c',%d},\n",
1561                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1562             for (j = 0; j < kd[i].total_kern_pairs; j++)
1563             {
1564                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1565                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1566                 {
1567                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1568                        "pair %d:%d got %d, expected %d\n",
1569                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1570                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1571                     matches++;
1572                 }
1573             }
1574         }
1575
1576         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1577            matches, kd[i].total_kern_pairs);
1578
1579         HeapFree(GetProcessHeap(), 0, kern_pair);
1580
1581         SelectObject(hdc, hfont_old);
1582         DeleteObject(hfont);
1583     }
1584
1585     ReleaseDC(0, hdc);
1586 }
1587
1588 static void test_height_selection(void)
1589 {
1590     static const struct font_data
1591     {
1592         const char face_name[LF_FACESIZE];
1593         int requested_height;
1594         int weight, height, ascent, descent, int_leading, ext_leading, dpi;
1595     } fd[] =
1596     {
1597         {"Tahoma", -12, FW_NORMAL, 14, 12, 2, 2, 0, 96 },
1598         {"Tahoma", -24, FW_NORMAL, 29, 24, 5, 5, 0, 96 },
1599         {"Tahoma", -48, FW_NORMAL, 58, 48, 10, 10, 0, 96 },
1600         {"Tahoma", -96, FW_NORMAL, 116, 96, 20, 20, 0, 96 },
1601         {"Tahoma", -192, FW_NORMAL, 232, 192, 40, 40, 0, 96 },
1602         {"Tahoma", 12, FW_NORMAL, 12, 10, 2, 2, 0, 96 },
1603         {"Tahoma", 24, FW_NORMAL, 24, 20, 4, 4, 0, 96 },
1604         {"Tahoma", 48, FW_NORMAL, 48, 40, 8, 8, 0, 96 },
1605         {"Tahoma", 96, FW_NORMAL, 96, 80, 16, 17, 0, 96 },
1606         {"Tahoma", 192, FW_NORMAL, 192, 159, 33, 33, 0, 96 }
1607     };
1608     HDC hdc;
1609     LOGFONT lf;
1610     HFONT hfont, old_hfont;
1611     TEXTMETRIC tm;
1612     INT ret, i;
1613
1614     hdc = CreateCompatibleDC(0);
1615     assert(hdc);
1616
1617     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
1618     {
1619         if (!is_truetype_font_installed(fd[i].face_name))
1620         {
1621             skip("%s is not installed\n", fd[i].face_name);
1622             continue;
1623         }
1624
1625         memset(&lf, 0, sizeof(lf));
1626         lf.lfHeight = fd[i].requested_height;
1627         lf.lfWeight = fd[i].weight;
1628         strcpy(lf.lfFaceName, fd[i].face_name);
1629
1630         hfont = CreateFontIndirect(&lf);
1631         assert(hfont);
1632
1633         old_hfont = SelectObject(hdc, hfont);
1634         ret = GetTextMetrics(hdc, &tm);
1635         ok(ret, "GetTextMetrics error %d\n", GetLastError());
1636         if(fd[i].dpi == tm.tmDigitizedAspectX)
1637         {
1638             trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
1639             ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmWeight, fd[i].weight);
1640             ok(match_off_by_1(tm.tmHeight, fd[i].height), "%s(%d): tm.tmHeight %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmHeight, fd[i].height);
1641             ok(match_off_by_1(tm.tmAscent, fd[i].ascent), "%s(%d): tm.tmAscent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmAscent, fd[i].ascent);
1642             ok(match_off_by_1(tm.tmDescent, fd[i].descent), "%s(%d): tm.tmDescent %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmDescent, fd[i].descent);
1643 #if 0 /* FIXME: calculation of tmInternalLeading in Wine doesn't match what Windows does */
1644             ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmInternalLeading, fd[i].int_leading);
1645 #endif
1646             ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %d != %d\n", fd[i].face_name, fd[i].requested_height, tm.tmExternalLeading, fd[i].ext_leading);
1647         }
1648
1649         SelectObject(hdc, old_hfont);
1650         DeleteObject(hfont);
1651     }
1652
1653     DeleteDC(hdc);
1654 }
1655
1656 static void test_GetOutlineTextMetrics(void)
1657 {
1658     OUTLINETEXTMETRIC *otm;
1659     LOGFONT lf;
1660     HFONT hfont, hfont_old;
1661     HDC hdc;
1662     DWORD ret, otm_size;
1663     LPSTR unset_ptr;
1664
1665     if (!is_font_installed("Arial"))
1666     {
1667         skip("Arial is not installed\n");
1668         return;
1669     }
1670
1671     hdc = GetDC(0);
1672
1673     memset(&lf, 0, sizeof(lf));
1674     strcpy(lf.lfFaceName, "Arial");
1675     lf.lfHeight = -13;
1676     lf.lfWeight = FW_NORMAL;
1677     lf.lfPitchAndFamily = DEFAULT_PITCH;
1678     lf.lfQuality = PROOF_QUALITY;
1679     hfont = CreateFontIndirect(&lf);
1680     assert(hfont != 0);
1681
1682     hfont_old = SelectObject(hdc, hfont);
1683     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1684     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1685
1686     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1687
1688     memset(otm, 0xAA, otm_size);
1689     SetLastError(0xdeadbeef);
1690     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1691     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1692     ok(ret == 1 /* Win9x */ ||
1693        ret == otm->otmSize /* XP*/,
1694        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1695     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1696     {
1697         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1698         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1699         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1700         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1701     }
1702
1703     memset(otm, 0xAA, otm_size);
1704     SetLastError(0xdeadbeef);
1705     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1706     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1707     ok(ret == 1 /* Win9x */ ||
1708        ret == otm->otmSize /* XP*/,
1709        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1710     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1711     {
1712         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1713         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1714         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1715         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1716     }
1717
1718     /* ask about truncated data */
1719     memset(otm, 0xAA, otm_size);
1720     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1721     SetLastError(0xdeadbeef);
1722     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1723     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1724     ok(ret == 1 /* Win9x */ ||
1725        ret == otm->otmSize /* XP*/,
1726        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1727     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1728     {
1729         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1730         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1731         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1732     }
1733     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1734
1735     HeapFree(GetProcessHeap(), 0, otm);
1736
1737     SelectObject(hdc, hfont_old);
1738     DeleteObject(hfont);
1739
1740     ReleaseDC(0, hdc);
1741 }
1742
1743 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1744 {
1745     INT         y,
1746                 breakCount,
1747                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1748                 areaWidth = clientArea->right - clientArea->left,
1749                 nErrors = 0, e;
1750     BOOL        lastExtent = FALSE;
1751     PSTR        pFirstChar, pLastChar;
1752     SIZE        size;
1753     TEXTMETRICA tm;
1754     struct err
1755     {
1756         char extent[100];
1757         int  GetTextExtentExPointWWidth;
1758     } error[10];
1759
1760     GetTextMetricsA(hdc, &tm);
1761     y = clientArea->top;
1762     do {
1763         breakCount = 0;
1764         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1765         pFirstChar = str;
1766
1767         do {
1768             pLastChar = str;
1769
1770             /* if not at the end of the string, ... */
1771             if (*str == '\0') break;
1772             /* ... add the next word to the current extent */
1773             while (*str != '\0' && *str++ != tm.tmBreakChar);
1774             breakCount++;
1775             SetTextJustification(hdc, 0, 0);
1776             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1777         } while ((int) size.cx < areaWidth);
1778
1779         /* ignore trailing break chars */
1780         breakCount--;
1781         while (*(pLastChar - 1) == tm.tmBreakChar)
1782         {
1783             pLastChar--;
1784             breakCount--;
1785         }
1786
1787         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1788
1789         SetTextJustification(hdc, 0, 0);
1790         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1791
1792         /* do not justify the last extent */
1793         if (*str != '\0' && breakCount > 0)
1794         {
1795             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1796             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1797             justifiedWidth = size.cx;
1798         }
1799         else lastExtent = TRUE;
1800
1801         /* catch errors and report them */
1802         if (!lastExtent && (justifiedWidth != areaWidth))
1803         {
1804             memset(error[nErrors].extent, 0, 100);
1805             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1806             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1807             nErrors++;
1808         }
1809
1810         y += size.cy;
1811         str = pLastChar;
1812     } while (*str && y < clientArea->bottom);
1813
1814     for (e = 0; e < nErrors; e++)
1815     {
1816         /* The width returned by GetTextExtentPoint32() is exactly the same
1817            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1818         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1819             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1820             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1821     }
1822 }
1823
1824 static void test_SetTextJustification(void)
1825 {
1826     HDC hdc;
1827     RECT clientArea;
1828     LOGFONTA lf;
1829     HFONT hfont;
1830     HWND hwnd;
1831     static char testText[] =
1832             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1833             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1834             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1835             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1836             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1837             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1838             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1839
1840     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1841     GetClientRect( hwnd, &clientArea );
1842     hdc = GetDC( hwnd );
1843
1844     memset(&lf, 0, sizeof lf);
1845     lf.lfCharSet = ANSI_CHARSET;
1846     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1847     lf.lfWeight = FW_DONTCARE;
1848     lf.lfHeight = 20;
1849     lf.lfQuality = DEFAULT_QUALITY;
1850     lstrcpyA(lf.lfFaceName, "Times New Roman");
1851     hfont = create_font("Times New Roman", &lf);
1852     SelectObject(hdc, hfont);
1853
1854     testJustification(hdc, testText, &clientArea);
1855
1856     DeleteObject(hfont);
1857     ReleaseDC(hwnd, hdc);
1858     DestroyWindow(hwnd);
1859 }
1860
1861 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1862 {
1863     HDC hdc;
1864     LOGFONTA lf;
1865     HFONT hfont, hfont_old;
1866     CHARSETINFO csi;
1867     FONTSIGNATURE fs;
1868     INT cs;
1869     DWORD i, ret;
1870     char name[64];
1871
1872     assert(count <= 128);
1873
1874     memset(&lf, 0, sizeof(lf));
1875
1876     lf.lfCharSet = charset;
1877     lf.lfHeight = 10;
1878     lstrcpyA(lf.lfFaceName, "Arial");
1879     SetLastError(0xdeadbeef);
1880     hfont = CreateFontIndirectA(&lf);
1881     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1882
1883     hdc = GetDC(0);
1884     hfont_old = SelectObject(hdc, hfont);
1885
1886     cs = GetTextCharsetInfo(hdc, &fs, 0);
1887     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1888
1889     SetLastError(0xdeadbeef);
1890     ret = GetTextFaceA(hdc, sizeof(name), name);
1891     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1892
1893     if (charset == SYMBOL_CHARSET)
1894     {
1895         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1896         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1897     }
1898     else
1899     {
1900         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1901         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1902     }
1903
1904     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1905     {
1906         trace("Can't find codepage for charset %d\n", cs);
1907         ReleaseDC(0, hdc);
1908         return FALSE;
1909     }
1910     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1911
1912     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
1913     {
1914         skip("Font code page %d, looking for code page %d\n",
1915              pGdiGetCodePage(hdc), code_page);
1916         ReleaseDC(0, hdc);
1917         return FALSE;
1918     }
1919
1920     if (unicode)
1921     {
1922         char ansi_buf[128];
1923         WCHAR unicode_buf[128];
1924
1925         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1926
1927         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1928
1929         SetLastError(0xdeadbeef);
1930         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1931         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
1932            count, ret, GetLastError());
1933     }
1934     else
1935     {
1936         char ansi_buf[128];
1937
1938         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1939
1940         SetLastError(0xdeadbeef);
1941         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1942         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
1943            count, ret, GetLastError());
1944     }
1945
1946     SelectObject(hdc, hfont_old);
1947     DeleteObject(hfont);
1948
1949     ReleaseDC(0, hdc);
1950
1951     return TRUE;
1952 }
1953
1954 static void test_font_charset(void)
1955 {
1956     static struct charset_data
1957     {
1958         INT charset;
1959         UINT code_page;
1960         WORD font_idxA[128], font_idxW[128];
1961     } cd[] =
1962     {
1963         { ANSI_CHARSET, 1252 },
1964         { RUSSIAN_CHARSET, 1251 },
1965         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1966     };
1967     int i;
1968
1969     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1970     {
1971         win_skip("Skipping the font charset test on a Win9x platform\n");
1972         return;
1973     }
1974
1975     if (!is_font_installed("Arial"))
1976     {
1977         skip("Arial is not installed\n");
1978         return;
1979     }
1980
1981     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1982     {
1983         if (cd[i].charset == SYMBOL_CHARSET)
1984         {
1985             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1986             {
1987                 skip("Symbol or Wingdings is not installed\n");
1988                 break;
1989             }
1990         }
1991         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
1992             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
1993             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1994     }
1995
1996     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1997     if (i > 2)
1998     {
1999         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
2000         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
2001     }
2002     else
2003         skip("Symbol or Wingdings is not installed\n");
2004 }
2005
2006 static void test_GetFontUnicodeRanges(void)
2007 {
2008     LOGFONTA lf;
2009     HDC hdc;
2010     HFONT hfont, hfont_old;
2011     DWORD size;
2012     GLYPHSET *gs;
2013     DWORD i;
2014
2015     if (!pGetFontUnicodeRanges)
2016     {
2017         win_skip("GetFontUnicodeRanges not available before W2K\n");
2018         return;
2019     }
2020
2021     memset(&lf, 0, sizeof(lf));
2022     lstrcpyA(lf.lfFaceName, "Arial");
2023     hfont = create_font("Arial", &lf);
2024
2025     hdc = GetDC(0);
2026     hfont_old = SelectObject(hdc, hfont);
2027
2028     size = pGetFontUnicodeRanges(NULL, NULL);
2029     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2030
2031     size = pGetFontUnicodeRanges(hdc, NULL);
2032     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2033
2034     gs = HeapAlloc(GetProcessHeap(), 0, size);
2035
2036     size = pGetFontUnicodeRanges(hdc, gs);
2037     ok(size, "GetFontUnicodeRanges failed\n");
2038
2039     if (0) /* Disabled to limit console spam */
2040         for (i = 0; i < gs->cRanges; i++)
2041             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
2042     trace("found %u ranges\n", gs->cRanges);
2043
2044     HeapFree(GetProcessHeap(), 0, gs);
2045
2046     SelectObject(hdc, hfont_old);
2047     DeleteObject(hfont);
2048     ReleaseDC(NULL, hdc);
2049 }
2050
2051 #define MAX_ENUM_FONTS 4096
2052
2053 struct enum_font_data
2054 {
2055     int total;
2056     LOGFONT lf[MAX_ENUM_FONTS];
2057 };
2058
2059 struct enum_font_dataW
2060 {
2061     int total;
2062     LOGFONTW lf[MAX_ENUM_FONTS];
2063 };
2064
2065 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
2066 {
2067     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2068     const NEWTEXTMETRIC *ntm = (const NEWTEXTMETRIC *)tm;
2069
2070     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2071     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2072
2073     if (type != TRUETYPE_FONTTYPE) return 1;
2074
2075     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2076
2077     if (0) /* Disabled to limit console spam */
2078         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2079               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2080     if (efd->total < MAX_ENUM_FONTS)
2081         efd->lf[efd->total++] = *lf;
2082     else
2083         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2084
2085     return 1;
2086 }
2087
2088 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
2089 {
2090     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2091     const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2092
2093     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2094     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2095
2096     if (type != TRUETYPE_FONTTYPE) return 1;
2097
2098     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2099
2100     if (0) /* Disabled to limit console spam */
2101         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2102               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2103     if (efd->total < MAX_ENUM_FONTS)
2104         efd->lf[efd->total++] = *lf;
2105     else
2106         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2107
2108     return 1;
2109 }
2110
2111 static void get_charset_stats(struct enum_font_data *efd,
2112                               int *ansi_charset, int *symbol_charset,
2113                               int *russian_charset)
2114 {
2115     int i;
2116
2117     *ansi_charset = 0;
2118     *symbol_charset = 0;
2119     *russian_charset = 0;
2120
2121     for (i = 0; i < efd->total; i++)
2122     {
2123         switch (efd->lf[i].lfCharSet)
2124         {
2125         case ANSI_CHARSET:
2126             (*ansi_charset)++;
2127             break;
2128         case SYMBOL_CHARSET:
2129             (*symbol_charset)++;
2130             break;
2131         case RUSSIAN_CHARSET:
2132             (*russian_charset)++;
2133             break;
2134         }
2135     }
2136 }
2137
2138 static void get_charset_statsW(struct enum_font_dataW *efd,
2139                               int *ansi_charset, int *symbol_charset,
2140                               int *russian_charset)
2141 {
2142     int i;
2143
2144     *ansi_charset = 0;
2145     *symbol_charset = 0;
2146     *russian_charset = 0;
2147
2148     for (i = 0; i < efd->total; i++)
2149     {
2150         switch (efd->lf[i].lfCharSet)
2151         {
2152         case ANSI_CHARSET:
2153             (*ansi_charset)++;
2154             break;
2155         case SYMBOL_CHARSET:
2156             (*symbol_charset)++;
2157             break;
2158         case RUSSIAN_CHARSET:
2159             (*russian_charset)++;
2160             break;
2161         }
2162     }
2163 }
2164
2165 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2166 {
2167     struct enum_font_data efd;
2168     struct enum_font_dataW efdw;
2169     LOGFONT lf;
2170     HDC hdc;
2171     int i, ret, ansi_charset, symbol_charset, russian_charset;
2172
2173     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2174
2175     if (*font_name && !is_truetype_font_installed(font_name))
2176     {
2177         skip("%s is not installed\n", font_name);
2178         return;
2179     }
2180
2181     hdc = GetDC(0);
2182
2183     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2184      * while EnumFontFamiliesEx doesn't.
2185      */
2186     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2187     {
2188         /*
2189          * Use EnumFontFamiliesW since win98 crashes when the
2190          *    second parameter is NULL using EnumFontFamilies
2191          */
2192         efdw.total = 0;
2193         SetLastError(0xdeadbeef);
2194         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2195         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2196         if(ret)
2197         {
2198             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2199             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2200                   ansi_charset, symbol_charset, russian_charset);
2201             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2202             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2203             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2204             ok(russian_charset > 0 ||
2205                broken(russian_charset == 0), /* NT4 */
2206                "NULL family should enumerate RUSSIAN_CHARSET\n");
2207         }
2208
2209         efdw.total = 0;
2210         SetLastError(0xdeadbeef);
2211         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2212         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2213         if(ret)
2214         {
2215             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2216             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2217                   ansi_charset, symbol_charset, russian_charset);
2218             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2219             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2220             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2221             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2222         }
2223     }
2224
2225     efd.total = 0;
2226     SetLastError(0xdeadbeef);
2227     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2228     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2229     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2230     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2231           ansi_charset, symbol_charset, russian_charset,
2232           *font_name ? font_name : "<empty>");
2233     if (*font_name)
2234         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2235     else
2236         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2237     for (i = 0; i < efd.total; i++)
2238     {
2239 /* FIXME: remove completely once Wine is fixed */
2240 if (efd.lf[i].lfCharSet != font_charset)
2241 {
2242 todo_wine
2243     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2244 }
2245 else
2246         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2247         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2248            font_name, efd.lf[i].lfFaceName);
2249     }
2250
2251     memset(&lf, 0, sizeof(lf));
2252     lf.lfCharSet = ANSI_CHARSET;
2253     lstrcpy(lf.lfFaceName, font_name);
2254     efd.total = 0;
2255     SetLastError(0xdeadbeef);
2256     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2257     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2258     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2259     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2260           ansi_charset, symbol_charset, russian_charset,
2261           *font_name ? font_name : "<empty>");
2262     if (font_charset == SYMBOL_CHARSET)
2263     {
2264         if (*font_name)
2265             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2266         else
2267             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2268     }
2269     else
2270     {
2271         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2272         for (i = 0; i < efd.total; i++)
2273         {
2274             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2275             if (*font_name)
2276                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2277                    font_name, efd.lf[i].lfFaceName);
2278         }
2279     }
2280
2281     /* DEFAULT_CHARSET should enumerate all available charsets */
2282     memset(&lf, 0, sizeof(lf));
2283     lf.lfCharSet = DEFAULT_CHARSET;
2284     lstrcpy(lf.lfFaceName, font_name);
2285     efd.total = 0;
2286     SetLastError(0xdeadbeef);
2287     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2288     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2289     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2290     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2291           ansi_charset, symbol_charset, russian_charset,
2292           *font_name ? font_name : "<empty>");
2293     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2294     for (i = 0; i < efd.total; i++)
2295     {
2296         if (*font_name)
2297             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2298                font_name, efd.lf[i].lfFaceName);
2299     }
2300     if (*font_name)
2301     {
2302         switch (font_charset)
2303         {
2304         case ANSI_CHARSET:
2305             ok(ansi_charset > 0,
2306                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2307             ok(!symbol_charset,
2308                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2309             ok(russian_charset > 0,
2310                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2311             break;
2312         case SYMBOL_CHARSET:
2313             ok(!ansi_charset,
2314                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2315             ok(symbol_charset,
2316                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2317             ok(!russian_charset,
2318                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2319             break;
2320         case DEFAULT_CHARSET:
2321             ok(ansi_charset > 0,
2322                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2323             ok(symbol_charset > 0,
2324                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2325             ok(russian_charset > 0,
2326                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2327             break;
2328         }
2329     }
2330     else
2331     {
2332         ok(ansi_charset > 0,
2333            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2334         ok(symbol_charset > 0,
2335            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2336         ok(russian_charset > 0,
2337            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2338     }
2339
2340     memset(&lf, 0, sizeof(lf));
2341     lf.lfCharSet = SYMBOL_CHARSET;
2342     lstrcpy(lf.lfFaceName, font_name);
2343     efd.total = 0;
2344     SetLastError(0xdeadbeef);
2345     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2346     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2347     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2348     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2349           ansi_charset, symbol_charset, russian_charset,
2350           *font_name ? font_name : "<empty>");
2351     if (*font_name && font_charset == ANSI_CHARSET)
2352         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2353     else
2354     {
2355         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2356         for (i = 0; i < efd.total; i++)
2357         {
2358             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2359             if (*font_name)
2360                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2361                    font_name, efd.lf[i].lfFaceName);
2362         }
2363
2364         ok(!ansi_charset,
2365            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2366         ok(symbol_charset > 0,
2367            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2368         ok(!russian_charset,
2369            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2370     }
2371
2372     ReleaseDC(0, hdc);
2373 }
2374
2375 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2376 {
2377     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2378
2379     if (type != TRUETYPE_FONTTYPE) return 1;
2380
2381     if (efd->total < MAX_ENUM_FONTS)
2382         efd->lf[efd->total++] = *lf;
2383     else
2384         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2385
2386     return 1;
2387 }
2388
2389 static void test_EnumFontFamiliesEx_default_charset(void)
2390 {
2391     struct enum_font_data efd;
2392     LOGFONT gui_font, enum_font;
2393     DWORD ret;
2394     HDC hdc;
2395
2396     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2397     ok(ret, "GetObject failed.\n");
2398     if (!ret)
2399         return;
2400
2401     efd.total = 0;
2402
2403     hdc = GetDC(0);
2404     memset(&enum_font, 0, sizeof(enum_font));
2405     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2406     enum_font.lfCharSet = DEFAULT_CHARSET;
2407     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2408     ReleaseDC(0, hdc);
2409
2410     if (efd.total == 0) {
2411         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2412         return;
2413     }
2414     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2415
2416     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet,
2417        "(%s) got charset %d expected %d\n",
2418        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2419
2420     return;
2421 }
2422
2423 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2424 {
2425     HFONT hfont, hfont_prev;
2426     DWORD ret;
2427     GLYPHMETRICS gm1, gm2;
2428     LOGFONTA lf2 = *lf;
2429     WORD idx;
2430
2431     if(!pGetGlyphIndicesA)
2432         return;
2433
2434     /* negative widths are handled just as positive ones */
2435     lf2.lfWidth = -lf->lfWidth;
2436
2437     SetLastError(0xdeadbeef);
2438     hfont = CreateFontIndirectA(lf);
2439     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2440     check_font("original", lf, hfont);
2441
2442     hfont_prev = SelectObject(hdc, hfont);
2443
2444     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2445     if (ret == GDI_ERROR || idx == 0xffff)
2446     {
2447         SelectObject(hdc, hfont_prev);
2448         DeleteObject(hfont);
2449         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2450         return;
2451     }
2452
2453     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2454     memset(&gm1, 0xab, sizeof(gm1));
2455     SetLastError(0xdeadbeef);
2456     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2457     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2458
2459     SelectObject(hdc, hfont_prev);
2460     DeleteObject(hfont);
2461
2462     SetLastError(0xdeadbeef);
2463     hfont = CreateFontIndirectA(&lf2);
2464     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2465     check_font("negative width", &lf2, hfont);
2466
2467     hfont_prev = SelectObject(hdc, hfont);
2468
2469     memset(&gm2, 0xbb, sizeof(gm2));
2470     SetLastError(0xdeadbeef);
2471     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2472     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2473
2474     SelectObject(hdc, hfont_prev);
2475     DeleteObject(hfont);
2476
2477     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2478        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2479        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2480        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2481        gm1.gmCellIncX == gm2.gmCellIncX &&
2482        gm1.gmCellIncY == gm2.gmCellIncY,
2483        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2484        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2485        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2486        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2487        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2488 }
2489
2490 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2491 #include "pshpack2.h"
2492 typedef struct
2493 {
2494     USHORT version;
2495     SHORT xAvgCharWidth;
2496     USHORT usWeightClass;
2497     USHORT usWidthClass;
2498     SHORT fsType;
2499     SHORT ySubscriptXSize;
2500     SHORT ySubscriptYSize;
2501     SHORT ySubscriptXOffset;
2502     SHORT ySubscriptYOffset;
2503     SHORT ySuperscriptXSize;
2504     SHORT ySuperscriptYSize;
2505     SHORT ySuperscriptXOffset;
2506     SHORT ySuperscriptYOffset;
2507     SHORT yStrikeoutSize;
2508     SHORT yStrikeoutPosition;
2509     SHORT sFamilyClass;
2510     PANOSE panose;
2511     ULONG ulUnicodeRange1;
2512     ULONG ulUnicodeRange2;
2513     ULONG ulUnicodeRange3;
2514     ULONG ulUnicodeRange4;
2515     CHAR achVendID[4];
2516     USHORT fsSelection;
2517     USHORT usFirstCharIndex;
2518     USHORT usLastCharIndex;
2519     /* According to the Apple spec, original version didn't have the below fields,
2520      * version numbers were taken from the OpenType spec.
2521      */
2522     /* version 0 (TrueType 1.5) */
2523     USHORT sTypoAscender;
2524     USHORT sTypoDescender;
2525     USHORT sTypoLineGap;
2526     USHORT usWinAscent;
2527     USHORT usWinDescent;
2528     /* version 1 (TrueType 1.66) */
2529     ULONG ulCodePageRange1;
2530     ULONG ulCodePageRange2;
2531     /* version 2 (OpenType 1.2) */
2532     SHORT sxHeight;
2533     SHORT sCapHeight;
2534     USHORT usDefaultChar;
2535     USHORT usBreakChar;
2536     USHORT usMaxContext;
2537 } TT_OS2_V2;
2538 #include "poppack.h"
2539
2540 #ifdef WORDS_BIGENDIAN
2541 #define GET_BE_WORD(x) (x)
2542 #define GET_BE_DWORD(x) (x)
2543 #else
2544 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2545 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2546 #endif
2547
2548 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2549                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2550                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2551 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2552 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2553 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2554
2555 typedef struct
2556 {
2557     USHORT version;
2558     USHORT num_tables;
2559 } cmap_header;
2560
2561 typedef struct
2562 {
2563     USHORT plat_id;
2564     USHORT enc_id;
2565     ULONG offset;
2566 } cmap_encoding_record;
2567
2568 typedef struct
2569 {
2570     USHORT format;
2571     USHORT length;
2572     USHORT language;
2573
2574     BYTE glyph_ids[256];
2575 } cmap_format_0;
2576
2577 typedef struct
2578 {
2579     USHORT format;
2580     USHORT length;
2581     USHORT language;
2582
2583     USHORT seg_countx2;
2584     USHORT search_range;
2585     USHORT entry_selector;
2586     USHORT range_shift;
2587
2588     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2589 /* Then follows:
2590     USHORT pad;
2591     USHORT start_count[seg_countx2 / 2];
2592     USHORT id_delta[seg_countx2 / 2];
2593     USHORT id_range_offset[seg_countx2 / 2];
2594     USHORT glyph_ids[];
2595 */
2596 } cmap_format_4;
2597
2598 typedef struct
2599 {
2600     USHORT end_count;
2601     USHORT start_count;
2602     USHORT id_delta;
2603     USHORT id_range_offset;
2604 } cmap_format_4_seg;
2605
2606 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2607 {
2608     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2609        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2610        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2611        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2612        os2->panose.bWeight, os2->panose.bProportion);
2613 }
2614
2615 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2616 {
2617     int i;
2618     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2619
2620     *first = 256;
2621
2622     for(i = 0; i < 256; i++)
2623     {
2624         if(cmap->glyph_ids[i] == 0) continue;
2625         *last = i;
2626         if(*first == 256) *first = i;
2627     }
2628     if(*first == 256) return FALSE;
2629     return TRUE;
2630 }
2631
2632 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2633 {
2634     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2635     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2636     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2637     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2638     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2639 }
2640
2641 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2642 {
2643     int i;
2644     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2645     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2646     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2647
2648     *first = 0x10000;
2649
2650     for(i = 0; i < seg_count; i++)
2651     {
2652         DWORD code, index;
2653         cmap_format_4_seg seg;
2654
2655         get_seg4(cmap, i, &seg);
2656         for(code = seg.start_count; code <= seg.end_count; code++)
2657         {
2658             if(seg.id_range_offset == 0)
2659                 index = (seg.id_delta + code) & 0xffff;
2660             else
2661             {
2662                 index = seg.id_range_offset / 2
2663                     + code - seg.start_count
2664                     + i - seg_count;
2665
2666                 /* some fonts have broken last segment */
2667                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2668                     index = GET_BE_WORD(glyph_ids[index]);
2669                 else
2670                 {
2671                     trace("segment %04x/%04x index %04x points to nowhere\n",
2672                           seg.start_count, seg.end_count, index);
2673                     index = 0;
2674                 }
2675                 if(index) index += seg.id_delta;
2676             }
2677             if(*first == 0x10000)
2678                 *last = *first = code;
2679             else if(index)
2680                 *last = code;
2681         }
2682     }
2683
2684     if(*first == 0x10000) return FALSE;
2685     return TRUE;
2686 }
2687
2688 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2689 {
2690     USHORT i;
2691     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2692
2693     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2694     {
2695         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2696             return (BYTE *)header + GET_BE_DWORD(record->offset);
2697         record++;
2698     }
2699     return NULL;
2700 }
2701
2702 typedef enum
2703 {
2704     cmap_none,
2705     cmap_ms_unicode,
2706     cmap_ms_symbol
2707 } cmap_type;
2708
2709 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2710 {
2711     LONG size, ret;
2712     cmap_header *header;
2713     void *cmap;
2714     BOOL r = FALSE;
2715     WORD format;
2716
2717     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2718     ok(size != GDI_ERROR, "no cmap table found\n");
2719     if(size == GDI_ERROR) return FALSE;
2720
2721     header = HeapAlloc(GetProcessHeap(), 0, size);
2722     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2723     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2724     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2725
2726     cmap = get_cmap(header, 3, 1);
2727     if(cmap)
2728         *cmap_type = cmap_ms_unicode;
2729     else
2730     {
2731         cmap = get_cmap(header, 3, 0);
2732         if(cmap) *cmap_type = cmap_ms_symbol;
2733     }
2734     if(!cmap)
2735     {
2736         *cmap_type = cmap_none;
2737         goto end;
2738     }
2739
2740     format = GET_BE_WORD(*(WORD *)cmap);
2741     switch(format)
2742     {
2743     case 0:
2744         r = get_first_last_from_cmap0(cmap, first, last);
2745         break;
2746     case 4:
2747         r = get_first_last_from_cmap4(cmap, first, last, size);
2748         break;
2749     default:
2750         trace("unhandled cmap format %d\n", format);
2751         break;
2752     }
2753
2754 end:
2755     HeapFree(GetProcessHeap(), 0, header);
2756     return r;
2757 }
2758
2759 #define TT_PLATFORM_MICROSOFT 3
2760 #define TT_MS_ID_UNICODE_CS 1
2761 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2762 #define TT_NAME_ID_FULL_NAME 4
2763
2764 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, char *out_buf, SIZE_T out_size)
2765 {
2766     struct sfnt_name_header
2767     {
2768         USHORT format;
2769         USHORT number_of_record;
2770         USHORT storage_offset;
2771     } *header;
2772     struct sfnt_name
2773     {
2774         USHORT platform_id;
2775         USHORT encoding_id;
2776         USHORT language_id;
2777         USHORT name_id;
2778         USHORT length;
2779         USHORT offset;
2780     } *entry;
2781     BOOL r = FALSE;
2782     LONG size, offset, length;
2783     LONG c, ret;
2784     WCHAR *name;
2785     BYTE *data;
2786     USHORT i;
2787
2788     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2789     ok(size != GDI_ERROR, "no name table found\n");
2790     if(size == GDI_ERROR) return FALSE;
2791
2792     data = HeapAlloc(GetProcessHeap(), 0, size);
2793     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2794     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2795
2796     header = (void *)data;
2797     header->format = GET_BE_WORD(header->format);
2798     header->number_of_record = GET_BE_WORD(header->number_of_record);
2799     header->storage_offset = GET_BE_WORD(header->storage_offset);
2800     if (header->format != 0)
2801     {
2802         trace("got format %u\n", header->format);
2803         goto out;
2804     }
2805     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2806     {
2807         trace("number records out of range: %d\n", header->number_of_record);
2808         goto out;
2809     }
2810     if (header->storage_offset >= size)
2811     {
2812         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2813         goto out;
2814     }
2815
2816     entry = (void *)&header[1];
2817     for (i = 0; i < header->number_of_record; i++)
2818     {
2819         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2820             GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS ||
2821             GET_BE_WORD(entry[i].language_id) != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
2822             GET_BE_WORD(entry[i].name_id) != name_id)
2823         {
2824             continue;
2825         }
2826
2827         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2828         length = GET_BE_WORD(entry[i].length);
2829         if (offset + length > size)
2830         {
2831             trace("entry %d is out of range\n", i);
2832             break;
2833         }
2834         if (length >= out_size)
2835         {
2836             trace("buffer too small for entry %d\n", i);
2837             break;
2838         }
2839
2840         name = (WCHAR *)(data + offset);
2841         for (c = 0; c < length / 2; c++)
2842             out_buf[c] = GET_BE_WORD(name[c]);
2843         out_buf[c] = 0;
2844
2845         r = TRUE;
2846         break;
2847     }
2848
2849 out:
2850     HeapFree(GetProcessHeap(), 0, data);
2851     return r;
2852 }
2853
2854 static void test_text_metrics(const LOGFONT *lf, const NEWTEXTMETRIC *ntm)
2855 {
2856     HDC hdc;
2857     HFONT hfont, hfont_old;
2858     TEXTMETRICA tmA;
2859     TT_OS2_V2 tt_os2;
2860     LONG size, ret;
2861     const char *font_name = lf->lfFaceName;
2862     DWORD cmap_first = 0, cmap_last = 0;
2863     UINT ascent, descent, cell_height;
2864     cmap_type cmap_type;
2865     BOOL sys_lang_non_english;
2866
2867     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2868     hdc = GetDC(0);
2869
2870     SetLastError(0xdeadbeef);
2871     hfont = CreateFontIndirectA(lf);
2872     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2873
2874     hfont_old = SelectObject(hdc, hfont);
2875
2876     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2877     if (size == GDI_ERROR)
2878     {
2879         trace("OS/2 chunk was not found\n");
2880         goto end_of_test;
2881     }
2882     if (size > sizeof(tt_os2))
2883     {
2884         trace("got too large OS/2 chunk of size %u\n", size);
2885         size = sizeof(tt_os2);
2886     }
2887
2888     memset(&tt_os2, 0, sizeof(tt_os2));
2889     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2890     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2891
2892     ascent = GET_BE_WORD(tt_os2.usWinAscent);
2893     descent = GET_BE_WORD(tt_os2.usWinDescent);
2894     cell_height = ascent + descent;
2895     ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
2896        font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
2897
2898     SetLastError(0xdeadbeef);
2899     ret = GetTextMetricsA(hdc, &tmA);
2900     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2901
2902     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2903     {
2904         skip("Unable to retrieve first and last glyphs from cmap\n");
2905     }
2906     else
2907     {
2908         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2909         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2910         UINT os2_first_char, os2_last_char, default_char, break_char;
2911         USHORT version;
2912         TEXTMETRICW tmW;
2913
2914         version = GET_BE_WORD(tt_os2.version);
2915
2916         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2917         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2918         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2919         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2920
2921         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2922               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2923               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2924
2925         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2926         {
2927             expect_first_W    = 0;
2928             switch(GetACP())
2929             {
2930             case 1257:  /* Baltic */
2931                 expect_last_W = 0xf8fd;
2932                 break;
2933             default:
2934                 expect_last_W = 0xf0ff;
2935             }
2936             expect_break_W    = 0x20;
2937             expect_default_W  = expect_break_W - 1;
2938             expect_first_A    = 0x1e;
2939             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2940         }
2941         else
2942         {
2943             expect_first_W    = cmap_first;
2944             expect_last_W     = min(cmap_last, os2_last_char);
2945             if(os2_first_char <= 1)
2946                 expect_break_W = os2_first_char + 2;
2947             else if(os2_first_char > 0xff)
2948                 expect_break_W = 0x20;
2949             else
2950                 expect_break_W = os2_first_char;
2951             expect_default_W  = expect_break_W - 1;
2952             expect_first_A    = expect_default_W - 1;
2953             expect_last_A     = min(expect_last_W, 0xff);
2954         }
2955         expect_break_A    = expect_break_W;
2956         expect_default_A  = expect_default_W;
2957
2958         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2959         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2960             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2961                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2962                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2963         else
2964             ok(tmA.tmFirstChar == expect_first_A ||
2965                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2966                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2967         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2968             ok(tmA.tmLastChar == expect_last_A ||
2969                tmA.tmLastChar == 0xff /* win9x */,
2970                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2971         else
2972            skip("tmLastChar is DBCS lead byte\n");
2973         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2974            font_name, tmA.tmBreakChar, expect_break_A);
2975         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2976            "A: tmDefaultChar for %s got %02x expected %02x\n",
2977            font_name, tmA.tmDefaultChar, expect_default_A);
2978
2979
2980         SetLastError(0xdeadbeef);
2981         ret = GetTextMetricsW(hdc, &tmW);
2982         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2983            "GetTextMetricsW error %u\n", GetLastError());
2984         if (ret)
2985         {
2986             /* Wine uses the os2 first char */
2987             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2988                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2989                              font_name, tmW.tmFirstChar, expect_first_W);
2990             else
2991                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2992                    font_name, tmW.tmFirstChar, expect_first_W);
2993
2994             /* Wine uses the os2 last char */
2995             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2996                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2997                              font_name, tmW.tmLastChar, expect_last_W);
2998             else
2999                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3000                    font_name, tmW.tmLastChar, expect_last_W);
3001             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
3002                font_name, tmW.tmBreakChar, expect_break_W);
3003             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
3004                "W: tmDefaultChar for %s got %02x expected %02x\n",
3005                font_name, tmW.tmDefaultChar, expect_default_W);
3006
3007             /* Test the aspect ratio while we have tmW */
3008             ret = GetDeviceCaps(hdc, LOGPIXELSX);
3009             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3010                tmW.tmDigitizedAspectX, ret);
3011             ret = GetDeviceCaps(hdc, LOGPIXELSY);
3012             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3013                tmW.tmDigitizedAspectX, ret);
3014         }
3015     }
3016
3017     /* test FF_ values */
3018     switch(tt_os2.panose.bFamilyType)
3019     {
3020     case PAN_ANY:
3021     case PAN_NO_FIT:
3022     case PAN_FAMILY_TEXT_DISPLAY:
3023     case PAN_FAMILY_PICTORIAL:
3024     default:
3025         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3026            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3027         {
3028             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3029             break;
3030         }
3031         switch(tt_os2.panose.bSerifStyle)
3032         {
3033         case PAN_ANY:
3034         case PAN_NO_FIT:
3035         default:
3036             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3037             break;
3038
3039         case PAN_SERIF_COVE:
3040         case PAN_SERIF_OBTUSE_COVE:
3041         case PAN_SERIF_SQUARE_COVE:
3042         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3043         case PAN_SERIF_SQUARE:
3044         case PAN_SERIF_THIN:
3045         case PAN_SERIF_BONE:
3046         case PAN_SERIF_EXAGGERATED:
3047         case PAN_SERIF_TRIANGLE:
3048             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
3049             break;
3050
3051         case PAN_SERIF_NORMAL_SANS:
3052         case PAN_SERIF_OBTUSE_SANS:
3053         case PAN_SERIF_PERP_SANS:
3054         case PAN_SERIF_FLARED:
3055         case PAN_SERIF_ROUNDED:
3056             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
3057             break;
3058         }
3059         break;
3060
3061     case PAN_FAMILY_SCRIPT:
3062         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
3063         break;
3064
3065     case PAN_FAMILY_DECORATIVE:
3066         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
3067         break;
3068     }
3069
3070     test_negative_width(hdc, lf);
3071
3072 end_of_test:
3073     SelectObject(hdc, hfont_old);
3074     DeleteObject(hfont);
3075
3076     ReleaseDC(0, hdc);
3077 }
3078
3079 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3080 {
3081     INT *enumed = (INT *)lParam;
3082
3083     if (type == TRUETYPE_FONTTYPE)
3084     {
3085         (*enumed)++;
3086         test_text_metrics(lf, (const NEWTEXTMETRIC *)ntm);
3087     }
3088     return 1;
3089 }
3090
3091 static void test_GetTextMetrics(void)
3092 {
3093     LOGFONTA lf;
3094     HDC hdc;
3095     INT enumed;
3096
3097     /* Report only once */
3098     if(!pGetGlyphIndicesA)
3099         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
3100
3101     hdc = GetDC(0);
3102
3103     memset(&lf, 0, sizeof(lf));
3104     lf.lfCharSet = DEFAULT_CHARSET;
3105     enumed = 0;
3106     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
3107     trace("Tested metrics of %d truetype fonts\n", enumed);
3108
3109     ReleaseDC(0, hdc);
3110 }
3111
3112 static void test_nonexistent_font(void)
3113 {
3114     static const struct
3115     {
3116         const char *name;
3117         int charset;
3118     } font_subst[] =
3119     {
3120         { "Times New Roman Baltic", 186 },
3121         { "Times New Roman CE", 238 },
3122         { "Times New Roman CYR", 204 },
3123         { "Times New Roman Greek", 161 },
3124         { "Times New Roman TUR", 162 }
3125     };
3126     LOGFONTA lf;
3127     HDC hdc;
3128     HFONT hfont;
3129     CHARSETINFO csi;
3130     INT cs, expected_cs, i;
3131     char buf[LF_FACESIZE];
3132
3133     if (!is_truetype_font_installed("Arial") ||
3134         !is_truetype_font_installed("Times New Roman"))
3135     {
3136         skip("Arial or Times New Roman not installed\n");
3137         return;
3138     }
3139
3140     expected_cs = GetACP();
3141     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
3142     {
3143         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
3144         return;
3145     }
3146     expected_cs = csi.ciCharset;
3147     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
3148
3149     hdc = GetDC(0);
3150
3151     memset(&lf, 0, sizeof(lf));
3152     lf.lfHeight = 100;
3153     lf.lfWeight = FW_REGULAR;
3154     lf.lfCharSet = ANSI_CHARSET;
3155     lf.lfPitchAndFamily = FF_SWISS;
3156     strcpy(lf.lfFaceName, "Nonexistent font");
3157     hfont = CreateFontIndirectA(&lf);
3158     hfont = SelectObject(hdc, hfont);
3159     GetTextFaceA(hdc, sizeof(buf), buf);
3160     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3161     cs = GetTextCharset(hdc);
3162     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3163     DeleteObject(SelectObject(hdc, hfont));
3164
3165     memset(&lf, 0, sizeof(lf));
3166     lf.lfHeight = -13;
3167     lf.lfWeight = FW_DONTCARE;
3168     strcpy(lf.lfFaceName, "Nonexistent font");
3169     hfont = CreateFontIndirectA(&lf);
3170     hfont = SelectObject(hdc, hfont);
3171     GetTextFaceA(hdc, sizeof(buf), buf);
3172 todo_wine /* Wine uses Arial for all substitutions */
3173     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3174        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3175        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3176        "Got %s\n", buf);
3177     cs = GetTextCharset(hdc);
3178     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3179     DeleteObject(SelectObject(hdc, hfont));
3180
3181     memset(&lf, 0, sizeof(lf));
3182     lf.lfHeight = -13;
3183     lf.lfWeight = FW_REGULAR;
3184     strcpy(lf.lfFaceName, "Nonexistent font");
3185     hfont = CreateFontIndirectA(&lf);
3186     hfont = SelectObject(hdc, hfont);
3187     GetTextFaceA(hdc, sizeof(buf), buf);
3188     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3189        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3190     cs = GetTextCharset(hdc);
3191     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3192     DeleteObject(SelectObject(hdc, hfont));
3193
3194     memset(&lf, 0, sizeof(lf));
3195     lf.lfHeight = -13;
3196     lf.lfWeight = FW_DONTCARE;
3197     strcpy(lf.lfFaceName, "Times New Roman");
3198     hfont = CreateFontIndirectA(&lf);
3199     hfont = SelectObject(hdc, hfont);
3200     GetTextFaceA(hdc, sizeof(buf), buf);
3201     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3202     cs = GetTextCharset(hdc);
3203     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3204     DeleteObject(SelectObject(hdc, hfont));
3205
3206     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3207     {
3208         memset(&lf, 0, sizeof(lf));
3209         lf.lfHeight = -13;
3210         lf.lfWeight = FW_REGULAR;
3211         strcpy(lf.lfFaceName, font_subst[i].name);
3212         hfont = CreateFontIndirectA(&lf);
3213         hfont = SelectObject(hdc, hfont);
3214         cs = GetTextCharset(hdc);
3215         if (font_subst[i].charset == expected_cs)
3216         {
3217             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3218             GetTextFaceA(hdc, sizeof(buf), buf);
3219             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3220         }
3221         else
3222         {
3223             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3224             GetTextFaceA(hdc, sizeof(buf), buf);
3225             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3226                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3227         }
3228         DeleteObject(SelectObject(hdc, hfont));
3229
3230         memset(&lf, 0, sizeof(lf));
3231         lf.lfHeight = -13;
3232         lf.lfWeight = FW_DONTCARE;
3233         strcpy(lf.lfFaceName, font_subst[i].name);
3234         hfont = CreateFontIndirectA(&lf);
3235         hfont = SelectObject(hdc, hfont);
3236         GetTextFaceA(hdc, sizeof(buf), buf);
3237         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3238            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3239            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3240            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3241            "got %s for font %s\n", buf, font_subst[i].name);
3242         cs = GetTextCharset(hdc);
3243         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3244         DeleteObject(SelectObject(hdc, hfont));
3245     }
3246
3247     ReleaseDC(0, hdc);
3248 }
3249
3250 static void test_GdiRealizationInfo(void)
3251 {
3252     HDC hdc;
3253     DWORD info[4];
3254     BOOL r;
3255     HFONT hfont, hfont_old;
3256     LOGFONTA lf;
3257
3258     if(!pGdiRealizationInfo)
3259     {
3260         win_skip("GdiRealizationInfo not available\n");
3261         return;
3262     }
3263
3264     hdc = GetDC(0);
3265
3266     memset(info, 0xcc, sizeof(info));
3267     r = pGdiRealizationInfo(hdc, info);
3268     ok(r != 0, "ret 0\n");
3269     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3270     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3271
3272     if (!is_truetype_font_installed("Arial"))
3273     {
3274         skip("skipping GdiRealizationInfo with truetype font\n");
3275         goto end;
3276     }
3277
3278     memset(&lf, 0, sizeof(lf));
3279     strcpy(lf.lfFaceName, "Arial");
3280     lf.lfHeight = 20;
3281     lf.lfWeight = FW_NORMAL;
3282     hfont = CreateFontIndirectA(&lf);
3283     hfont_old = SelectObject(hdc, hfont);
3284
3285     memset(info, 0xcc, sizeof(info));
3286     r = pGdiRealizationInfo(hdc, info);
3287     ok(r != 0, "ret 0\n");
3288     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3289     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3290
3291     DeleteObject(SelectObject(hdc, hfont_old));
3292
3293  end:
3294     ReleaseDC(0, hdc);
3295 }
3296
3297 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3298    the nul in the count of characters copied when the face name buffer is not
3299    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3300    always includes it.  */
3301 static void test_GetTextFace(void)
3302 {
3303     static const char faceA[] = "Tahoma";
3304     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3305     LOGFONTA fA = {0};
3306     LOGFONTW fW = {0};
3307     char bufA[LF_FACESIZE];
3308     WCHAR bufW[LF_FACESIZE];
3309     HFONT f, g;
3310     HDC dc;
3311     int n;
3312
3313     if(!is_font_installed("Tahoma"))
3314     {
3315         skip("Tahoma is not installed so skipping this test\n");
3316         return;
3317     }
3318
3319     /* 'A' case.  */
3320     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3321     f = CreateFontIndirectA(&fA);
3322     ok(f != NULL, "CreateFontIndirectA failed\n");
3323
3324     dc = GetDC(NULL);
3325     g = SelectObject(dc, f);
3326     n = GetTextFaceA(dc, sizeof bufA, bufA);
3327     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3328     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3329
3330     /* Play with the count arg.  */
3331     bufA[0] = 'x';
3332     n = GetTextFaceA(dc, 0, bufA);
3333     ok(n == 0, "GetTextFaceA returned %d\n", n);
3334     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3335
3336     bufA[0] = 'x';
3337     n = GetTextFaceA(dc, 1, bufA);
3338     ok(n == 0, "GetTextFaceA returned %d\n", n);
3339     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3340
3341     bufA[0] = 'x'; bufA[1] = 'y';
3342     n = GetTextFaceA(dc, 2, bufA);
3343     ok(n == 1, "GetTextFaceA returned %d\n", n);
3344     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3345
3346     n = GetTextFaceA(dc, 0, NULL);
3347     ok(n == sizeof faceA ||
3348        broken(n == 0), /* win98, winMe */
3349        "GetTextFaceA returned %d\n", n);
3350
3351     DeleteObject(SelectObject(dc, g));
3352     ReleaseDC(NULL, dc);
3353
3354     /* 'W' case.  */
3355     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3356     SetLastError(0xdeadbeef);
3357     f = CreateFontIndirectW(&fW);
3358     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3359     {
3360         win_skip("CreateFontIndirectW is not implemented\n");
3361         return;
3362     }
3363     ok(f != NULL, "CreateFontIndirectW failed\n");
3364
3365     dc = GetDC(NULL);
3366     g = SelectObject(dc, f);
3367     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3368     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3369     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3370
3371     /* Play with the count arg.  */
3372     bufW[0] = 'x';
3373     n = GetTextFaceW(dc, 0, bufW);
3374     ok(n == 0, "GetTextFaceW returned %d\n", n);
3375     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3376
3377     bufW[0] = 'x';
3378     n = GetTextFaceW(dc, 1, bufW);
3379     ok(n == 1, "GetTextFaceW returned %d\n", n);
3380     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3381
3382     bufW[0] = 'x'; bufW[1] = 'y';
3383     n = GetTextFaceW(dc, 2, bufW);
3384     ok(n == 2, "GetTextFaceW returned %d\n", n);
3385     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3386
3387     n = GetTextFaceW(dc, 0, NULL);
3388     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3389
3390     DeleteObject(SelectObject(dc, g));
3391     ReleaseDC(NULL, dc);
3392 }
3393
3394 static void test_orientation(void)
3395 {
3396     static const char test_str[11] = "Test String";
3397     HDC hdc;
3398     LOGFONTA lf;
3399     HFONT hfont, old_hfont;
3400     SIZE size;
3401
3402     if (!is_truetype_font_installed("Arial"))
3403     {
3404         skip("Arial is not installed\n");
3405         return;
3406     }
3407
3408     hdc = CreateCompatibleDC(0);
3409     memset(&lf, 0, sizeof(lf));
3410     lstrcpyA(lf.lfFaceName, "Arial");
3411     lf.lfHeight = 72;
3412     lf.lfOrientation = lf.lfEscapement = 900;
3413     hfont = create_font("orientation", &lf);
3414     old_hfont = SelectObject(hdc, hfont);
3415     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3416     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3417     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3418     SelectObject(hdc, old_hfont);
3419     DeleteObject(hfont);
3420     DeleteDC(hdc);
3421 }
3422
3423 static void test_oemcharset(void)
3424 {
3425     HDC hdc;
3426     LOGFONTA lf, clf;
3427     HFONT hfont, old_hfont;
3428     int charset;
3429
3430     hdc = CreateCompatibleDC(0);
3431     ZeroMemory(&lf, sizeof(lf));
3432     lf.lfHeight = 12;
3433     lf.lfCharSet = OEM_CHARSET;
3434     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3435     lstrcpyA(lf.lfFaceName, "Terminal");
3436     hfont = CreateFontIndirectA(&lf);
3437     old_hfont = SelectObject(hdc, hfont);
3438     charset = GetTextCharset(hdc);
3439 todo_wine
3440     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3441     hfont = SelectObject(hdc, old_hfont);
3442     GetObjectA(hfont, sizeof(clf), &clf);
3443     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3444     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3445     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3446     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3447     DeleteObject(hfont);
3448     DeleteDC(hdc);
3449 }
3450
3451 static void test_GetGlyphOutline(void)
3452 {
3453     HDC hdc;
3454     GLYPHMETRICS gm, gm2;
3455     LOGFONTA lf;
3456     HFONT hfont, old_hfont;
3457     INT ret, ret2;
3458     static const struct
3459     {
3460         UINT cs;
3461         UINT a;
3462         UINT w;
3463     } c[] =
3464     {
3465         {ANSI_CHARSET, 0x30, 0x30},
3466         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3467         {HANGEUL_CHARSET, 0x8141, 0xac02},
3468         {JOHAB_CHARSET, 0x8446, 0x3135},
3469         {GB2312_CHARSET, 0x8141, 0x4e04},
3470         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3471     };
3472     UINT i;
3473
3474     if (!is_truetype_font_installed("Tahoma"))
3475     {
3476         skip("Tahoma is not installed\n");
3477         return;
3478     }
3479
3480     hdc = CreateCompatibleDC(0);
3481     memset(&lf, 0, sizeof(lf));
3482     lf.lfHeight = 72;
3483     lstrcpyA(lf.lfFaceName, "Tahoma");
3484     SetLastError(0xdeadbeef);
3485     hfont = CreateFontIndirectA(&lf);
3486     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3487     old_hfont = SelectObject(hdc, hfont);
3488
3489     memset(&gm, 0, sizeof(gm));
3490     SetLastError(0xdeadbeef);
3491     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3492     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3493
3494     memset(&gm, 0, sizeof(gm));
3495     SetLastError(0xdeadbeef);
3496     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3497     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3498     ok(GetLastError() == 0xdeadbeef ||
3499        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3500        "expected 0xdeadbeef, got %u\n", GetLastError());
3501
3502     memset(&gm, 0, sizeof(gm));
3503     SetLastError(0xdeadbeef);
3504     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3505     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3506         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3507
3508     memset(&gm, 0, sizeof(gm));
3509     SetLastError(0xdeadbeef);
3510     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3511     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3512     {
3513        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3514        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3515     }
3516
3517     /* test for needed buffer size request on space char */
3518     memset(&gm, 0, sizeof(gm));
3519     SetLastError(0xdeadbeef);
3520     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3521     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3522         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3523
3524     /* requesting buffer size for space char + error */
3525     memset(&gm, 0, sizeof(gm));
3526     SetLastError(0xdeadbeef);
3527     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3528     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3529     {
3530        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3531        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3532     }
3533
3534     SelectObject(hdc, old_hfont);
3535     DeleteObject(hfont);
3536
3537     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3538     {
3539         lf.lfFaceName[0] = '\0';
3540         lf.lfCharSet = c[i].cs;
3541         lf.lfPitchAndFamily = 0;
3542         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3543         {
3544             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3545             continue;
3546         }
3547
3548         old_hfont = SelectObject(hdc, hfont);
3549
3550         /* expected to ignore superfluous bytes (sigle-byte character) */
3551         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3552         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3553         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3554
3555         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3556         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3557            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3558
3559         /* expected to ignore superfluous bytes (double-byte character) */
3560         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3561         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3562         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3563            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3564
3565         /* expected to match wide-char version results */
3566         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3567         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3568
3569         hfont = SelectObject(hdc, old_hfont);
3570         DeleteObject(hfont);
3571     }
3572
3573     DeleteDC(hdc);
3574 }
3575
3576 /* bug #9995: there is a limit to the character width that can be specified */
3577 static void test_GetTextMetrics2(const char *fontname, int font_height)
3578 {
3579     HFONT of, hf;
3580     HDC hdc;
3581     TEXTMETRICA tm;
3582     BOOL ret;
3583     int ave_width, height, width, ratio, scale;
3584
3585     if (!is_truetype_font_installed( fontname)) {
3586         skip("%s is not installed\n", fontname);
3587         return;
3588     }
3589     hdc = CreateCompatibleDC(0);
3590     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3591     /* select width = 0 */
3592     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3593             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3594             DEFAULT_QUALITY, VARIABLE_PITCH,
3595             fontname);
3596     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3597     of = SelectObject( hdc, hf);
3598     ret = GetTextMetricsA( hdc, &tm);
3599     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3600     height = tm.tmHeight;
3601     ave_width = tm.tmAveCharWidth;
3602     SelectObject( hdc, of);
3603     DeleteObject( hf);
3604
3605     trace("height %d, ave width %d\n", height, ave_width);
3606
3607     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3608     {
3609         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3610                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3611                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3612         ok(hf != 0, "CreateFont failed\n");
3613         of = SelectObject(hdc, hf);
3614         ret = GetTextMetrics(hdc, &tm);
3615         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3616         SelectObject(hdc, of);
3617         DeleteObject(hf);
3618
3619         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3620             break;
3621     }
3622
3623     DeleteDC(hdc);
3624
3625     ratio = width / height;
3626     scale = width / ave_width;
3627
3628     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3629           width, height, ratio, width, ave_width, scale);
3630
3631     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3632 }
3633
3634 static void test_CreateFontIndirect(void)
3635 {
3636     LOGFONTA lf, getobj_lf;
3637     int ret, i;
3638     HFONT hfont;
3639     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3640
3641     memset(&lf, 0, sizeof(lf));
3642     lf.lfCharSet = ANSI_CHARSET;
3643     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3644     lf.lfHeight = 16;
3645     lf.lfWidth = 16;
3646     lf.lfQuality = DEFAULT_QUALITY;
3647     lf.lfItalic = FALSE;
3648     lf.lfWeight = FW_DONTCARE;
3649
3650     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3651     {
3652         lstrcpyA(lf.lfFaceName, TestName[i]);
3653         hfont = CreateFontIndirectA(&lf);
3654         ok(hfont != 0, "CreateFontIndirectA failed\n");
3655         SetLastError(0xdeadbeef);
3656         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3657         ok(ret, "GetObject failed: %d\n", GetLastError());
3658         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3659         ok(lf.lfWeight == getobj_lf.lfWeight ||
3660            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3661            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3662         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3663            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3664            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3665         DeleteObject(hfont);
3666     }
3667 }
3668
3669 static void test_CreateFontIndirectEx(void)
3670 {
3671     ENUMLOGFONTEXDVA lfex;
3672     HFONT hfont;
3673
3674     if (!pCreateFontIndirectExA)
3675     {
3676         win_skip("CreateFontIndirectExA is not available\n");
3677         return;
3678     }
3679
3680     if (!is_truetype_font_installed("Arial"))
3681     {
3682         skip("Arial is not installed\n");
3683         return;
3684     }
3685
3686     SetLastError(0xdeadbeef);
3687     hfont = pCreateFontIndirectExA(NULL);
3688     ok(hfont == NULL, "got %p\n", hfont);
3689     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3690
3691     memset(&lfex, 0, sizeof(lfex));
3692     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3693     hfont = pCreateFontIndirectExA(&lfex);
3694     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3695     if (hfont)
3696         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3697     DeleteObject(hfont);
3698 }
3699
3700 static void free_font(void *font)
3701 {
3702     UnmapViewOfFile(font);
3703 }
3704
3705 static void *load_font(const char *font_name, DWORD *font_size)
3706 {
3707     char file_name[MAX_PATH];
3708     HANDLE file, mapping;
3709     void *font;
3710
3711     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3712     strcat(file_name, "\\fonts\\");
3713     strcat(file_name, font_name);
3714
3715     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3716     if (file == INVALID_HANDLE_VALUE) return NULL;
3717
3718     *font_size = GetFileSize(file, NULL);
3719
3720     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3721     if (!mapping)
3722     {
3723         CloseHandle(file);
3724         return NULL;
3725     }
3726
3727     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3728
3729     CloseHandle(file);
3730     CloseHandle(mapping);
3731     return font;
3732 }
3733
3734 static void test_AddFontMemResource(void)
3735 {
3736     void *font;
3737     DWORD font_size, num_fonts;
3738     HANDLE ret;
3739     BOOL bRet;
3740
3741     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3742     {
3743         win_skip("AddFontMemResourceEx is not available on this platform\n");
3744         return;
3745     }
3746
3747     font = load_font("sserife.fon", &font_size);
3748     if (!font)
3749     {
3750         skip("Unable to locate and load font sserife.fon\n");
3751         return;
3752     }
3753
3754     SetLastError(0xdeadbeef);
3755     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3756     ok(!ret, "AddFontMemResourceEx should fail\n");
3757     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3758        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3759        GetLastError());
3760
3761     SetLastError(0xdeadbeef);
3762     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3763     ok(!ret, "AddFontMemResourceEx should fail\n");
3764     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3765        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3766        GetLastError());
3767
3768     SetLastError(0xdeadbeef);
3769     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3770     ok(!ret, "AddFontMemResourceEx should fail\n");
3771     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3772        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3773        GetLastError());
3774
3775     SetLastError(0xdeadbeef);
3776     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3777     ok(!ret, "AddFontMemResourceEx should fail\n");
3778     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3779        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3780        GetLastError());
3781
3782     SetLastError(0xdeadbeef);
3783     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3784     ok(!ret, "AddFontMemResourceEx should fail\n");
3785     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3786        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3787        GetLastError());
3788
3789     SetLastError(0xdeadbeef);
3790     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3791     ok(!ret, "AddFontMemResourceEx should fail\n");
3792     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3793        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3794        GetLastError());
3795
3796     num_fonts = 0xdeadbeef;
3797     SetLastError(0xdeadbeef);
3798     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3799     ok(!ret, "AddFontMemResourceEx should fail\n");
3800     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3801        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3802        GetLastError());
3803     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3804
3805     if (0) /* hangs under windows 2000 */
3806     {
3807         num_fonts = 0xdeadbeef;
3808         SetLastError(0xdeadbeef);
3809         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3810         ok(!ret, "AddFontMemResourceEx should fail\n");
3811         ok(GetLastError() == 0xdeadbeef,
3812            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3813            GetLastError());
3814         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3815     }
3816
3817     num_fonts = 0xdeadbeef;
3818     SetLastError(0xdeadbeef);
3819     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3820     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3821     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3822     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3823
3824     free_font(font);
3825
3826     SetLastError(0xdeadbeef);
3827     bRet = pRemoveFontMemResourceEx(ret);
3828     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3829
3830     /* test invalid pointer to number of loaded fonts */
3831     font = load_font("sserife.fon", &font_size);
3832     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3833
3834     SetLastError(0xdeadbeef);
3835     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3836     ok(!ret, "AddFontMemResourceEx should fail\n");
3837     ok(GetLastError() == 0xdeadbeef,
3838        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3839        GetLastError());
3840
3841     SetLastError(0xdeadbeef);
3842     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3843     ok(!ret, "AddFontMemResourceEx should fail\n");
3844     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3845        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3846        GetLastError());
3847
3848     free_font(font);
3849 }
3850
3851 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3852 {
3853     LOGFONT *lf;
3854
3855     if (type != TRUETYPE_FONTTYPE) return 1;
3856
3857     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3858
3859     lf = (LOGFONT *)lparam;
3860     *lf = *elf;
3861     return 0;
3862 }
3863
3864 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3865 {
3866     int ret;
3867     LOGFONT *lf;
3868
3869     if (type != TRUETYPE_FONTTYPE) return 1;
3870
3871     lf = (LOGFONT *)lparam;
3872     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3873     if(ret == 0)
3874     {
3875         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3876         *lf = *elf;
3877         return 0;
3878     }
3879     return 1;
3880 }
3881
3882 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3883 {
3884     return lparam;
3885 }
3886
3887 static void test_EnumFonts(void)
3888 {
3889     int ret;
3890     LOGFONT lf;
3891     HDC hdc;
3892
3893     if (!is_truetype_font_installed("Arial"))
3894     {
3895         skip("Arial is not installed\n");
3896         return;
3897     }
3898
3899     /* Windows uses localized font face names, so Arial Bold won't be found */
3900     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3901     {
3902         skip("User locale is not English, skipping the test\n");
3903         return;
3904     }
3905
3906     hdc = CreateCompatibleDC(0);
3907
3908     /* check that the enumproc's retval is returned */
3909     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
3910     ok(ret == 0xcafe, "got %08x\n", ret);
3911
3912     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3913     ok(!ret, "font Arial is not enumerated\n");
3914     ret = strcmp(lf.lfFaceName, "Arial");
3915     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3916     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3917
3918     lstrcpy(lf.lfFaceName, "Arial");
3919     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3920     ok(!ret, "font Arial is not enumerated\n");
3921     ret = strcmp(lf.lfFaceName, "Arial");
3922     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3923     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3924
3925     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3926     ok(!ret, "font Arial Bold is not enumerated\n");
3927     ret = strcmp(lf.lfFaceName, "Arial");
3928     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3929     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3930
3931     lstrcpy(lf.lfFaceName, "Arial Bold");
3932     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3933     ok(ret, "font Arial Bold should not be enumerated\n");
3934
3935     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3936     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3937     ret = strcmp(lf.lfFaceName, "Arial");
3938     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3939     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3940
3941     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3942     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3943     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3944
3945     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3946     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3947
3948     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3949     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3950     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3951
3952     DeleteDC(hdc);
3953 }
3954
3955 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3956 {
3957     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3958     const char *fullname = (const char *)lParam;
3959
3960     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
3961
3962     return 1;
3963 }
3964
3965 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
3966 {
3967     HDC hdc = GetDC(0);
3968     BOOL ret = FALSE;
3969
3970     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
3971         ret = TRUE;
3972
3973     ReleaseDC(0, hdc);
3974     return ret;
3975 }
3976
3977 static void test_fullname(void)
3978 {
3979     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
3980     char buf[LF_FULLFACESIZE];
3981     HFONT hfont, of;
3982     LOGFONTA lf;
3983     HDC hdc;
3984     int i;
3985
3986     hdc = CreateCompatibleDC(0);
3987     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3988
3989     memset(&lf, 0, sizeof(lf));
3990     lf.lfCharSet = ANSI_CHARSET;
3991     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3992     lf.lfHeight = 16;
3993     lf.lfWidth = 16;
3994     lf.lfQuality = DEFAULT_QUALITY;
3995     lf.lfItalic = FALSE;
3996     lf.lfWeight = FW_DONTCARE;
3997
3998     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3999     {
4000         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
4001         {
4002             skip("%s is not installed\n", TestName[i]);
4003             continue;
4004         }
4005
4006         lstrcpyA(lf.lfFaceName, TestName[i]);
4007         hfont = CreateFontIndirectA(&lf);
4008         ok(hfont != 0, "CreateFontIndirectA failed\n");
4009
4010         of = SelectObject(hdc, hfont);
4011         buf[0] = 0;
4012         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
4013            "face full name could not be read\n");
4014         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
4015         SelectObject(hdc, of);
4016         DeleteObject(hfont);
4017     }
4018     DeleteDC(hdc);
4019 }
4020
4021 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
4022 {
4023     char tmp_path[MAX_PATH];
4024     HRSRC rsrc;
4025     void *rsrc_data;
4026     DWORD rsrc_size;
4027     HANDLE hfile;
4028     BOOL ret;
4029
4030     SetLastError(0xdeadbeef);
4031     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4032     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4033     if (!rsrc) return FALSE;
4034     SetLastError(0xdeadbeef);
4035     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4036     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4037     if (!rsrc_data) return FALSE;
4038     SetLastError(0xdeadbeef);
4039     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4040     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4041     if (!rsrc_size) return FALSE;
4042
4043     SetLastError(0xdeadbeef);
4044     ret = GetTempPath(MAX_PATH, tmp_path);
4045     ok(ret, "GetTempPath() error %d\n", GetLastError());
4046     SetLastError(0xdeadbeef);
4047     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4048     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4049
4050     SetLastError(0xdeadbeef);
4051     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4052     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4053     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4054
4055     SetLastError(0xdeadbeef);
4056     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4057     ok(ret, "WriteFile() error %d\n", GetLastError());
4058
4059     CloseHandle(hfile);
4060     return ret;
4061 }
4062
4063 static void test_CreateScalableFontResource(void)
4064 {
4065     char ttf_name[MAX_PATH];
4066     char tmp_path[MAX_PATH];
4067     char fot_name[MAX_PATH];
4068     char *file_part;
4069     DWORD ret;
4070
4071     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4072     {
4073         win_skip("AddFontResourceExA is not available on this platform\n");
4074         return;
4075     }
4076
4077     if (!write_ttf_file("wine_test.ttf", ttf_name))
4078     {
4079         skip("Failed to create ttf file for testing\n");
4080         return;
4081     }
4082
4083     trace("created %s\n", ttf_name);
4084
4085     ret = is_truetype_font_installed("wine_test");
4086     ok(!ret, "font wine_test should not be enumerated\n");
4087
4088     ret = GetTempPath(MAX_PATH, tmp_path);
4089     ok(ret, "GetTempPath() error %d\n", GetLastError());
4090     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4091     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4092
4093     ret = GetFileAttributes(fot_name);
4094     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4095
4096     SetLastError(0xdeadbeef);
4097     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4098     ok(!ret, "CreateScalableFontResource() should fail\n");
4099     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4100
4101     SetLastError(0xdeadbeef);
4102     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4103     ok(!ret, "CreateScalableFontResource() should fail\n");
4104     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4105
4106     file_part = strrchr(ttf_name, '\\');
4107     SetLastError(0xdeadbeef);
4108     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4109     ok(!ret, "CreateScalableFontResource() should fail\n");
4110     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4111
4112     SetLastError(0xdeadbeef);
4113     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4114     ok(!ret, "CreateScalableFontResource() should fail\n");
4115     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4116
4117     SetLastError(0xdeadbeef);
4118     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4119     ok(!ret, "CreateScalableFontResource() should fail\n");
4120     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4121
4122     ret = DeleteFile(fot_name);
4123     ok(ret, "DeleteFile() error %d\n", GetLastError());
4124
4125     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4126 todo_wine
4127     ok(!ret, "RemoveFontResourceEx() should fail\n");
4128
4129     /* test public font resource */
4130     SetLastError(0xdeadbeef);
4131     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4132     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4133
4134     ret = is_truetype_font_installed("wine_test");
4135     ok(!ret, "font wine_test should not be enumerated\n");
4136
4137     SetLastError(0xdeadbeef);
4138     ret = pAddFontResourceExA(fot_name, 0, 0);
4139     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4140
4141     ret = is_truetype_font_installed("wine_test");
4142     ok(ret, "font wine_test should be enumerated\n");
4143
4144     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4145 todo_wine
4146     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4147
4148     SetLastError(0xdeadbeef);
4149     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4150     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4151
4152     ret = is_truetype_font_installed("wine_test");
4153 todo_wine
4154     ok(!ret, "font wine_test should not be enumerated\n");
4155
4156     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
4157     if (ret)
4158     {
4159         /* remove once RemoveFontResource is implemented */
4160         DeleteFile(fot_name);
4161         DeleteFile(ttf_name);
4162         return;
4163     }
4164
4165     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4166     ok(!ret, "RemoveFontResourceEx() should fail\n");
4167
4168     DeleteFile(fot_name);
4169
4170     /* test hidden font resource */
4171     SetLastError(0xdeadbeef);
4172     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4173     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4174
4175     ret = is_truetype_font_installed("wine_test");
4176     ok(!ret, "font wine_test should not be enumerated\n");
4177
4178     SetLastError(0xdeadbeef);
4179     ret = pAddFontResourceExA(fot_name, 0, 0);
4180     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4181
4182     ret = is_truetype_font_installed("wine_test");
4183     ok(!ret, "font wine_test should not be enumerated\n");
4184
4185     /* XP allows removing a private font added with 0 flags */
4186     SetLastError(0xdeadbeef);
4187     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4188     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4189
4190     ret = is_truetype_font_installed("wine_test");
4191     ok(!ret, "font wine_test should not be enumerated\n");
4192
4193     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4194     ok(!ret, "RemoveFontResourceEx() should fail\n");
4195
4196     DeleteFile(fot_name);
4197     DeleteFile(ttf_name);
4198 }
4199
4200 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4201 {
4202     LOGFONTA lf;
4203     HFONT hfont, hfont_prev;
4204     HDC hdc;
4205     char facename[100];
4206     DWORD ret;
4207     static const WCHAR str[] = { 0x2025 };
4208
4209     *installed = is_truetype_font_installed(name);
4210
4211     lf.lfHeight = -18;
4212     lf.lfWidth = 0;
4213     lf.lfEscapement = 0;
4214     lf.lfOrientation = 0;
4215     lf.lfWeight = FW_DONTCARE;
4216     lf.lfItalic = 0;
4217     lf.lfUnderline = 0;
4218     lf.lfStrikeOut = 0;
4219     lf.lfCharSet = DEFAULT_CHARSET;
4220     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4221     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4222     lf.lfQuality = DEFAULT_QUALITY;
4223     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4224     strcpy(lf.lfFaceName, name);
4225
4226     hfont = CreateFontIndirectA(&lf);
4227     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4228
4229     hdc = GetDC(NULL);
4230
4231     hfont_prev = SelectObject(hdc, hfont);
4232     ok(hfont_prev != NULL, "SelectObject failed\n");
4233
4234     ret = GetTextFaceA(hdc, sizeof facename, facename);
4235     ok(ret, "GetTextFaceA failed\n");
4236     *selected = !strcmp(facename, name);
4237
4238     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4239     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4240     if (!*selected)
4241         memset(gm, 0, sizeof *gm);
4242
4243     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4244     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4245
4246     SelectObject(hdc, hfont_prev);
4247     DeleteObject(hfont);
4248     ReleaseDC(NULL, hdc);
4249 }
4250
4251 static void test_vertical_font(void)
4252 {
4253     char ttf_name[MAX_PATH];
4254     int num;
4255     BOOL ret, installed, selected;
4256     GLYPHMETRICS gm;
4257     WORD hgi, vgi;
4258
4259     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4260     {
4261         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4262         return;
4263     }
4264
4265     if (!write_ttf_file("vertical.ttf", ttf_name))
4266     {
4267         skip("Failed to create ttf file for testing\n");
4268         return;
4269     }
4270
4271     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4272     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4273
4274     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
4275     ok(installed, "@WineTestVertical is not installed\n");
4276     ok(selected, "@WineTestVertical is not selected\n");
4277     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
4278        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
4279        gm.gmBlackBoxX, gm.gmBlackBoxY);
4280
4281     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4282     ok(installed, "@@WineTestVertical is not installed\n");
4283     ok(selected, "@@WineTestVertical is not selected\n");
4284     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4285        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4286        gm.gmBlackBoxX, gm.gmBlackBoxY);
4287
4288     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4289
4290     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4291     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4292
4293     DeleteFile(ttf_name);
4294 }
4295
4296 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4297                                            DWORD type, LPARAM lParam)
4298 {
4299     if (lf->lfFaceName[0] == '@') {
4300         return 0;
4301     }
4302     return 1;
4303 }
4304
4305 static void test_east_asian_font_selection(void)
4306 {
4307     HDC hdc;
4308     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4309                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4310     size_t i;
4311
4312     hdc = GetDC(NULL);
4313
4314     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4315     {
4316         LOGFONTA lf;
4317         HFONT hfont;
4318         char face_name[LF_FACESIZE];
4319         int ret;
4320
4321         memset(&lf, 0, sizeof lf);
4322         lf.lfFaceName[0] = '\0';
4323         lf.lfCharSet = charset[i];
4324
4325         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4326         {
4327             skip("Vertical font for charset %u is not installed\n", charset[i]);
4328             continue;
4329         }
4330
4331         hfont = CreateFontIndirectA(&lf);
4332         hfont = SelectObject(hdc, hfont);
4333         memset(face_name, 0, sizeof face_name);
4334         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4335         ok(ret && face_name[0] != '@',
4336            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4337         DeleteObject(SelectObject(hdc, hfont));
4338
4339         memset(&lf, 0, sizeof lf);
4340         strcpy(lf.lfFaceName, "@");
4341         lf.lfCharSet = charset[i];
4342         hfont = CreateFontIndirectA(&lf);
4343         hfont = SelectObject(hdc, hfont);
4344         memset(face_name, 0, sizeof face_name);
4345         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4346         ok(ret && face_name[0] == '@',
4347            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4348         DeleteObject(SelectObject(hdc, hfont));
4349     }
4350     ReleaseDC(NULL, hdc);
4351 }
4352
4353 static int get_font_dpi(const LOGFONT *lf)
4354 {
4355     HDC hdc = CreateCompatibleDC(0);
4356     HFONT hfont;
4357     TEXTMETRIC tm;
4358     int ret;
4359
4360     hfont = CreateFontIndirect(lf);
4361     ok(hfont != 0, "CreateFontIndirect failed\n");
4362
4363     SelectObject(hdc, hfont);
4364     ret = GetTextMetrics(hdc, &tm);
4365     ok(ret, "GetTextMetrics failed\n");
4366     ret = tm.tmDigitizedAspectX;
4367
4368     DeleteDC(hdc);
4369     DeleteObject(hfont);
4370
4371     return ret;
4372 }
4373
4374 static void test_stock_fonts(void)
4375 {
4376     static const int font[] =
4377     {
4378         ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, DEVICE_DEFAULT_FONT, DEFAULT_GUI_FONT
4379         /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
4380     };
4381     static const struct test_data
4382     {
4383         int charset, weight, height, dpi;
4384         const char face_name[LF_FACESIZE];
4385     } td[][11] =
4386     {
4387         { /* ANSI_FIXED_FONT */
4388             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "Courier" },
4389             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "Courier" },
4390             { 0 }
4391         },
4392         { /* ANSI_VAR_FONT */
4393             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "MS Sans Serif" },
4394             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "MS Sans Serif" },
4395             { 0 }
4396         },
4397         { /* SYSTEM_FONT */
4398             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4399             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4400             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4401             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4402             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4403             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4404             { 0 }
4405         },
4406         { /* DEVICE_DEFAULT_FONT */
4407             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4408             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4409             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4410             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4411             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4412             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4413             { 0 }
4414         },
4415         { /* DEFAULT_GUI_FONT */
4416             { SHIFTJIS_CHARSET, FW_NORMAL, -12, 96, "?MS UI Gothic" },
4417             { SHIFTJIS_CHARSET, FW_NORMAL, -15, 120, "?MS UI Gothic" },
4418             { HANGEUL_CHARSET, FW_NORMAL, -12, 96, "?Gulim" },
4419             { HANGEUL_CHARSET, FW_NORMAL, -15, 120, "?Gulim" },
4420             { GB2312_CHARSET, FW_NORMAL, -12, 96, "?SimHei" },
4421             { GB2312_CHARSET, FW_NORMAL, -15, 120, "?SimHei" },
4422             { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 96, "?MingLiU" },
4423             { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 120, "?MingLiU" },
4424             { DEFAULT_CHARSET, FW_NORMAL, -11, 96, "MS Shell Dlg" },
4425             { DEFAULT_CHARSET, FW_NORMAL, -13, 120, "MS Shell Dlg" },
4426             { 0 }
4427         }
4428     };
4429     int i, j;
4430
4431     for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
4432     {
4433         HFONT hfont;
4434         LOGFONT lf;
4435         int ret;
4436
4437         hfont = GetStockObject(font[i]);
4438         ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
4439
4440         ret = GetObject(hfont, sizeof(lf), &lf);
4441         if (ret != sizeof(lf))
4442         {
4443             /* NT4 */
4444             win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
4445             continue;
4446         }
4447
4448         for (j = 0; td[i][j].face_name[0] != 0; j++)
4449         {
4450             if (lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET)
4451             {
4452                 continue;
4453             }
4454
4455             ret = get_font_dpi(&lf);
4456             if (ret != td[i][j].dpi)
4457             {
4458                 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
4459                       i, j, lf.lfFaceName, ret, td[i][j].dpi);
4460                 continue;
4461             }
4462
4463             ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
4464             ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
4465             if (td[i][j].face_name[0] == '?')
4466             {
4467                 /* Wine doesn't have this font, skip this case for now.
4468                    Actually, the face name is localized on Windows and varies
4469                    dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
4470                 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
4471             }
4472             else
4473             {
4474                 ok(!lstrcmp(td[i][j].face_name, lf.lfFaceName), "%d(%d): expected lfFaceName %s, got %s\n", i, j, td[i][j].face_name, lf.lfFaceName);
4475             }
4476             break;
4477         }
4478     }
4479 }
4480
4481 START_TEST(font)
4482 {
4483     init();
4484
4485     test_stock_fonts();
4486     test_logfont();
4487     test_bitmap_font();
4488     test_outline_font();
4489     test_bitmap_font_metrics();
4490     test_GdiGetCharDimensions();
4491     test_GetCharABCWidths();
4492     test_text_extents();
4493     test_GetGlyphIndices();
4494     test_GetKerningPairs();
4495     test_GetOutlineTextMetrics();
4496     test_SetTextJustification();
4497     test_font_charset();
4498     test_GetFontUnicodeRanges();
4499     test_nonexistent_font();
4500     test_orientation();
4501     test_height_selection();
4502     test_AddFontMemResource();
4503     test_EnumFonts();
4504
4505     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4506      * I'd like to avoid them in this test.
4507      */
4508     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4509     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4510     if (is_truetype_font_installed("Arial Black") &&
4511         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4512     {
4513         test_EnumFontFamilies("", ANSI_CHARSET);
4514         test_EnumFontFamilies("", SYMBOL_CHARSET);
4515         test_EnumFontFamilies("", DEFAULT_CHARSET);
4516     }
4517     else
4518         skip("Arial Black or Symbol/Wingdings is not installed\n");
4519     test_EnumFontFamiliesEx_default_charset();
4520     test_GetTextMetrics();
4521     test_GdiRealizationInfo();
4522     test_GetTextFace();
4523     test_GetGlyphOutline();
4524     test_GetTextMetrics2("Tahoma", -11);
4525     test_GetTextMetrics2("Tahoma", -55);
4526     test_GetTextMetrics2("Tahoma", -110);
4527     test_GetTextMetrics2("Arial", -11);
4528     test_GetTextMetrics2("Arial", -55);
4529     test_GetTextMetrics2("Arial", -110);
4530     test_CreateFontIndirect();
4531     test_CreateFontIndirectEx();
4532     test_oemcharset();
4533     test_fullname();
4534     test_east_asian_font_selection();
4535
4536     /* These tests should be last test until RemoveFontResource
4537      * is properly implemented.
4538      */
4539     test_vertical_font();
4540     test_CreateScalableFontResource();
4541 }