include: Assorted spelling fixes.
[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                 areaWidth = clientArea->right - clientArea->left,
1757                 nErrors = 0, e;
1758     PSTR        pFirstChar, pLastChar;
1759     SIZE        size;
1760     TEXTMETRICA tm;
1761     struct err
1762     {
1763         char *start;
1764         int  len;
1765         int  GetTextExtentExPointWWidth;
1766     } error[20];
1767
1768     GetTextMetricsA(hdc, &tm);
1769     y = clientArea->top;
1770     do {
1771         breakCount = 0;
1772         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1773         pFirstChar = str;
1774
1775         do {
1776             pLastChar = str;
1777
1778             /* if not at the end of the string, ... */
1779             if (*str == '\0') break;
1780             /* ... add the next word to the current extent */
1781             while (*str != '\0' && *str++ != tm.tmBreakChar);
1782             breakCount++;
1783             SetTextJustification(hdc, 0, 0);
1784             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1785         } while ((int) size.cx < areaWidth);
1786
1787         /* ignore trailing break chars */
1788         breakCount--;
1789         while (*(pLastChar - 1) == tm.tmBreakChar)
1790         {
1791             pLastChar--;
1792             breakCount--;
1793         }
1794
1795         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1796
1797         SetTextJustification(hdc, 0, 0);
1798         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1799
1800         /* do not justify the last extent */
1801         if (*str != '\0' && breakCount > 0)
1802         {
1803             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1804             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1805             if (size.cx != areaWidth && nErrors < sizeof(error)/sizeof(error[0]) - 1)
1806             {
1807                 error[nErrors].start = pFirstChar;
1808                 error[nErrors].len = pLastChar - pFirstChar;
1809                 error[nErrors].GetTextExtentExPointWWidth = size.cx;
1810                 nErrors++;
1811             }
1812         }
1813
1814         trace( "%u %.*s\n", size.cx, (int)(pLastChar - pFirstChar), pFirstChar);
1815
1816         y += size.cy;
1817         str = pLastChar;
1818     } while (*str && y < clientArea->bottom);
1819
1820     for (e = 0; e < nErrors; e++)
1821     {
1822         /* The width returned by GetTextExtentPoint32() is exactly the same
1823            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1824         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1825             "GetTextExtentPointW() for \"%.*s\" should have returned a width of %d, not %d.\n",
1826            error[e].len, error[e].start, areaWidth, error[e].GetTextExtentExPointWWidth);
1827     }
1828 }
1829
1830 static void test_SetTextJustification(void)
1831 {
1832     HDC hdc;
1833     RECT clientArea;
1834     LOGFONTA lf;
1835     HFONT hfont;
1836     HWND hwnd;
1837     static char testText[] =
1838             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1839             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1840             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1841             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1842             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1843             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1844             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1845
1846     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1847     GetClientRect( hwnd, &clientArea );
1848     hdc = GetDC( hwnd );
1849
1850     memset(&lf, 0, sizeof lf);
1851     lf.lfCharSet = ANSI_CHARSET;
1852     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1853     lf.lfWeight = FW_DONTCARE;
1854     lf.lfHeight = 20;
1855     lf.lfQuality = DEFAULT_QUALITY;
1856     lstrcpyA(lf.lfFaceName, "Times New Roman");
1857     hfont = create_font("Times New Roman", &lf);
1858     SelectObject(hdc, hfont);
1859
1860     testJustification(hdc, testText, &clientArea);
1861
1862     SetMapMode( hdc, MM_ANISOTROPIC );
1863     SetWindowExtEx( hdc, 2, 2, NULL );
1864     GetClientRect( hwnd, &clientArea );
1865     DPtoLP( hdc, (POINT *)&clientArea, 2 );
1866     testJustification(hdc, testText, &clientArea);
1867
1868     SetViewportExtEx( hdc, 3, 3, NULL );
1869     GetClientRect( hwnd, &clientArea );
1870     DPtoLP( hdc, (POINT *)&clientArea, 2 );
1871     testJustification(hdc, testText, &clientArea);
1872
1873     DeleteObject(hfont);
1874     ReleaseDC(hwnd, hdc);
1875     DestroyWindow(hwnd);
1876 }
1877
1878 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1879 {
1880     HDC hdc;
1881     LOGFONTA lf;
1882     HFONT hfont, hfont_old;
1883     CHARSETINFO csi;
1884     FONTSIGNATURE fs;
1885     INT cs;
1886     DWORD i, ret;
1887     char name[64];
1888
1889     assert(count <= 128);
1890
1891     memset(&lf, 0, sizeof(lf));
1892
1893     lf.lfCharSet = charset;
1894     lf.lfHeight = 10;
1895     lstrcpyA(lf.lfFaceName, "Arial");
1896     SetLastError(0xdeadbeef);
1897     hfont = CreateFontIndirectA(&lf);
1898     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1899
1900     hdc = GetDC(0);
1901     hfont_old = SelectObject(hdc, hfont);
1902
1903     cs = GetTextCharsetInfo(hdc, &fs, 0);
1904     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1905
1906     SetLastError(0xdeadbeef);
1907     ret = GetTextFaceA(hdc, sizeof(name), name);
1908     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1909
1910     if (charset == SYMBOL_CHARSET)
1911     {
1912         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1913         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1914     }
1915     else
1916     {
1917         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1918         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1919     }
1920
1921     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1922     {
1923         trace("Can't find codepage for charset %d\n", cs);
1924         ReleaseDC(0, hdc);
1925         return FALSE;
1926     }
1927     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1928
1929     if (pGdiGetCodePage != NULL && pGdiGetCodePage(hdc) != code_page)
1930     {
1931         skip("Font code page %d, looking for code page %d\n",
1932              pGdiGetCodePage(hdc), code_page);
1933         ReleaseDC(0, hdc);
1934         return FALSE;
1935     }
1936
1937     if (unicode)
1938     {
1939         char ansi_buf[128];
1940         WCHAR unicode_buf[128];
1941
1942         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1943
1944         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1945
1946         SetLastError(0xdeadbeef);
1947         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1948         ok(ret == count, "GetGlyphIndicesW expected %d got %d, error %u\n",
1949            count, ret, GetLastError());
1950     }
1951     else
1952     {
1953         char ansi_buf[128];
1954
1955         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1956
1957         SetLastError(0xdeadbeef);
1958         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1959         ok(ret == count, "GetGlyphIndicesA expected %d got %d, error %u\n",
1960            count, ret, GetLastError());
1961     }
1962
1963     SelectObject(hdc, hfont_old);
1964     DeleteObject(hfont);
1965
1966     ReleaseDC(0, hdc);
1967
1968     return TRUE;
1969 }
1970
1971 static void test_font_charset(void)
1972 {
1973     static struct charset_data
1974     {
1975         INT charset;
1976         UINT code_page;
1977         WORD font_idxA[128], font_idxW[128];
1978     } cd[] =
1979     {
1980         { ANSI_CHARSET, 1252 },
1981         { RUSSIAN_CHARSET, 1251 },
1982         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1983     };
1984     int i;
1985
1986     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1987     {
1988         win_skip("Skipping the font charset test on a Win9x platform\n");
1989         return;
1990     }
1991
1992     if (!is_font_installed("Arial"))
1993     {
1994         skip("Arial is not installed\n");
1995         return;
1996     }
1997
1998     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1999     {
2000         if (cd[i].charset == SYMBOL_CHARSET)
2001         {
2002             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
2003             {
2004                 skip("Symbol or Wingdings is not installed\n");
2005                 break;
2006             }
2007         }
2008         if (get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE) &&
2009             get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE))
2010             ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
2011     }
2012
2013     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
2014     if (i > 2)
2015     {
2016         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
2017         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
2018     }
2019     else
2020         skip("Symbol or Wingdings is not installed\n");
2021 }
2022
2023 static void test_GetFontUnicodeRanges(void)
2024 {
2025     LOGFONTA lf;
2026     HDC hdc;
2027     HFONT hfont, hfont_old;
2028     DWORD size;
2029     GLYPHSET *gs;
2030     DWORD i;
2031
2032     if (!pGetFontUnicodeRanges)
2033     {
2034         win_skip("GetFontUnicodeRanges not available before W2K\n");
2035         return;
2036     }
2037
2038     memset(&lf, 0, sizeof(lf));
2039     lstrcpyA(lf.lfFaceName, "Arial");
2040     hfont = create_font("Arial", &lf);
2041
2042     hdc = GetDC(0);
2043     hfont_old = SelectObject(hdc, hfont);
2044
2045     size = pGetFontUnicodeRanges(NULL, NULL);
2046     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
2047
2048     size = pGetFontUnicodeRanges(hdc, NULL);
2049     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
2050
2051     gs = HeapAlloc(GetProcessHeap(), 0, size);
2052
2053     size = pGetFontUnicodeRanges(hdc, gs);
2054     ok(size, "GetFontUnicodeRanges failed\n");
2055
2056     if (0) /* Disabled to limit console spam */
2057         for (i = 0; i < gs->cRanges; i++)
2058             trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
2059     trace("found %u ranges\n", gs->cRanges);
2060
2061     HeapFree(GetProcessHeap(), 0, gs);
2062
2063     SelectObject(hdc, hfont_old);
2064     DeleteObject(hfont);
2065     ReleaseDC(NULL, hdc);
2066 }
2067
2068 #define MAX_ENUM_FONTS 4096
2069
2070 struct enum_font_data
2071 {
2072     int total;
2073     LOGFONT lf[MAX_ENUM_FONTS];
2074 };
2075
2076 struct enum_fullname_data
2077 {
2078     int total;
2079     ENUMLOGFONT elf[MAX_ENUM_FONTS];
2080 };
2081
2082 struct enum_font_dataW
2083 {
2084     int total;
2085     LOGFONTW lf[MAX_ENUM_FONTS];
2086 };
2087
2088 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
2089 {
2090     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2091     const NEWTEXTMETRIC *ntm = (const NEWTEXTMETRIC *)tm;
2092
2093     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2094     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2095
2096     if (type != TRUETYPE_FONTTYPE) return 1;
2097
2098     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2099
2100     if (0) /* Disabled to limit console spam */
2101         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2102               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2103     if (efd->total < MAX_ENUM_FONTS)
2104         efd->lf[efd->total++] = *lf;
2105     else
2106         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2107
2108     return 1;
2109 }
2110
2111 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
2112 {
2113     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2114     const NEWTEXTMETRICW *ntm = (const NEWTEXTMETRICW *)tm;
2115
2116     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2117     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2118
2119     if (type != TRUETYPE_FONTTYPE) return 1;
2120
2121     ok(ntm->ntmCellHeight + ntm->ntmCellHeight/5 >= ntm->ntmSizeEM, "ntmCellHeight %d should be close to ntmSizeEM %d\n", ntm->ntmCellHeight, ntm->ntmSizeEM);
2122
2123     if (0) /* Disabled to limit console spam */
2124         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2125               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2126     if (efd->total < MAX_ENUM_FONTS)
2127         efd->lf[efd->total++] = *lf;
2128     else
2129         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2130
2131     return 1;
2132 }
2133
2134 static void get_charset_stats(struct enum_font_data *efd,
2135                               int *ansi_charset, int *symbol_charset,
2136                               int *russian_charset)
2137 {
2138     int i;
2139
2140     *ansi_charset = 0;
2141     *symbol_charset = 0;
2142     *russian_charset = 0;
2143
2144     for (i = 0; i < efd->total; i++)
2145     {
2146         switch (efd->lf[i].lfCharSet)
2147         {
2148         case ANSI_CHARSET:
2149             (*ansi_charset)++;
2150             break;
2151         case SYMBOL_CHARSET:
2152             (*symbol_charset)++;
2153             break;
2154         case RUSSIAN_CHARSET:
2155             (*russian_charset)++;
2156             break;
2157         }
2158     }
2159 }
2160
2161 static void get_charset_statsW(struct enum_font_dataW *efd,
2162                               int *ansi_charset, int *symbol_charset,
2163                               int *russian_charset)
2164 {
2165     int i;
2166
2167     *ansi_charset = 0;
2168     *symbol_charset = 0;
2169     *russian_charset = 0;
2170
2171     for (i = 0; i < efd->total; i++)
2172     {
2173         switch (efd->lf[i].lfCharSet)
2174         {
2175         case ANSI_CHARSET:
2176             (*ansi_charset)++;
2177             break;
2178         case SYMBOL_CHARSET:
2179             (*symbol_charset)++;
2180             break;
2181         case RUSSIAN_CHARSET:
2182             (*russian_charset)++;
2183             break;
2184         }
2185     }
2186 }
2187
2188 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2189 {
2190     struct enum_font_data efd;
2191     struct enum_font_dataW efdw;
2192     LOGFONT lf;
2193     HDC hdc;
2194     int i, ret, ansi_charset, symbol_charset, russian_charset;
2195
2196     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2197
2198     if (*font_name && !is_truetype_font_installed(font_name))
2199     {
2200         skip("%s is not installed\n", font_name);
2201         return;
2202     }
2203
2204     hdc = GetDC(0);
2205
2206     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2207      * while EnumFontFamiliesEx doesn't.
2208      */
2209     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2210     {
2211         /*
2212          * Use EnumFontFamiliesW since win98 crashes when the
2213          *    second parameter is NULL using EnumFontFamilies
2214          */
2215         efdw.total = 0;
2216         SetLastError(0xdeadbeef);
2217         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2218         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2219         if(ret)
2220         {
2221             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2222             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2223                   ansi_charset, symbol_charset, russian_charset);
2224             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2225             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2226             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2227             ok(russian_charset > 0 ||
2228                broken(russian_charset == 0), /* NT4 */
2229                "NULL family should enumerate RUSSIAN_CHARSET\n");
2230         }
2231
2232         efdw.total = 0;
2233         SetLastError(0xdeadbeef);
2234         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2235         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2236         if(ret)
2237         {
2238             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2239             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2240                   ansi_charset, symbol_charset, russian_charset);
2241             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2242             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2243             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2244             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2245         }
2246     }
2247
2248     efd.total = 0;
2249     SetLastError(0xdeadbeef);
2250     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2251     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2252     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2253     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2254           ansi_charset, symbol_charset, russian_charset,
2255           *font_name ? font_name : "<empty>");
2256     if (*font_name)
2257         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2258     else
2259         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2260     for (i = 0; i < efd.total; i++)
2261     {
2262 /* FIXME: remove completely once Wine is fixed */
2263 if (efd.lf[i].lfCharSet != font_charset)
2264 {
2265 todo_wine
2266     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2267 }
2268 else
2269         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2270         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2271            font_name, efd.lf[i].lfFaceName);
2272     }
2273
2274     memset(&lf, 0, sizeof(lf));
2275     lf.lfCharSet = ANSI_CHARSET;
2276     lstrcpy(lf.lfFaceName, font_name);
2277     efd.total = 0;
2278     SetLastError(0xdeadbeef);
2279     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2280     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2281     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2282     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2283           ansi_charset, symbol_charset, russian_charset,
2284           *font_name ? font_name : "<empty>");
2285     if (font_charset == SYMBOL_CHARSET)
2286     {
2287         if (*font_name)
2288             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2289         else
2290             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2291     }
2292     else
2293     {
2294         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2295         for (i = 0; i < efd.total; i++)
2296         {
2297             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2298             if (*font_name)
2299                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2300                    font_name, efd.lf[i].lfFaceName);
2301         }
2302     }
2303
2304     /* DEFAULT_CHARSET should enumerate all available charsets */
2305     memset(&lf, 0, sizeof(lf));
2306     lf.lfCharSet = DEFAULT_CHARSET;
2307     lstrcpy(lf.lfFaceName, font_name);
2308     efd.total = 0;
2309     SetLastError(0xdeadbeef);
2310     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2311     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2312     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2313     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2314           ansi_charset, symbol_charset, russian_charset,
2315           *font_name ? font_name : "<empty>");
2316     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2317     for (i = 0; i < efd.total; i++)
2318     {
2319         if (*font_name)
2320             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2321                font_name, efd.lf[i].lfFaceName);
2322     }
2323     if (*font_name)
2324     {
2325         switch (font_charset)
2326         {
2327         case ANSI_CHARSET:
2328             ok(ansi_charset > 0,
2329                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2330             ok(!symbol_charset,
2331                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2332             ok(russian_charset > 0,
2333                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2334             break;
2335         case SYMBOL_CHARSET:
2336             ok(!ansi_charset,
2337                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2338             ok(symbol_charset,
2339                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2340             ok(!russian_charset,
2341                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2342             break;
2343         case DEFAULT_CHARSET:
2344             ok(ansi_charset > 0,
2345                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2346             ok(symbol_charset > 0,
2347                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2348             ok(russian_charset > 0,
2349                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2350             break;
2351         }
2352     }
2353     else
2354     {
2355         ok(ansi_charset > 0,
2356            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2357         ok(symbol_charset > 0,
2358            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2359         ok(russian_charset > 0,
2360            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2361     }
2362
2363     memset(&lf, 0, sizeof(lf));
2364     lf.lfCharSet = SYMBOL_CHARSET;
2365     lstrcpy(lf.lfFaceName, font_name);
2366     efd.total = 0;
2367     SetLastError(0xdeadbeef);
2368     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2369     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2370     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2371     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2372           ansi_charset, symbol_charset, russian_charset,
2373           *font_name ? font_name : "<empty>");
2374     if (*font_name && font_charset == ANSI_CHARSET)
2375         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2376     else
2377     {
2378         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2379         for (i = 0; i < efd.total; i++)
2380         {
2381             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2382             if (*font_name)
2383                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2384                    font_name, efd.lf[i].lfFaceName);
2385         }
2386
2387         ok(!ansi_charset,
2388            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2389         ok(symbol_charset > 0,
2390            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2391         ok(!russian_charset,
2392            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2393     }
2394
2395     ReleaseDC(0, hdc);
2396 }
2397
2398 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2399 {
2400     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2401
2402     if (type != TRUETYPE_FONTTYPE) return 1;
2403
2404     if (efd->total < MAX_ENUM_FONTS)
2405         efd->lf[efd->total++] = *lf;
2406     else
2407         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2408
2409     return 1;
2410 }
2411
2412 static INT CALLBACK enum_fullname_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2413 {
2414     struct enum_fullname_data *efnd = (struct enum_fullname_data *)lParam;
2415
2416     if (type != TRUETYPE_FONTTYPE) return 1;
2417
2418     if (efnd->total < MAX_ENUM_FONTS)
2419         efnd->elf[efnd->total++] = *(ENUMLOGFONT*)lf;
2420     else
2421         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2422
2423     return 1;
2424 }
2425
2426 static void test_EnumFontFamiliesEx_default_charset(void)
2427 {
2428     struct enum_font_data efd;
2429     LOGFONT gui_font, enum_font;
2430     DWORD ret;
2431     HDC hdc;
2432
2433     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2434     ok(ret, "GetObject failed.\n");
2435     if (!ret)
2436         return;
2437
2438     efd.total = 0;
2439
2440     hdc = GetDC(0);
2441     memset(&enum_font, 0, sizeof(enum_font));
2442     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2443     enum_font.lfCharSet = DEFAULT_CHARSET;
2444     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2445     ReleaseDC(0, hdc);
2446
2447     if (efd.total == 0) {
2448         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2449         return;
2450     }
2451     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2452
2453     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet || broken(system_lang_id == LANG_ARABIC),
2454        "(%s) got charset %d expected %d\n",
2455        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2456
2457     return;
2458 }
2459
2460 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2461 {
2462     HFONT hfont, hfont_prev;
2463     DWORD ret;
2464     GLYPHMETRICS gm1, gm2;
2465     LOGFONTA lf2 = *lf;
2466     WORD idx;
2467
2468     if(!pGetGlyphIndicesA)
2469         return;
2470
2471     /* negative widths are handled just as positive ones */
2472     lf2.lfWidth = -lf->lfWidth;
2473
2474     SetLastError(0xdeadbeef);
2475     hfont = CreateFontIndirectA(lf);
2476     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2477     check_font("original", lf, hfont);
2478
2479     hfont_prev = SelectObject(hdc, hfont);
2480
2481     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2482     if (ret == GDI_ERROR || idx == 0xffff)
2483     {
2484         SelectObject(hdc, hfont_prev);
2485         DeleteObject(hfont);
2486         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2487         return;
2488     }
2489
2490     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2491     memset(&gm1, 0xab, sizeof(gm1));
2492     SetLastError(0xdeadbeef);
2493     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2494     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2495
2496     SelectObject(hdc, hfont_prev);
2497     DeleteObject(hfont);
2498
2499     SetLastError(0xdeadbeef);
2500     hfont = CreateFontIndirectA(&lf2);
2501     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2502     check_font("negative width", &lf2, hfont);
2503
2504     hfont_prev = SelectObject(hdc, hfont);
2505
2506     memset(&gm2, 0xbb, sizeof(gm2));
2507     SetLastError(0xdeadbeef);
2508     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2509     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2510
2511     SelectObject(hdc, hfont_prev);
2512     DeleteObject(hfont);
2513
2514     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2515        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2516        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2517        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2518        gm1.gmCellIncX == gm2.gmCellIncX &&
2519        gm1.gmCellIncY == gm2.gmCellIncY,
2520        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2521        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2522        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2523        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2524        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2525 }
2526
2527 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2528 #include "pshpack2.h"
2529 typedef struct
2530 {
2531     USHORT version;
2532     SHORT xAvgCharWidth;
2533     USHORT usWeightClass;
2534     USHORT usWidthClass;
2535     SHORT fsType;
2536     SHORT ySubscriptXSize;
2537     SHORT ySubscriptYSize;
2538     SHORT ySubscriptXOffset;
2539     SHORT ySubscriptYOffset;
2540     SHORT ySuperscriptXSize;
2541     SHORT ySuperscriptYSize;
2542     SHORT ySuperscriptXOffset;
2543     SHORT ySuperscriptYOffset;
2544     SHORT yStrikeoutSize;
2545     SHORT yStrikeoutPosition;
2546     SHORT sFamilyClass;
2547     PANOSE panose;
2548     ULONG ulUnicodeRange1;
2549     ULONG ulUnicodeRange2;
2550     ULONG ulUnicodeRange3;
2551     ULONG ulUnicodeRange4;
2552     CHAR achVendID[4];
2553     USHORT fsSelection;
2554     USHORT usFirstCharIndex;
2555     USHORT usLastCharIndex;
2556     /* According to the Apple spec, original version didn't have the below fields,
2557      * version numbers were taken from the OpenType spec.
2558      */
2559     /* version 0 (TrueType 1.5) */
2560     USHORT sTypoAscender;
2561     USHORT sTypoDescender;
2562     USHORT sTypoLineGap;
2563     USHORT usWinAscent;
2564     USHORT usWinDescent;
2565     /* version 1 (TrueType 1.66) */
2566     ULONG ulCodePageRange1;
2567     ULONG ulCodePageRange2;
2568     /* version 2 (OpenType 1.2) */
2569     SHORT sxHeight;
2570     SHORT sCapHeight;
2571     USHORT usDefaultChar;
2572     USHORT usBreakChar;
2573     USHORT usMaxContext;
2574 } TT_OS2_V2;
2575 #include "poppack.h"
2576
2577 #ifdef WORDS_BIGENDIAN
2578 #define GET_BE_WORD(x) (x)
2579 #define GET_BE_DWORD(x) (x)
2580 #else
2581 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2582 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2583 #endif
2584
2585 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2586                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2587                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2588 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2589 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2590 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2591
2592 typedef struct
2593 {
2594     USHORT version;
2595     USHORT num_tables;
2596 } cmap_header;
2597
2598 typedef struct
2599 {
2600     USHORT plat_id;
2601     USHORT enc_id;
2602     ULONG offset;
2603 } cmap_encoding_record;
2604
2605 typedef struct
2606 {
2607     USHORT format;
2608     USHORT length;
2609     USHORT language;
2610
2611     BYTE glyph_ids[256];
2612 } cmap_format_0;
2613
2614 typedef struct
2615 {
2616     USHORT format;
2617     USHORT length;
2618     USHORT language;
2619
2620     USHORT seg_countx2;
2621     USHORT search_range;
2622     USHORT entry_selector;
2623     USHORT range_shift;
2624
2625     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2626 /* Then follows:
2627     USHORT pad;
2628     USHORT start_count[seg_countx2 / 2];
2629     USHORT id_delta[seg_countx2 / 2];
2630     USHORT id_range_offset[seg_countx2 / 2];
2631     USHORT glyph_ids[];
2632 */
2633 } cmap_format_4;
2634
2635 typedef struct
2636 {
2637     USHORT end_count;
2638     USHORT start_count;
2639     USHORT id_delta;
2640     USHORT id_range_offset;
2641 } cmap_format_4_seg;
2642
2643 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2644 {
2645     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2646        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2647        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2648        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2649        os2->panose.bWeight, os2->panose.bProportion);
2650 }
2651
2652 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2653 {
2654     int i;
2655     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2656
2657     *first = 256;
2658
2659     for(i = 0; i < 256; i++)
2660     {
2661         if(cmap->glyph_ids[i] == 0) continue;
2662         *last = i;
2663         if(*first == 256) *first = i;
2664     }
2665     if(*first == 256) return FALSE;
2666     return TRUE;
2667 }
2668
2669 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2670 {
2671     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2672     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2673     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2674     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2675     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2676 }
2677
2678 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2679 {
2680     int i;
2681     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2682     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2683     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2684
2685     *first = 0x10000;
2686
2687     for(i = 0; i < seg_count; i++)
2688     {
2689         DWORD code, index;
2690         cmap_format_4_seg seg;
2691
2692         get_seg4(cmap, i, &seg);
2693         for(code = seg.start_count; code <= seg.end_count; code++)
2694         {
2695             if(seg.id_range_offset == 0)
2696                 index = (seg.id_delta + code) & 0xffff;
2697             else
2698             {
2699                 index = seg.id_range_offset / 2
2700                     + code - seg.start_count
2701                     + i - seg_count;
2702
2703                 /* some fonts have broken last segment */
2704                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2705                     index = GET_BE_WORD(glyph_ids[index]);
2706                 else
2707                 {
2708                     trace("segment %04x/%04x index %04x points to nowhere\n",
2709                           seg.start_count, seg.end_count, index);
2710                     index = 0;
2711                 }
2712                 if(index) index += seg.id_delta;
2713             }
2714             if(*first == 0x10000)
2715                 *last = *first = code;
2716             else if(index)
2717                 *last = code;
2718         }
2719     }
2720
2721     if(*first == 0x10000) return FALSE;
2722     return TRUE;
2723 }
2724
2725 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2726 {
2727     USHORT i;
2728     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2729
2730     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2731     {
2732         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2733             return (BYTE *)header + GET_BE_DWORD(record->offset);
2734         record++;
2735     }
2736     return NULL;
2737 }
2738
2739 typedef enum
2740 {
2741     cmap_none,
2742     cmap_ms_unicode,
2743     cmap_ms_symbol
2744 } cmap_type;
2745
2746 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2747 {
2748     LONG size, ret;
2749     cmap_header *header;
2750     void *cmap;
2751     BOOL r = FALSE;
2752     WORD format;
2753
2754     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2755     ok(size != GDI_ERROR, "no cmap table found\n");
2756     if(size == GDI_ERROR) return FALSE;
2757
2758     header = HeapAlloc(GetProcessHeap(), 0, size);
2759     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2760     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2761     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2762
2763     cmap = get_cmap(header, 3, 1);
2764     if(cmap)
2765         *cmap_type = cmap_ms_unicode;
2766     else
2767     {
2768         cmap = get_cmap(header, 3, 0);
2769         if(cmap) *cmap_type = cmap_ms_symbol;
2770     }
2771     if(!cmap)
2772     {
2773         *cmap_type = cmap_none;
2774         goto end;
2775     }
2776
2777     format = GET_BE_WORD(*(WORD *)cmap);
2778     switch(format)
2779     {
2780     case 0:
2781         r = get_first_last_from_cmap0(cmap, first, last);
2782         break;
2783     case 4:
2784         r = get_first_last_from_cmap4(cmap, first, last, size);
2785         break;
2786     default:
2787         trace("unhandled cmap format %d\n", format);
2788         break;
2789     }
2790
2791 end:
2792     HeapFree(GetProcessHeap(), 0, header);
2793     return r;
2794 }
2795
2796 #define TT_PLATFORM_MICROSOFT 3
2797 #define TT_MS_ID_SYMBOL_CS 0
2798 #define TT_MS_ID_UNICODE_CS 1
2799 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2800 #define TT_NAME_ID_FONT_FAMILY 1
2801 #define TT_NAME_ID_FONT_SUBFAMILY 2
2802 #define TT_NAME_ID_UNIQUE_ID 3
2803 #define TT_NAME_ID_FULL_NAME 4
2804
2805 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, WCHAR *out_buf, SIZE_T out_size, LCID language_id)
2806 {
2807     struct sfnt_name_header
2808     {
2809         USHORT format;
2810         USHORT number_of_record;
2811         USHORT storage_offset;
2812     } *header;
2813     struct sfnt_name
2814     {
2815         USHORT platform_id;
2816         USHORT encoding_id;
2817         USHORT language_id;
2818         USHORT name_id;
2819         USHORT length;
2820         USHORT offset;
2821     } *entry;
2822     BOOL r = FALSE;
2823     LONG size, offset, length;
2824     LONG c, ret;
2825     WCHAR *name;
2826     BYTE *data;
2827     USHORT i;
2828
2829     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2830     ok(size != GDI_ERROR, "no name table found\n");
2831     if(size == GDI_ERROR) return FALSE;
2832
2833     data = HeapAlloc(GetProcessHeap(), 0, size);
2834     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2835     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2836
2837     header = (void *)data;
2838     header->format = GET_BE_WORD(header->format);
2839     header->number_of_record = GET_BE_WORD(header->number_of_record);
2840     header->storage_offset = GET_BE_WORD(header->storage_offset);
2841     if (header->format != 0)
2842     {
2843         trace("got format %u\n", header->format);
2844         goto out;
2845     }
2846     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2847     {
2848         trace("number records out of range: %d\n", header->number_of_record);
2849         goto out;
2850     }
2851     if (header->storage_offset >= size)
2852     {
2853         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2854         goto out;
2855     }
2856
2857     entry = (void *)&header[1];
2858     for (i = 0; i < header->number_of_record; i++)
2859     {
2860         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2861             (GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS && GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_SYMBOL_CS) ||
2862             GET_BE_WORD(entry[i].language_id) != language_id ||
2863             GET_BE_WORD(entry[i].name_id) != name_id)
2864         {
2865             continue;
2866         }
2867
2868         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2869         length = GET_BE_WORD(entry[i].length);
2870         if (offset + length > size)
2871         {
2872             trace("entry %d is out of range\n", i);
2873             break;
2874         }
2875         if (length >= out_size)
2876         {
2877             trace("buffer too small for entry %d\n", i);
2878             break;
2879         }
2880
2881         name = (WCHAR *)(data + offset);
2882         for (c = 0; c < length / 2; c++)
2883             out_buf[c] = GET_BE_WORD(name[c]);
2884         out_buf[c] = 0;
2885
2886         r = TRUE;
2887         break;
2888     }
2889
2890 out:
2891     HeapFree(GetProcessHeap(), 0, data);
2892     return r;
2893 }
2894
2895 static void test_text_metrics(const LOGFONT *lf, const NEWTEXTMETRIC *ntm)
2896 {
2897     HDC hdc;
2898     HFONT hfont, hfont_old;
2899     TEXTMETRICA tmA;
2900     TT_OS2_V2 tt_os2;
2901     LONG size, ret;
2902     const char *font_name = lf->lfFaceName;
2903     DWORD cmap_first = 0, cmap_last = 0;
2904     UINT ascent, descent, cell_height;
2905     cmap_type cmap_type;
2906     BOOL sys_lang_non_english;
2907
2908     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2909     hdc = GetDC(0);
2910
2911     SetLastError(0xdeadbeef);
2912     hfont = CreateFontIndirectA(lf);
2913     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2914
2915     hfont_old = SelectObject(hdc, hfont);
2916
2917     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2918     if (size == GDI_ERROR)
2919     {
2920         trace("OS/2 chunk was not found\n");
2921         goto end_of_test;
2922     }
2923     if (size > sizeof(tt_os2))
2924     {
2925         trace("got too large OS/2 chunk of size %u\n", size);
2926         size = sizeof(tt_os2);
2927     }
2928
2929     memset(&tt_os2, 0, sizeof(tt_os2));
2930     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2931     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2932
2933     ascent = GET_BE_WORD(tt_os2.usWinAscent);
2934     descent = GET_BE_WORD(tt_os2.usWinDescent);
2935     cell_height = ascent + descent;
2936     ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
2937        font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
2938
2939     SetLastError(0xdeadbeef);
2940     ret = GetTextMetricsA(hdc, &tmA);
2941     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2942
2943     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2944     {
2945         skip("Unable to retrieve first and last glyphs from cmap\n");
2946     }
2947     else
2948     {
2949         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2950         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2951         UINT os2_first_char, os2_last_char, default_char, break_char;
2952         USHORT version;
2953         TEXTMETRICW tmW;
2954
2955         version = GET_BE_WORD(tt_os2.version);
2956
2957         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2958         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2959         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2960         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2961
2962         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2963               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2964               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2965
2966         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2967         {
2968             expect_first_W    = 0;
2969             switch(GetACP())
2970             {
2971             case 1257:  /* Baltic */
2972                 expect_last_W = 0xf8fd;
2973                 break;
2974             default:
2975                 expect_last_W = 0xf0ff;
2976             }
2977             expect_break_W    = 0x20;
2978             expect_default_W  = expect_break_W - 1;
2979             expect_first_A    = 0x1e;
2980             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2981         }
2982         else
2983         {
2984             expect_first_W    = cmap_first;
2985             expect_last_W     = min(cmap_last, os2_last_char);
2986             if(os2_first_char <= 1)
2987                 expect_break_W = os2_first_char + 2;
2988             else if(os2_first_char > 0xff)
2989                 expect_break_W = 0x20;
2990             else
2991                 expect_break_W = os2_first_char;
2992             expect_default_W  = expect_break_W - 1;
2993             expect_first_A    = expect_default_W - 1;
2994             expect_last_A     = min(expect_last_W, 0xff);
2995         }
2996         expect_break_A    = expect_break_W;
2997         expect_default_A  = expect_default_W;
2998
2999         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
3000         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
3001             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
3002                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3003                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3004         else
3005             ok(tmA.tmFirstChar == expect_first_A ||
3006                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
3007                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
3008         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
3009             ok(tmA.tmLastChar == expect_last_A ||
3010                tmA.tmLastChar == 0xff /* win9x */,
3011                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
3012         else
3013            skip("tmLastChar is DBCS lead byte\n");
3014         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
3015            font_name, tmA.tmBreakChar, expect_break_A);
3016         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
3017            "A: tmDefaultChar for %s got %02x expected %02x\n",
3018            font_name, tmA.tmDefaultChar, expect_default_A);
3019
3020
3021         SetLastError(0xdeadbeef);
3022         ret = GetTextMetricsW(hdc, &tmW);
3023         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
3024            "GetTextMetricsW error %u\n", GetLastError());
3025         if (ret)
3026         {
3027             /* Wine uses the os2 first char */
3028             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
3029                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3030                              font_name, tmW.tmFirstChar, expect_first_W);
3031             else
3032                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
3033                    font_name, tmW.tmFirstChar, expect_first_W);
3034
3035             /* Wine uses the os2 last char */
3036             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
3037                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3038                              font_name, tmW.tmLastChar, expect_last_W);
3039             else
3040                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
3041                    font_name, tmW.tmLastChar, expect_last_W);
3042             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
3043                font_name, tmW.tmBreakChar, expect_break_W);
3044             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
3045                "W: tmDefaultChar for %s got %02x expected %02x\n",
3046                font_name, tmW.tmDefaultChar, expect_default_W);
3047
3048             /* Test the aspect ratio while we have tmW */
3049             ret = GetDeviceCaps(hdc, LOGPIXELSX);
3050             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3051                tmW.tmDigitizedAspectX, ret);
3052             ret = GetDeviceCaps(hdc, LOGPIXELSY);
3053             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3054                tmW.tmDigitizedAspectX, ret);
3055         }
3056     }
3057
3058     /* test FF_ values */
3059     switch(tt_os2.panose.bFamilyType)
3060     {
3061     case PAN_ANY:
3062     case PAN_NO_FIT:
3063     case PAN_FAMILY_TEXT_DISPLAY:
3064     case PAN_FAMILY_PICTORIAL:
3065     default:
3066         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3067            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3068         {
3069             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3070             break;
3071         }
3072         switch(tt_os2.panose.bSerifStyle)
3073         {
3074         case PAN_ANY:
3075         case PAN_NO_FIT:
3076         default:
3077             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3078             break;
3079
3080         case PAN_SERIF_COVE:
3081         case PAN_SERIF_OBTUSE_COVE:
3082         case PAN_SERIF_SQUARE_COVE:
3083         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3084         case PAN_SERIF_SQUARE:
3085         case PAN_SERIF_THIN:
3086         case PAN_SERIF_BONE:
3087         case PAN_SERIF_EXAGGERATED:
3088         case PAN_SERIF_TRIANGLE:
3089             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
3090             break;
3091
3092         case PAN_SERIF_NORMAL_SANS:
3093         case PAN_SERIF_OBTUSE_SANS:
3094         case PAN_SERIF_PERP_SANS:
3095         case PAN_SERIF_FLARED:
3096         case PAN_SERIF_ROUNDED:
3097             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
3098             break;
3099         }
3100         break;
3101
3102     case PAN_FAMILY_SCRIPT:
3103         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
3104         break;
3105
3106     case PAN_FAMILY_DECORATIVE:
3107         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
3108         break;
3109     }
3110
3111     test_negative_width(hdc, lf);
3112
3113 end_of_test:
3114     SelectObject(hdc, hfont_old);
3115     DeleteObject(hfont);
3116
3117     ReleaseDC(0, hdc);
3118 }
3119
3120 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3121 {
3122     INT *enumed = (INT *)lParam;
3123
3124     if (type == TRUETYPE_FONTTYPE)
3125     {
3126         (*enumed)++;
3127         test_text_metrics(lf, (const NEWTEXTMETRIC *)ntm);
3128     }
3129     return 1;
3130 }
3131
3132 static void test_GetTextMetrics(void)
3133 {
3134     LOGFONTA lf;
3135     HDC hdc;
3136     INT enumed;
3137
3138     /* Report only once */
3139     if(!pGetGlyphIndicesA)
3140         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
3141
3142     hdc = GetDC(0);
3143
3144     memset(&lf, 0, sizeof(lf));
3145     lf.lfCharSet = DEFAULT_CHARSET;
3146     enumed = 0;
3147     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
3148     trace("Tested metrics of %d truetype fonts\n", enumed);
3149
3150     ReleaseDC(0, hdc);
3151 }
3152
3153 static void test_nonexistent_font(void)
3154 {
3155     static const struct
3156     {
3157         const char *name;
3158         int charset;
3159     } font_subst[] =
3160     {
3161         { "Times New Roman Baltic", 186 },
3162         { "Times New Roman CE", 238 },
3163         { "Times New Roman CYR", 204 },
3164         { "Times New Roman Greek", 161 },
3165         { "Times New Roman TUR", 162 }
3166     };
3167     LOGFONTA lf;
3168     HDC hdc;
3169     HFONT hfont;
3170     CHARSETINFO csi;
3171     INT cs, expected_cs, i;
3172     char buf[LF_FACESIZE];
3173
3174     if (!is_truetype_font_installed("Arial") ||
3175         !is_truetype_font_installed("Times New Roman"))
3176     {
3177         skip("Arial or Times New Roman not installed\n");
3178         return;
3179     }
3180
3181     expected_cs = GetACP();
3182     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
3183     {
3184         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
3185         return;
3186     }
3187     expected_cs = csi.ciCharset;
3188     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
3189
3190     hdc = GetDC(0);
3191
3192     memset(&lf, 0, sizeof(lf));
3193     lf.lfHeight = 100;
3194     lf.lfWeight = FW_REGULAR;
3195     lf.lfCharSet = ANSI_CHARSET;
3196     lf.lfPitchAndFamily = FF_SWISS;
3197     strcpy(lf.lfFaceName, "Nonexistent font");
3198     hfont = CreateFontIndirectA(&lf);
3199     hfont = SelectObject(hdc, hfont);
3200     GetTextFaceA(hdc, sizeof(buf), buf);
3201     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3202     cs = GetTextCharset(hdc);
3203     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3204     DeleteObject(SelectObject(hdc, hfont));
3205
3206     memset(&lf, 0, sizeof(lf));
3207     lf.lfHeight = -13;
3208     lf.lfWeight = FW_DONTCARE;
3209     strcpy(lf.lfFaceName, "Nonexistent font");
3210     hfont = CreateFontIndirectA(&lf);
3211     hfont = SelectObject(hdc, hfont);
3212     GetTextFaceA(hdc, sizeof(buf), buf);
3213 todo_wine /* Wine uses Arial for all substitutions */
3214     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3215        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3216        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3217        "Got %s\n", buf);
3218     cs = GetTextCharset(hdc);
3219     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3220     DeleteObject(SelectObject(hdc, hfont));
3221
3222     memset(&lf, 0, sizeof(lf));
3223     lf.lfHeight = -13;
3224     lf.lfWeight = FW_REGULAR;
3225     strcpy(lf.lfFaceName, "Nonexistent font");
3226     hfont = CreateFontIndirectA(&lf);
3227     hfont = SelectObject(hdc, hfont);
3228     GetTextFaceA(hdc, sizeof(buf), buf);
3229     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3230        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3231     cs = GetTextCharset(hdc);
3232     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3233     DeleteObject(SelectObject(hdc, hfont));
3234
3235     memset(&lf, 0, sizeof(lf));
3236     lf.lfHeight = -13;
3237     lf.lfWeight = FW_DONTCARE;
3238     strcpy(lf.lfFaceName, "Times New Roman");
3239     hfont = CreateFontIndirectA(&lf);
3240     hfont = SelectObject(hdc, hfont);
3241     GetTextFaceA(hdc, sizeof(buf), buf);
3242     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3243     cs = GetTextCharset(hdc);
3244     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3245     DeleteObject(SelectObject(hdc, hfont));
3246
3247     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3248     {
3249         memset(&lf, 0, sizeof(lf));
3250         lf.lfHeight = -13;
3251         lf.lfWeight = FW_REGULAR;
3252         strcpy(lf.lfFaceName, font_subst[i].name);
3253         hfont = CreateFontIndirectA(&lf);
3254         hfont = SelectObject(hdc, hfont);
3255         cs = GetTextCharset(hdc);
3256         if (font_subst[i].charset == expected_cs)
3257         {
3258             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3259             GetTextFaceA(hdc, sizeof(buf), buf);
3260             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3261         }
3262         else
3263         {
3264             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3265             GetTextFaceA(hdc, sizeof(buf), buf);
3266             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3267                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3268         }
3269         DeleteObject(SelectObject(hdc, hfont));
3270
3271         memset(&lf, 0, sizeof(lf));
3272         lf.lfHeight = -13;
3273         lf.lfWeight = FW_DONTCARE;
3274         strcpy(lf.lfFaceName, font_subst[i].name);
3275         hfont = CreateFontIndirectA(&lf);
3276         hfont = SelectObject(hdc, hfont);
3277         GetTextFaceA(hdc, sizeof(buf), buf);
3278         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3279            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3280            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3281            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3282            "got %s for font %s\n", buf, font_subst[i].name);
3283         cs = GetTextCharset(hdc);
3284         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3285         DeleteObject(SelectObject(hdc, hfont));
3286     }
3287
3288     ReleaseDC(0, hdc);
3289 }
3290
3291 static void test_GdiRealizationInfo(void)
3292 {
3293     HDC hdc;
3294     DWORD info[4];
3295     BOOL r;
3296     HFONT hfont, hfont_old;
3297     LOGFONTA lf;
3298
3299     if(!pGdiRealizationInfo)
3300     {
3301         win_skip("GdiRealizationInfo not available\n");
3302         return;
3303     }
3304
3305     hdc = GetDC(0);
3306
3307     memset(info, 0xcc, sizeof(info));
3308     r = pGdiRealizationInfo(hdc, info);
3309     ok(r != 0, "ret 0\n");
3310     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3311     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3312
3313     if (!is_truetype_font_installed("Arial"))
3314     {
3315         skip("skipping GdiRealizationInfo with truetype font\n");
3316         goto end;
3317     }
3318
3319     memset(&lf, 0, sizeof(lf));
3320     strcpy(lf.lfFaceName, "Arial");
3321     lf.lfHeight = 20;
3322     lf.lfWeight = FW_NORMAL;
3323     hfont = CreateFontIndirectA(&lf);
3324     hfont_old = SelectObject(hdc, hfont);
3325
3326     memset(info, 0xcc, sizeof(info));
3327     r = pGdiRealizationInfo(hdc, info);
3328     ok(r != 0, "ret 0\n");
3329     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3330     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3331
3332     DeleteObject(SelectObject(hdc, hfont_old));
3333
3334  end:
3335     ReleaseDC(0, hdc);
3336 }
3337
3338 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3339    the nul in the count of characters copied when the face name buffer is not
3340    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3341    always includes it.  */
3342 static void test_GetTextFace(void)
3343 {
3344     static const char faceA[] = "Tahoma";
3345     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3346     LOGFONTA fA = {0};
3347     LOGFONTW fW = {0};
3348     char bufA[LF_FACESIZE];
3349     WCHAR bufW[LF_FACESIZE];
3350     HFONT f, g;
3351     HDC dc;
3352     int n;
3353
3354     if(!is_font_installed("Tahoma"))
3355     {
3356         skip("Tahoma is not installed so skipping this test\n");
3357         return;
3358     }
3359
3360     /* 'A' case.  */
3361     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3362     f = CreateFontIndirectA(&fA);
3363     ok(f != NULL, "CreateFontIndirectA failed\n");
3364
3365     dc = GetDC(NULL);
3366     g = SelectObject(dc, f);
3367     n = GetTextFaceA(dc, sizeof bufA, bufA);
3368     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3369     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3370
3371     /* Play with the count arg.  */
3372     bufA[0] = 'x';
3373     n = GetTextFaceA(dc, 0, bufA);
3374     ok(n == 0, "GetTextFaceA returned %d\n", n);
3375     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3376
3377     bufA[0] = 'x';
3378     n = GetTextFaceA(dc, 1, bufA);
3379     ok(n == 0, "GetTextFaceA returned %d\n", n);
3380     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3381
3382     bufA[0] = 'x'; bufA[1] = 'y';
3383     n = GetTextFaceA(dc, 2, bufA);
3384     ok(n == 1, "GetTextFaceA returned %d\n", n);
3385     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3386
3387     n = GetTextFaceA(dc, 0, NULL);
3388     ok(n == sizeof faceA ||
3389        broken(n == 0), /* win98, winMe */
3390        "GetTextFaceA returned %d\n", n);
3391
3392     DeleteObject(SelectObject(dc, g));
3393     ReleaseDC(NULL, dc);
3394
3395     /* 'W' case.  */
3396     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3397     SetLastError(0xdeadbeef);
3398     f = CreateFontIndirectW(&fW);
3399     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3400     {
3401         win_skip("CreateFontIndirectW is not implemented\n");
3402         return;
3403     }
3404     ok(f != NULL, "CreateFontIndirectW failed\n");
3405
3406     dc = GetDC(NULL);
3407     g = SelectObject(dc, f);
3408     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3409     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3410     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3411
3412     /* Play with the count arg.  */
3413     bufW[0] = 'x';
3414     n = GetTextFaceW(dc, 0, bufW);
3415     ok(n == 0, "GetTextFaceW returned %d\n", n);
3416     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3417
3418     bufW[0] = 'x';
3419     n = GetTextFaceW(dc, 1, bufW);
3420     ok(n == 1, "GetTextFaceW returned %d\n", n);
3421     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3422
3423     bufW[0] = 'x'; bufW[1] = 'y';
3424     n = GetTextFaceW(dc, 2, bufW);
3425     ok(n == 2, "GetTextFaceW returned %d\n", n);
3426     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3427
3428     n = GetTextFaceW(dc, 0, NULL);
3429     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3430
3431     DeleteObject(SelectObject(dc, g));
3432     ReleaseDC(NULL, dc);
3433 }
3434
3435 static void test_orientation(void)
3436 {
3437     static const char test_str[11] = "Test String";
3438     HDC hdc;
3439     LOGFONTA lf;
3440     HFONT hfont, old_hfont;
3441     SIZE size;
3442
3443     if (!is_truetype_font_installed("Arial"))
3444     {
3445         skip("Arial is not installed\n");
3446         return;
3447     }
3448
3449     hdc = CreateCompatibleDC(0);
3450     memset(&lf, 0, sizeof(lf));
3451     lstrcpyA(lf.lfFaceName, "Arial");
3452     lf.lfHeight = 72;
3453     lf.lfOrientation = lf.lfEscapement = 900;
3454     hfont = create_font("orientation", &lf);
3455     old_hfont = SelectObject(hdc, hfont);
3456     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3457     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3458     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3459     SelectObject(hdc, old_hfont);
3460     DeleteObject(hfont);
3461     DeleteDC(hdc);
3462 }
3463
3464 static void test_oemcharset(void)
3465 {
3466     HDC hdc;
3467     LOGFONTA lf, clf;
3468     HFONT hfont, old_hfont;
3469     int charset;
3470
3471     hdc = CreateCompatibleDC(0);
3472     ZeroMemory(&lf, sizeof(lf));
3473     lf.lfHeight = 12;
3474     lf.lfCharSet = OEM_CHARSET;
3475     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3476     lstrcpyA(lf.lfFaceName, "Terminal");
3477     hfont = CreateFontIndirectA(&lf);
3478     old_hfont = SelectObject(hdc, hfont);
3479     charset = GetTextCharset(hdc);
3480 todo_wine
3481     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3482     hfont = SelectObject(hdc, old_hfont);
3483     GetObjectA(hfont, sizeof(clf), &clf);
3484     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3485     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3486     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3487     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3488     DeleteObject(hfont);
3489     DeleteDC(hdc);
3490 }
3491
3492 static void test_GetGlyphOutline(void)
3493 {
3494     HDC hdc;
3495     GLYPHMETRICS gm, gm2;
3496     LOGFONTA lf;
3497     HFONT hfont, old_hfont;
3498     INT ret, ret2;
3499     static const struct
3500     {
3501         UINT cs;
3502         UINT a;
3503         UINT w;
3504     } c[] =
3505     {
3506         {ANSI_CHARSET, 0x30, 0x30},
3507         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3508         {HANGEUL_CHARSET, 0x8141, 0xac02},
3509         {JOHAB_CHARSET, 0x8446, 0x3135},
3510         {GB2312_CHARSET, 0x8141, 0x4e04},
3511         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3512     };
3513     UINT i;
3514
3515     if (!is_truetype_font_installed("Tahoma"))
3516     {
3517         skip("Tahoma is not installed\n");
3518         return;
3519     }
3520
3521     hdc = CreateCompatibleDC(0);
3522     memset(&lf, 0, sizeof(lf));
3523     lf.lfHeight = 72;
3524     lstrcpyA(lf.lfFaceName, "Tahoma");
3525     SetLastError(0xdeadbeef);
3526     hfont = CreateFontIndirectA(&lf);
3527     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3528     old_hfont = SelectObject(hdc, hfont);
3529
3530     memset(&gm, 0, sizeof(gm));
3531     SetLastError(0xdeadbeef);
3532     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3533     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3534
3535     memset(&gm, 0, sizeof(gm));
3536     SetLastError(0xdeadbeef);
3537     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3538     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3539     ok(GetLastError() == 0xdeadbeef ||
3540        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3541        "expected 0xdeadbeef, got %u\n", GetLastError());
3542
3543     memset(&gm, 0, sizeof(gm));
3544     SetLastError(0xdeadbeef);
3545     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3546     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3547         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3548
3549     memset(&gm, 0, sizeof(gm));
3550     SetLastError(0xdeadbeef);
3551     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3552     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3553     {
3554        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3555        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3556     }
3557
3558     /* test for needed buffer size request on space char */
3559     memset(&gm, 0, sizeof(gm));
3560     SetLastError(0xdeadbeef);
3561     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3562     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3563         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3564
3565     /* requesting buffer size for space char + error */
3566     memset(&gm, 0, sizeof(gm));
3567     SetLastError(0xdeadbeef);
3568     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3569     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3570     {
3571        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3572        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3573     }
3574
3575     SelectObject(hdc, old_hfont);
3576     DeleteObject(hfont);
3577
3578     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3579     {
3580         lf.lfFaceName[0] = '\0';
3581         lf.lfCharSet = c[i].cs;
3582         lf.lfPitchAndFamily = 0;
3583         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3584         {
3585             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3586             continue;
3587         }
3588
3589         old_hfont = SelectObject(hdc, hfont);
3590
3591         /* expected to ignore superfluous bytes (sigle-byte character) */
3592         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3593         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3594         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3595
3596         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3597         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3598            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3599
3600         /* expected to ignore superfluous bytes (double-byte character) */
3601         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3602         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3603         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3604            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3605
3606         /* expected to match wide-char version results */
3607         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3608         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3609
3610         hfont = SelectObject(hdc, old_hfont);
3611         DeleteObject(hfont);
3612     }
3613
3614     DeleteDC(hdc);
3615 }
3616
3617 /* bug #9995: there is a limit to the character width that can be specified */
3618 static void test_GetTextMetrics2(const char *fontname, int font_height)
3619 {
3620     HFONT of, hf;
3621     HDC hdc;
3622     TEXTMETRICA tm;
3623     BOOL ret;
3624     int ave_width, height, width, ratio, scale;
3625
3626     if (!is_truetype_font_installed( fontname)) {
3627         skip("%s is not installed\n", fontname);
3628         return;
3629     }
3630     hdc = CreateCompatibleDC(0);
3631     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3632     /* select width = 0 */
3633     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3634             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3635             DEFAULT_QUALITY, VARIABLE_PITCH,
3636             fontname);
3637     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3638     of = SelectObject( hdc, hf);
3639     ret = GetTextMetricsA( hdc, &tm);
3640     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3641     height = tm.tmHeight;
3642     ave_width = tm.tmAveCharWidth;
3643     SelectObject( hdc, of);
3644     DeleteObject( hf);
3645
3646     trace("height %d, ave width %d\n", height, ave_width);
3647
3648     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3649     {
3650         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3651                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3652                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3653         ok(hf != 0, "CreateFont failed\n");
3654         of = SelectObject(hdc, hf);
3655         ret = GetTextMetrics(hdc, &tm);
3656         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3657         SelectObject(hdc, of);
3658         DeleteObject(hf);
3659
3660         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3661             break;
3662     }
3663
3664     DeleteDC(hdc);
3665
3666     ratio = width / height;
3667     scale = width / ave_width;
3668
3669     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3670           width, height, ratio, width, ave_width, scale);
3671
3672     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3673 }
3674
3675 static void test_CreateFontIndirect(void)
3676 {
3677     LOGFONTA lf, getobj_lf;
3678     int ret, i;
3679     HFONT hfont;
3680     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3681
3682     memset(&lf, 0, sizeof(lf));
3683     lf.lfCharSet = ANSI_CHARSET;
3684     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3685     lf.lfHeight = 16;
3686     lf.lfWidth = 16;
3687     lf.lfQuality = DEFAULT_QUALITY;
3688     lf.lfItalic = FALSE;
3689     lf.lfWeight = FW_DONTCARE;
3690
3691     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3692     {
3693         lstrcpyA(lf.lfFaceName, TestName[i]);
3694         hfont = CreateFontIndirectA(&lf);
3695         ok(hfont != 0, "CreateFontIndirectA failed\n");
3696         SetLastError(0xdeadbeef);
3697         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3698         ok(ret, "GetObject failed: %d\n", GetLastError());
3699         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3700         ok(lf.lfWeight == getobj_lf.lfWeight ||
3701            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3702            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3703         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3704            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3705            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3706         DeleteObject(hfont);
3707     }
3708 }
3709
3710 static void test_CreateFontIndirectEx(void)
3711 {
3712     ENUMLOGFONTEXDVA lfex;
3713     HFONT hfont;
3714
3715     if (!pCreateFontIndirectExA)
3716     {
3717         win_skip("CreateFontIndirectExA is not available\n");
3718         return;
3719     }
3720
3721     if (!is_truetype_font_installed("Arial"))
3722     {
3723         skip("Arial is not installed\n");
3724         return;
3725     }
3726
3727     SetLastError(0xdeadbeef);
3728     hfont = pCreateFontIndirectExA(NULL);
3729     ok(hfont == NULL, "got %p\n", hfont);
3730     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3731
3732     memset(&lfex, 0, sizeof(lfex));
3733     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3734     hfont = pCreateFontIndirectExA(&lfex);
3735     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3736     if (hfont)
3737         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3738     DeleteObject(hfont);
3739 }
3740
3741 static void free_font(void *font)
3742 {
3743     UnmapViewOfFile(font);
3744 }
3745
3746 static void *load_font(const char *font_name, DWORD *font_size)
3747 {
3748     char file_name[MAX_PATH];
3749     HANDLE file, mapping;
3750     void *font;
3751
3752     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3753     strcat(file_name, "\\fonts\\");
3754     strcat(file_name, font_name);
3755
3756     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3757     if (file == INVALID_HANDLE_VALUE) return NULL;
3758
3759     *font_size = GetFileSize(file, NULL);
3760
3761     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3762     if (!mapping)
3763     {
3764         CloseHandle(file);
3765         return NULL;
3766     }
3767
3768     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3769
3770     CloseHandle(file);
3771     CloseHandle(mapping);
3772     return font;
3773 }
3774
3775 static void test_AddFontMemResource(void)
3776 {
3777     void *font;
3778     DWORD font_size, num_fonts;
3779     HANDLE ret;
3780     BOOL bRet;
3781
3782     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3783     {
3784         win_skip("AddFontMemResourceEx is not available on this platform\n");
3785         return;
3786     }
3787
3788     font = load_font("sserife.fon", &font_size);
3789     if (!font)
3790     {
3791         skip("Unable to locate and load font sserife.fon\n");
3792         return;
3793     }
3794
3795     SetLastError(0xdeadbeef);
3796     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3797     ok(!ret, "AddFontMemResourceEx should fail\n");
3798     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3799        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3800        GetLastError());
3801
3802     SetLastError(0xdeadbeef);
3803     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3804     ok(!ret, "AddFontMemResourceEx should fail\n");
3805     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3806        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3807        GetLastError());
3808
3809     SetLastError(0xdeadbeef);
3810     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3811     ok(!ret, "AddFontMemResourceEx should fail\n");
3812     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3813        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3814        GetLastError());
3815
3816     SetLastError(0xdeadbeef);
3817     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3818     ok(!ret, "AddFontMemResourceEx should fail\n");
3819     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3820        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3821        GetLastError());
3822
3823     SetLastError(0xdeadbeef);
3824     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3825     ok(!ret, "AddFontMemResourceEx should fail\n");
3826     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3827        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3828        GetLastError());
3829
3830     SetLastError(0xdeadbeef);
3831     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
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
3837     num_fonts = 0xdeadbeef;
3838     SetLastError(0xdeadbeef);
3839     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3840     ok(!ret, "AddFontMemResourceEx should fail\n");
3841     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3842        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3843        GetLastError());
3844     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3845
3846     if (0) /* hangs under windows 2000 */
3847     {
3848         num_fonts = 0xdeadbeef;
3849         SetLastError(0xdeadbeef);
3850         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3851         ok(!ret, "AddFontMemResourceEx should fail\n");
3852         ok(GetLastError() == 0xdeadbeef,
3853            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3854            GetLastError());
3855         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3856     }
3857
3858     num_fonts = 0xdeadbeef;
3859     SetLastError(0xdeadbeef);
3860     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3861     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3862     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3863     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3864
3865     free_font(font);
3866
3867     SetLastError(0xdeadbeef);
3868     bRet = pRemoveFontMemResourceEx(ret);
3869     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3870
3871     /* test invalid pointer to number of loaded fonts */
3872     font = load_font("sserife.fon", &font_size);
3873     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3874
3875     SetLastError(0xdeadbeef);
3876     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3877     ok(!ret, "AddFontMemResourceEx should fail\n");
3878     ok(GetLastError() == 0xdeadbeef,
3879        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3880        GetLastError());
3881
3882     SetLastError(0xdeadbeef);
3883     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3884     ok(!ret, "AddFontMemResourceEx should fail\n");
3885     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3886        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3887        GetLastError());
3888
3889     free_font(font);
3890 }
3891
3892 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3893 {
3894     LOGFONT *lf;
3895
3896     if (type != TRUETYPE_FONTTYPE) return 1;
3897
3898     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3899
3900     lf = (LOGFONT *)lparam;
3901     *lf = *elf;
3902     return 0;
3903 }
3904
3905 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3906 {
3907     int ret;
3908     LOGFONT *lf;
3909
3910     if (type != TRUETYPE_FONTTYPE) return 1;
3911
3912     lf = (LOGFONT *)lparam;
3913     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3914     if(ret == 0)
3915     {
3916         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3917         *lf = *elf;
3918         return 0;
3919     }
3920     return 1;
3921 }
3922
3923 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3924 {
3925     return lparam;
3926 }
3927
3928 static void test_EnumFonts(void)
3929 {
3930     int ret;
3931     LOGFONT lf;
3932     HDC hdc;
3933
3934     if (!is_truetype_font_installed("Arial"))
3935     {
3936         skip("Arial is not installed\n");
3937         return;
3938     }
3939
3940     /* Windows uses localized font face names, so Arial Bold won't be found */
3941     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3942     {
3943         skip("User locale is not English, skipping the test\n");
3944         return;
3945     }
3946
3947     hdc = CreateCompatibleDC(0);
3948
3949     /* check that the enumproc's retval is returned */
3950     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
3951     ok(ret == 0xcafe, "got %08x\n", ret);
3952
3953     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3954     ok(!ret, "font Arial is not enumerated\n");
3955     ret = strcmp(lf.lfFaceName, "Arial");
3956     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3957     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3958
3959     lstrcpy(lf.lfFaceName, "Arial");
3960     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3961     ok(!ret, "font Arial is not enumerated\n");
3962     ret = strcmp(lf.lfFaceName, "Arial");
3963     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3964     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3965
3966     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3967     ok(!ret, "font Arial Bold is not enumerated\n");
3968     ret = strcmp(lf.lfFaceName, "Arial");
3969     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3970     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3971
3972     lstrcpy(lf.lfFaceName, "Arial Bold");
3973     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3974     ok(ret, "font Arial Bold should not be enumerated\n");
3975
3976     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3977     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3978     ret = strcmp(lf.lfFaceName, "Arial");
3979     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3980     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3981
3982     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3983     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3984     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3985
3986     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3987     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3988
3989     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3990     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3991     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3992
3993     DeleteDC(hdc);
3994 }
3995
3996 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3997 {
3998     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3999     const char *fullname = (const char *)lParam;
4000
4001     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
4002
4003     return 1;
4004 }
4005
4006 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
4007 {
4008     HDC hdc = GetDC(0);
4009     BOOL ret = FALSE;
4010
4011     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
4012         ret = TRUE;
4013
4014     ReleaseDC(0, hdc);
4015     return ret;
4016 }
4017
4018 static void test_fullname(void)
4019 {
4020     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
4021     WCHAR bufW[LF_FULLFACESIZE];
4022     char bufA[LF_FULLFACESIZE];
4023     HFONT hfont, of;
4024     LOGFONTA lf;
4025     HDC hdc;
4026     int i;
4027     DWORD ret;
4028
4029     hdc = CreateCompatibleDC(0);
4030     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4031
4032     memset(&lf, 0, sizeof(lf));
4033     lf.lfCharSet = ANSI_CHARSET;
4034     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4035     lf.lfHeight = 16;
4036     lf.lfWidth = 16;
4037     lf.lfQuality = DEFAULT_QUALITY;
4038     lf.lfItalic = FALSE;
4039     lf.lfWeight = FW_DONTCARE;
4040
4041     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
4042     {
4043         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
4044         {
4045             skip("%s is not installed\n", TestName[i]);
4046             continue;
4047         }
4048
4049         lstrcpyA(lf.lfFaceName, TestName[i]);
4050         hfont = CreateFontIndirectA(&lf);
4051         ok(hfont != 0, "CreateFontIndirectA failed\n");
4052
4053         of = SelectObject(hdc, hfont);
4054         bufW[0] = 0;
4055         bufA[0] = 0;
4056         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, sizeof(bufW), TT_MS_LANGID_ENGLISH_UNITED_STATES);
4057         ok(ret, "face full name could not be read\n");
4058         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, sizeof(bufA), NULL, FALSE);
4059         ok(!lstrcmpA(bufA, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], bufA);
4060         SelectObject(hdc, of);
4061         DeleteObject(hfont);
4062     }
4063     DeleteDC(hdc);
4064 }
4065
4066 static WCHAR *prepend_at(WCHAR *family)
4067 {
4068     if (!family)
4069         return NULL;
4070
4071     memmove(family + 1, family, (lstrlenW(family) + 1) * sizeof(WCHAR));
4072     family[0] = '@';
4073     return family;
4074 }
4075
4076 static void test_fullname2_helper(const char *Family)
4077 {
4078     char *FamilyName, *FaceName, *StyleName, *otmStr;
4079     struct enum_fullname_data efnd;
4080     WCHAR *bufW;
4081     char *bufA;
4082     HFONT hfont, of;
4083     LOGFONTA lf;
4084     HDC hdc;
4085     int i;
4086     DWORD otm_size, ret, buf_size;
4087     OUTLINETEXTMETRICA *otm;
4088     BOOL want_vertical, get_vertical;
4089     want_vertical = ( Family[0] == '@' );
4090
4091     hdc = CreateCompatibleDC(0);
4092     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4093
4094     memset(&lf, 0, sizeof(lf));
4095     lf.lfCharSet = DEFAULT_CHARSET;
4096     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4097     lf.lfHeight = 16;
4098     lf.lfWidth = 16;
4099     lf.lfQuality = DEFAULT_QUALITY;
4100     lf.lfItalic = FALSE;
4101     lf.lfWeight = FW_DONTCARE;
4102     lstrcpy(lf.lfFaceName, Family);
4103     efnd.total = 0;
4104     EnumFontFamiliesExA(hdc, &lf, enum_fullname_data_proc, (LPARAM)&efnd, 0);
4105     if (efnd.total == 0)
4106         skip("%s is not installed\n", lf.lfFaceName);
4107
4108     for (i = 0; i < efnd.total; i++)
4109     {
4110         FamilyName = (char *)efnd.elf[i].elfLogFont.lfFaceName;
4111         FaceName = (char *)efnd.elf[i].elfFullName;
4112         StyleName = (char *)efnd.elf[i].elfStyle;
4113
4114         trace("Checking font %s:\nFamilyName: %s; FaceName: %s; StyleName: %s\n", Family, FamilyName, FaceName, StyleName);
4115
4116         get_vertical = ( FamilyName[0] == '@' );
4117         ok(get_vertical == want_vertical, "Vertical flags don't match: %s %s\n", Family, FamilyName);
4118
4119         lstrcpyA(lf.lfFaceName, FaceName);
4120         hfont = CreateFontIndirectA(&lf);
4121         ok(hfont != 0, "CreateFontIndirectA failed\n");
4122
4123         of = SelectObject(hdc, hfont);
4124         buf_size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
4125         ok(buf_size != GDI_ERROR, "no name table found\n");
4126         if (buf_size == GDI_ERROR) continue;
4127
4128         bufW = HeapAlloc(GetProcessHeap(), 0, buf_size);
4129         bufA = HeapAlloc(GetProcessHeap(), 0, buf_size);
4130
4131         otm_size = GetOutlineTextMetricsA(hdc, 0, NULL);
4132         otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
4133         memset(otm, 0, otm_size);
4134         ret = GetOutlineTextMetrics(hdc, otm_size, otm);
4135         ok(ret != 0, "GetOutlineTextMetrics fails!\n");
4136         if (ret == 0) continue;
4137
4138         bufW[0] = 0;
4139         bufA[0] = 0;
4140         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, GetSystemDefaultLangID());
4141         if (!ret)
4142         {
4143             trace("no localized FONT_FAMILY found.\n");
4144             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_FAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4145         }
4146         ok(ret, "FAMILY (family name) could not be read\n");
4147         if (want_vertical) bufW = prepend_at(bufW);
4148         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4149         ok(!lstrcmpA(FamilyName, bufA), "font family names don't match: returned %s, expect %s\n", FamilyName, bufA);
4150         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFamilyName;
4151         ok(!lstrcmpA(FamilyName, otmStr), "FamilyName %s doesn't match otmpFamilyName %s\n", FamilyName, otmStr);
4152
4153         bufW[0] = 0;
4154         bufA[0] = 0;
4155         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, GetSystemDefaultLangID());
4156         if (!ret)
4157         {
4158             trace("no localized FULL_NAME found.\n");
4159             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4160         }
4161         ok(ret, "FULL_NAME (face name) could not be read\n");
4162         if (want_vertical) bufW = prepend_at(bufW);
4163         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4164         ok(!lstrcmpA(FaceName, bufA), "font face names don't match: returned %s, expect %s\n", FaceName, bufA);
4165         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFaceName;
4166         ok(!lstrcmpA(FaceName, otmStr), "FaceName %s doesn't match otmpFaceName %s\n", FaceName, otmStr);
4167
4168         bufW[0] = 0;
4169         bufA[0] = 0;
4170         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, GetSystemDefaultLangID());
4171         if (!ret)
4172         {
4173             trace("no localized FONT_SUBFAMILY found.\n");
4174             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_FONT_SUBFAMILY, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4175         }
4176         ok(ret, "SUBFAMILY (style name) could not be read\n");
4177         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4178         ok(!lstrcmpA(StyleName, bufA), "style names don't match: returned %s, expect %s\n", StyleName, bufA);
4179         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpStyleName;
4180         ok(!lstrcmpA(StyleName, otmStr), "StyleName %s doesn't match otmpStyleName %s\n", StyleName, otmStr);
4181
4182         bufW[0] = 0;
4183         bufA[0] = 0;
4184         ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, GetSystemDefaultLangID());
4185         if (!ret)
4186         {
4187             trace("no localized UNIQUE_ID found.\n");
4188             ret = get_ttf_nametable_entry(hdc, TT_NAME_ID_UNIQUE_ID, bufW, buf_size, TT_MS_LANGID_ENGLISH_UNITED_STATES);
4189         }
4190         ok(ret, "UNIQUE_ID (full name) could not be read\n");
4191         WideCharToMultiByte(CP_ACP, 0, bufW, -1, bufA, buf_size, NULL, FALSE);
4192         otmStr = (LPSTR)otm + (UINT_PTR)otm->otmpFullName;
4193         ok(!lstrcmpA(otmStr, bufA), "UNIQUE ID (full name) doesn't match: returned %s, expect %s\n", otmStr, bufA);
4194
4195         SelectObject(hdc, of);
4196         DeleteObject(hfont);
4197
4198         HeapFree(GetProcessHeap(), 0, otm);
4199         HeapFree(GetProcessHeap(), 0, bufW);
4200         HeapFree(GetProcessHeap(), 0, bufA);
4201     }
4202     DeleteDC(hdc);
4203 }
4204
4205 static void test_fullname2(void)
4206 {
4207     test_fullname2_helper("Arial");
4208     test_fullname2_helper("DejaVu Sans");
4209     test_fullname2_helper("Lucida Sans");
4210     test_fullname2_helper("Tahoma");
4211     test_fullname2_helper("Webdings");
4212     test_fullname2_helper("Wingdings");
4213     test_fullname2_helper("SimSun");
4214     test_fullname2_helper("NSimSun");
4215     test_fullname2_helper("MingLiu");
4216     test_fullname2_helper("PMingLiu");
4217     test_fullname2_helper("WenQuanYi Micro Hei");
4218     test_fullname2_helper("MS UI Gothic");
4219     test_fullname2_helper("Ume UI Gothic");
4220     test_fullname2_helper("MS Gothic");
4221     test_fullname2_helper("Ume Gothic");
4222     test_fullname2_helper("MS PGothic");
4223     test_fullname2_helper("Ume P Gothic");
4224     test_fullname2_helper("Gulim");
4225     test_fullname2_helper("Batang");
4226     test_fullname2_helper("UnBatang");
4227     test_fullname2_helper("UnDotum");
4228     test_fullname2_helper("@SimSun");
4229     test_fullname2_helper("@NSimSun");
4230     test_fullname2_helper("@MingLiu");
4231     test_fullname2_helper("@PMingLiu");
4232     test_fullname2_helper("@WenQuanYi Micro Hei");
4233     test_fullname2_helper("@MS UI Gothic");
4234     test_fullname2_helper("@Ume UI Gothic");
4235     test_fullname2_helper("@MS Gothic");
4236     test_fullname2_helper("@Ume Gothic");
4237     test_fullname2_helper("@MS PGothic");
4238     test_fullname2_helper("@Ume P Gothic");
4239     test_fullname2_helper("@Gulim");
4240     test_fullname2_helper("@Batang");
4241     test_fullname2_helper("@UnBatang");
4242     test_fullname2_helper("@UnDotum");
4243
4244 }
4245
4246 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
4247 {
4248     char tmp_path[MAX_PATH];
4249     HRSRC rsrc;
4250     void *rsrc_data;
4251     DWORD rsrc_size;
4252     HANDLE hfile;
4253     BOOL ret;
4254
4255     SetLastError(0xdeadbeef);
4256     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4257     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4258     if (!rsrc) return FALSE;
4259     SetLastError(0xdeadbeef);
4260     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4261     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4262     if (!rsrc_data) return FALSE;
4263     SetLastError(0xdeadbeef);
4264     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4265     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4266     if (!rsrc_size) return FALSE;
4267
4268     SetLastError(0xdeadbeef);
4269     ret = GetTempPath(MAX_PATH, tmp_path);
4270     ok(ret, "GetTempPath() error %d\n", GetLastError());
4271     SetLastError(0xdeadbeef);
4272     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4273     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4274
4275     SetLastError(0xdeadbeef);
4276     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4277     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4278     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4279
4280     SetLastError(0xdeadbeef);
4281     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4282     ok(ret, "WriteFile() error %d\n", GetLastError());
4283
4284     CloseHandle(hfile);
4285     return ret;
4286 }
4287
4288 static void test_GetGlyphOutline_empty_contour(void)
4289 {
4290     HDC hdc;
4291     LOGFONTA lf;
4292     HFONT hfont, hfont_prev;
4293     TTPOLYGONHEADER *header;
4294     GLYPHMETRICS gm;
4295     char buf[1024];
4296     DWORD ret;
4297
4298     memset(&lf, 0, sizeof(lf));
4299     lf.lfHeight = 72;
4300     lstrcpyA(lf.lfFaceName, "wine_test");
4301
4302     hfont = CreateFontIndirectA(&lf);
4303     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
4304
4305     hdc = GetDC(NULL);
4306
4307     hfont_prev = SelectObject(hdc, hfont);
4308     ok(hfont_prev != NULL, "SelectObject failed\n");
4309
4310     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, 0, NULL, &mat);
4311     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4312
4313     header = (TTPOLYGONHEADER*)buf;
4314     ret = GetGlyphOutlineW(hdc, 0xa8, GGO_NATIVE, &gm, sizeof(buf), buf, &mat);
4315     ok(ret == 228, "GetGlyphOutline returned %d, expected 228\n", ret);
4316     ok(header->cb == 36, "header->cb = %d, expected 36\n", header->cb);
4317     ok(header->dwType == TT_POLYGON_TYPE, "header->dwType = %d, expected TT_POLYGON_TYPE\n", header->dwType);
4318     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4319     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4320     header = (TTPOLYGONHEADER*)((char*)header+header->cb);
4321     ok(header->cb == 96, "header->cb = %d, expected 96\n", header->cb);
4322
4323     SelectObject(hdc, hfont_prev);
4324     DeleteObject(hfont);
4325     ReleaseDC(NULL, hdc);
4326 }
4327
4328 static void test_CreateScalableFontResource(void)
4329 {
4330     char ttf_name[MAX_PATH];
4331     char tmp_path[MAX_PATH];
4332     char fot_name[MAX_PATH];
4333     char *file_part;
4334     DWORD ret;
4335
4336     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4337     {
4338         win_skip("AddFontResourceExA is not available on this platform\n");
4339         return;
4340     }
4341
4342     if (!write_ttf_file("wine_test.ttf", ttf_name))
4343     {
4344         skip("Failed to create ttf file for testing\n");
4345         return;
4346     }
4347
4348     trace("created %s\n", ttf_name);
4349
4350     ret = is_truetype_font_installed("wine_test");
4351     ok(!ret, "font wine_test should not be enumerated\n");
4352
4353     ret = GetTempPath(MAX_PATH, tmp_path);
4354     ok(ret, "GetTempPath() error %d\n", GetLastError());
4355     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4356     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4357
4358     ret = GetFileAttributes(fot_name);
4359     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4360
4361     SetLastError(0xdeadbeef);
4362     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4363     ok(!ret, "CreateScalableFontResource() should fail\n");
4364     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4365
4366     SetLastError(0xdeadbeef);
4367     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4368     ok(!ret, "CreateScalableFontResource() should fail\n");
4369     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4370
4371     file_part = strrchr(ttf_name, '\\');
4372     SetLastError(0xdeadbeef);
4373     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4374     ok(!ret, "CreateScalableFontResource() should fail\n");
4375     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4376
4377     SetLastError(0xdeadbeef);
4378     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4379     ok(!ret, "CreateScalableFontResource() should fail\n");
4380     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4381
4382     SetLastError(0xdeadbeef);
4383     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4384     ok(!ret, "CreateScalableFontResource() should fail\n");
4385     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4386
4387     ret = DeleteFile(fot_name);
4388     ok(ret, "DeleteFile() error %d\n", GetLastError());
4389
4390     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4391 todo_wine
4392     ok(!ret, "RemoveFontResourceEx() should fail\n");
4393
4394     /* test public font resource */
4395     SetLastError(0xdeadbeef);
4396     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4397     ok(ret, "CreateScalableFontResource() 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     SetLastError(0xdeadbeef);
4403     ret = pAddFontResourceExA(fot_name, 0, 0);
4404     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4405
4406     ret = is_truetype_font_installed("wine_test");
4407     ok(ret, "font wine_test should be enumerated\n");
4408
4409     test_GetGlyphOutline_empty_contour();
4410
4411     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4412 todo_wine
4413     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4414
4415     SetLastError(0xdeadbeef);
4416     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4417     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4418
4419     ret = is_truetype_font_installed("wine_test");
4420 todo_wine
4421     ok(!ret, "font wine_test should not be enumerated\n");
4422
4423     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
4424     if (ret)
4425     {
4426         /* remove once RemoveFontResource is implemented */
4427         DeleteFile(fot_name);
4428         DeleteFile(ttf_name);
4429         return;
4430     }
4431
4432     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4433     ok(!ret, "RemoveFontResourceEx() should fail\n");
4434
4435     DeleteFile(fot_name);
4436
4437     /* test hidden font resource */
4438     SetLastError(0xdeadbeef);
4439     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4440     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4441
4442     ret = is_truetype_font_installed("wine_test");
4443     ok(!ret, "font wine_test should not be enumerated\n");
4444
4445     SetLastError(0xdeadbeef);
4446     ret = pAddFontResourceExA(fot_name, 0, 0);
4447     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4448
4449     ret = is_truetype_font_installed("wine_test");
4450     ok(!ret, "font wine_test should not be enumerated\n");
4451
4452     /* XP allows removing a private font added with 0 flags */
4453     SetLastError(0xdeadbeef);
4454     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4455     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4456
4457     ret = is_truetype_font_installed("wine_test");
4458     ok(!ret, "font wine_test should not be enumerated\n");
4459
4460     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4461     ok(!ret, "RemoveFontResourceEx() should fail\n");
4462
4463     DeleteFile(fot_name);
4464     DeleteFile(ttf_name);
4465 }
4466
4467 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4468 {
4469     LOGFONTA lf;
4470     HFONT hfont, hfont_prev;
4471     HDC hdc;
4472     char facename[100];
4473     DWORD ret;
4474     static const WCHAR str[] = { 0x2025 };
4475
4476     *installed = is_truetype_font_installed(name);
4477
4478     lf.lfHeight = -18;
4479     lf.lfWidth = 0;
4480     lf.lfEscapement = 0;
4481     lf.lfOrientation = 0;
4482     lf.lfWeight = FW_DONTCARE;
4483     lf.lfItalic = 0;
4484     lf.lfUnderline = 0;
4485     lf.lfStrikeOut = 0;
4486     lf.lfCharSet = DEFAULT_CHARSET;
4487     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4488     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4489     lf.lfQuality = DEFAULT_QUALITY;
4490     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4491     strcpy(lf.lfFaceName, name);
4492
4493     hfont = CreateFontIndirectA(&lf);
4494     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4495
4496     hdc = GetDC(NULL);
4497
4498     hfont_prev = SelectObject(hdc, hfont);
4499     ok(hfont_prev != NULL, "SelectObject failed\n");
4500
4501     ret = GetTextFaceA(hdc, sizeof facename, facename);
4502     ok(ret, "GetTextFaceA failed\n");
4503     *selected = !strcmp(facename, name);
4504
4505     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4506     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4507     if (!*selected)
4508         memset(gm, 0, sizeof *gm);
4509
4510     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4511     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4512
4513     SelectObject(hdc, hfont_prev);
4514     DeleteObject(hfont);
4515     ReleaseDC(NULL, hdc);
4516 }
4517
4518 static void test_vertical_font(void)
4519 {
4520     char ttf_name[MAX_PATH];
4521     int num;
4522     BOOL ret, installed, selected;
4523     GLYPHMETRICS gm;
4524     WORD hgi, vgi;
4525
4526     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4527     {
4528         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4529         return;
4530     }
4531
4532     if (!write_ttf_file("vertical.ttf", ttf_name))
4533     {
4534         skip("Failed to create ttf file for testing\n");
4535         return;
4536     }
4537
4538     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4539     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4540
4541     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
4542     ok(installed, "@WineTestVertical is not installed\n");
4543     ok(selected, "@WineTestVertical is not selected\n");
4544     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
4545        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
4546        gm.gmBlackBoxX, gm.gmBlackBoxY);
4547
4548     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4549     ok(installed, "@@WineTestVertical is not installed\n");
4550     ok(selected, "@@WineTestVertical is not selected\n");
4551     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4552        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4553        gm.gmBlackBoxX, gm.gmBlackBoxY);
4554
4555     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4556
4557     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4558     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4559
4560     DeleteFile(ttf_name);
4561 }
4562
4563 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4564                                            DWORD type, LPARAM lParam)
4565 {
4566     if (lf->lfFaceName[0] == '@') {
4567         return 0;
4568     }
4569     return 1;
4570 }
4571
4572 static void test_east_asian_font_selection(void)
4573 {
4574     HDC hdc;
4575     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4576                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4577     size_t i;
4578
4579     hdc = GetDC(NULL);
4580
4581     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4582     {
4583         LOGFONTA lf;
4584         HFONT hfont;
4585         char face_name[LF_FACESIZE];
4586         int ret;
4587
4588         memset(&lf, 0, sizeof lf);
4589         lf.lfFaceName[0] = '\0';
4590         lf.lfCharSet = charset[i];
4591
4592         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4593         {
4594             skip("Vertical font for charset %u is not installed\n", charset[i]);
4595             continue;
4596         }
4597
4598         hfont = CreateFontIndirectA(&lf);
4599         hfont = SelectObject(hdc, hfont);
4600         memset(face_name, 0, sizeof face_name);
4601         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4602         ok(ret && face_name[0] != '@',
4603            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4604         DeleteObject(SelectObject(hdc, hfont));
4605
4606         memset(&lf, 0, sizeof lf);
4607         strcpy(lf.lfFaceName, "@");
4608         lf.lfCharSet = charset[i];
4609         hfont = CreateFontIndirectA(&lf);
4610         hfont = SelectObject(hdc, hfont);
4611         memset(face_name, 0, sizeof face_name);
4612         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4613         ok(ret && face_name[0] == '@',
4614            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4615         DeleteObject(SelectObject(hdc, hfont));
4616     }
4617     ReleaseDC(NULL, hdc);
4618 }
4619
4620 static int get_font_dpi(const LOGFONT *lf)
4621 {
4622     HDC hdc = CreateCompatibleDC(0);
4623     HFONT hfont;
4624     TEXTMETRIC tm;
4625     int ret;
4626
4627     hfont = CreateFontIndirect(lf);
4628     ok(hfont != 0, "CreateFontIndirect failed\n");
4629
4630     SelectObject(hdc, hfont);
4631     ret = GetTextMetrics(hdc, &tm);
4632     ok(ret, "GetTextMetrics failed\n");
4633     ret = tm.tmDigitizedAspectX;
4634
4635     DeleteDC(hdc);
4636     DeleteObject(hfont);
4637
4638     return ret;
4639 }
4640
4641 static void test_stock_fonts(void)
4642 {
4643     static const int font[] =
4644     {
4645         ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, DEVICE_DEFAULT_FONT, DEFAULT_GUI_FONT
4646         /* SYSTEM_FIXED_FONT, OEM_FIXED_FONT */
4647     };
4648     static const struct test_data
4649     {
4650         int charset, weight, height, dpi;
4651         const char face_name[LF_FACESIZE];
4652     } td[][11] =
4653     {
4654         { /* ANSI_FIXED_FONT */
4655             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "Courier" },
4656             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "Courier" },
4657             { 0 }
4658         },
4659         { /* ANSI_VAR_FONT */
4660             { DEFAULT_CHARSET, FW_NORMAL, 12, 96, "MS Sans Serif" },
4661             { DEFAULT_CHARSET, FW_NORMAL, 12, 120, "MS Sans Serif" },
4662             { 0 }
4663         },
4664         { /* SYSTEM_FONT */
4665             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4666             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4667             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4668             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4669             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4670             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4671             { 0 }
4672         },
4673         { /* DEVICE_DEFAULT_FONT */
4674             { SHIFTJIS_CHARSET, FW_NORMAL, 18, 96, "System" },
4675             { SHIFTJIS_CHARSET, FW_NORMAL, 22, 120, "System" },
4676             { HANGEUL_CHARSET, FW_NORMAL, 16, 96, "System" },
4677             { HANGEUL_CHARSET, FW_NORMAL, 20, 120, "System" },
4678             { DEFAULT_CHARSET, FW_BOLD, 16, 96, "System" },
4679             { DEFAULT_CHARSET, FW_BOLD, 20, 120, "System" },
4680             { 0 }
4681         },
4682         { /* DEFAULT_GUI_FONT */
4683             { SHIFTJIS_CHARSET, FW_NORMAL, -12, 96, "?MS UI Gothic" },
4684             { SHIFTJIS_CHARSET, FW_NORMAL, -15, 120, "?MS UI Gothic" },
4685             { HANGEUL_CHARSET, FW_NORMAL, -12, 96, "?Gulim" },
4686             { HANGEUL_CHARSET, FW_NORMAL, -15, 120, "?Gulim" },
4687             { GB2312_CHARSET, FW_NORMAL, -12, 96, "?SimHei" },
4688             { GB2312_CHARSET, FW_NORMAL, -15, 120, "?SimHei" },
4689             { CHINESEBIG5_CHARSET, FW_NORMAL, -12, 96, "?MingLiU" },
4690             { CHINESEBIG5_CHARSET, FW_NORMAL, -15, 120, "?MingLiU" },
4691             { DEFAULT_CHARSET, FW_NORMAL, -11, 96, "MS Shell Dlg" },
4692             { DEFAULT_CHARSET, FW_NORMAL, -13, 120, "MS Shell Dlg" },
4693             { 0 }
4694         }
4695     };
4696     int i, j;
4697
4698     for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
4699     {
4700         HFONT hfont;
4701         LOGFONT lf;
4702         int ret;
4703
4704         hfont = GetStockObject(font[i]);
4705         ok(hfont != 0, "%d: GetStockObject(%d) failed\n", i, font[i]);
4706
4707         ret = GetObject(hfont, sizeof(lf), &lf);
4708         if (ret != sizeof(lf))
4709         {
4710             /* NT4 */
4711             win_skip("%d: GetObject returned %d instead of sizeof(LOGFONT)\n", i, ret);
4712             continue;
4713         }
4714
4715         for (j = 0; td[i][j].face_name[0] != 0; j++)
4716         {
4717             if (lf.lfCharSet != td[i][j].charset && td[i][j].charset != DEFAULT_CHARSET)
4718             {
4719                 continue;
4720             }
4721
4722             ret = get_font_dpi(&lf);
4723             if (ret != td[i][j].dpi)
4724             {
4725                 trace("%d(%d): font %s %d dpi doesn't match test data %d\n",
4726                       i, j, lf.lfFaceName, ret, td[i][j].dpi);
4727                 continue;
4728             }
4729
4730             ok(td[i][j].weight == lf.lfWeight, "%d(%d): expected lfWeight %d, got %d\n", i, j, td[i][j].weight, lf.lfWeight);
4731             ok(td[i][j].height == lf.lfHeight, "%d(%d): expected lfHeight %d, got %d\n", i, j, td[i][j].height, lf.lfHeight);
4732             if (td[i][j].face_name[0] == '?')
4733             {
4734                 /* Wine doesn't have this font, skip this case for now.
4735                    Actually, the face name is localized on Windows and varies
4736                    dpending on Windows versions (e.g. Japanese NT4 vs win2k). */
4737                 trace("%d(%d): default gui font is %s\n", i, j, lf.lfFaceName);
4738             }
4739             else
4740             {
4741                 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);
4742             }
4743             break;
4744         }
4745     }
4746 }
4747
4748 START_TEST(font)
4749 {
4750     init();
4751
4752     test_stock_fonts();
4753     test_logfont();
4754     test_bitmap_font();
4755     test_outline_font();
4756     test_bitmap_font_metrics();
4757     test_GdiGetCharDimensions();
4758     test_GetCharABCWidths();
4759     test_text_extents();
4760     test_GetGlyphIndices();
4761     test_GetKerningPairs();
4762     test_GetOutlineTextMetrics();
4763     test_SetTextJustification();
4764     test_font_charset();
4765     test_GetFontUnicodeRanges();
4766     test_nonexistent_font();
4767     test_orientation();
4768     test_height_selection();
4769     test_AddFontMemResource();
4770     test_EnumFonts();
4771
4772     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4773      * I'd like to avoid them in this test.
4774      */
4775     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4776     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4777     if (is_truetype_font_installed("Arial Black") &&
4778         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4779     {
4780         test_EnumFontFamilies("", ANSI_CHARSET);
4781         test_EnumFontFamilies("", SYMBOL_CHARSET);
4782         test_EnumFontFamilies("", DEFAULT_CHARSET);
4783     }
4784     else
4785         skip("Arial Black or Symbol/Wingdings is not installed\n");
4786     test_EnumFontFamiliesEx_default_charset();
4787     test_GetTextMetrics();
4788     test_GdiRealizationInfo();
4789     test_GetTextFace();
4790     test_GetGlyphOutline();
4791     test_GetTextMetrics2("Tahoma", -11);
4792     test_GetTextMetrics2("Tahoma", -55);
4793     test_GetTextMetrics2("Tahoma", -110);
4794     test_GetTextMetrics2("Arial", -11);
4795     test_GetTextMetrics2("Arial", -55);
4796     test_GetTextMetrics2("Arial", -110);
4797     test_CreateFontIndirect();
4798     test_CreateFontIndirectEx();
4799     test_oemcharset();
4800     test_fullname();
4801     test_fullname2();
4802     test_east_asian_font_selection();
4803
4804     /* These tests should be last test until RemoveFontResource
4805      * is properly implemented.
4806      */
4807     test_vertical_font();
4808     test_CreateScalableFontResource();
4809 }