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