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