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