po: Update French translation.
[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 LOGFONT *lf, const NEWTEXTMETRIC *ntm)
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     UINT ascent, descent, cell_height;
2855     cmap_type cmap_type;
2856     BOOL sys_lang_non_english;
2857
2858     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2859     hdc = GetDC(0);
2860
2861     SetLastError(0xdeadbeef);
2862     hfont = CreateFontIndirectA(lf);
2863     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2864
2865     hfont_old = SelectObject(hdc, hfont);
2866
2867     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2868     if (size == GDI_ERROR)
2869     {
2870         trace("OS/2 chunk was not found\n");
2871         goto end_of_test;
2872     }
2873     if (size > sizeof(tt_os2))
2874     {
2875         trace("got too large OS/2 chunk of size %u\n", size);
2876         size = sizeof(tt_os2);
2877     }
2878
2879     memset(&tt_os2, 0, sizeof(tt_os2));
2880     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2881     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2882
2883     ascent = GET_BE_WORD(tt_os2.usWinAscent);
2884     descent = GET_BE_WORD(tt_os2.usWinDescent);
2885     cell_height = ascent + descent;
2886     ok(ntm->ntmCellHeight == cell_height, "%s: ntmCellHeight %u != %u, os2.usWinAscent/os2.usWinDescent %u/%u\n",
2887        font_name, ntm->ntmCellHeight, cell_height, ascent, descent);
2888
2889     SetLastError(0xdeadbeef);
2890     ret = GetTextMetricsA(hdc, &tmA);
2891     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2892
2893     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2894     {
2895         skip("Unable to retrieve first and last glyphs from cmap\n");
2896     }
2897     else
2898     {
2899         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2900         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2901         UINT os2_first_char, os2_last_char, default_char, break_char;
2902         USHORT version;
2903         TEXTMETRICW tmW;
2904
2905         version = GET_BE_WORD(tt_os2.version);
2906
2907         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2908         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2909         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2910         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2911
2912         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2913               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2914               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2915
2916         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2917         {
2918             expect_first_W    = 0;
2919             switch(GetACP())
2920             {
2921             case 1257:  /* Baltic */
2922                 expect_last_W = 0xf8fd;
2923                 break;
2924             default:
2925                 expect_last_W = 0xf0ff;
2926             }
2927             expect_break_W    = 0x20;
2928             expect_default_W  = expect_break_W - 1;
2929             expect_first_A    = 0x1e;
2930             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2931         }
2932         else
2933         {
2934             expect_first_W    = cmap_first;
2935             expect_last_W     = min(cmap_last, os2_last_char);
2936             if(os2_first_char <= 1)
2937                 expect_break_W = os2_first_char + 2;
2938             else if(os2_first_char > 0xff)
2939                 expect_break_W = 0x20;
2940             else
2941                 expect_break_W = os2_first_char;
2942             expect_default_W  = expect_break_W - 1;
2943             expect_first_A    = expect_default_W - 1;
2944             expect_last_A     = min(expect_last_W, 0xff);
2945         }
2946         expect_break_A    = expect_break_W;
2947         expect_default_A  = expect_default_W;
2948
2949         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2950         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2951             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2952                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2953                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2954         else
2955             ok(tmA.tmFirstChar == expect_first_A ||
2956                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2957                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2958         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2959             ok(tmA.tmLastChar == expect_last_A ||
2960                tmA.tmLastChar == 0xff /* win9x */,
2961                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2962         else
2963            skip("tmLastChar is DBCS lead byte\n");
2964         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2965            font_name, tmA.tmBreakChar, expect_break_A);
2966         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2967            "A: tmDefaultChar for %s got %02x expected %02x\n",
2968            font_name, tmA.tmDefaultChar, expect_default_A);
2969
2970
2971         SetLastError(0xdeadbeef);
2972         ret = GetTextMetricsW(hdc, &tmW);
2973         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2974            "GetTextMetricsW error %u\n", GetLastError());
2975         if (ret)
2976         {
2977             /* Wine uses the os2 first char */
2978             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2979                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2980                              font_name, tmW.tmFirstChar, expect_first_W);
2981             else
2982                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2983                    font_name, tmW.tmFirstChar, expect_first_W);
2984
2985             /* Wine uses the os2 last char */
2986             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2987                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2988                              font_name, tmW.tmLastChar, expect_last_W);
2989             else
2990                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2991                    font_name, tmW.tmLastChar, expect_last_W);
2992             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2993                font_name, tmW.tmBreakChar, expect_break_W);
2994             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2995                "W: tmDefaultChar for %s got %02x expected %02x\n",
2996                font_name, tmW.tmDefaultChar, expect_default_W);
2997
2998             /* Test the aspect ratio while we have tmW */
2999             ret = GetDeviceCaps(hdc, LOGPIXELSX);
3000             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
3001                tmW.tmDigitizedAspectX, ret);
3002             ret = GetDeviceCaps(hdc, LOGPIXELSY);
3003             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
3004                tmW.tmDigitizedAspectX, ret);
3005         }
3006     }
3007
3008     /* test FF_ values */
3009     switch(tt_os2.panose.bFamilyType)
3010     {
3011     case PAN_ANY:
3012     case PAN_NO_FIT:
3013     case PAN_FAMILY_TEXT_DISPLAY:
3014     case PAN_FAMILY_PICTORIAL:
3015     default:
3016         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3017            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3018         {
3019             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3020             break;
3021         }
3022         switch(tt_os2.panose.bSerifStyle)
3023         {
3024         case PAN_ANY:
3025         case PAN_NO_FIT:
3026         default:
3027             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3028             break;
3029
3030         case PAN_SERIF_COVE:
3031         case PAN_SERIF_OBTUSE_COVE:
3032         case PAN_SERIF_SQUARE_COVE:
3033         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3034         case PAN_SERIF_SQUARE:
3035         case PAN_SERIF_THIN:
3036         case PAN_SERIF_BONE:
3037         case PAN_SERIF_EXAGGERATED:
3038         case PAN_SERIF_TRIANGLE:
3039             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
3040             break;
3041
3042         case PAN_SERIF_NORMAL_SANS:
3043         case PAN_SERIF_OBTUSE_SANS:
3044         case PAN_SERIF_PERP_SANS:
3045         case PAN_SERIF_FLARED:
3046         case PAN_SERIF_ROUNDED:
3047             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
3048             break;
3049         }
3050         break;
3051
3052     case PAN_FAMILY_SCRIPT:
3053         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
3054         break;
3055
3056     case PAN_FAMILY_DECORATIVE:
3057         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
3058         break;
3059     }
3060
3061     test_negative_width(hdc, lf);
3062
3063 end_of_test:
3064     SelectObject(hdc, hfont_old);
3065     DeleteObject(hfont);
3066
3067     ReleaseDC(0, hdc);
3068 }
3069
3070 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3071 {
3072     INT *enumed = (INT *)lParam;
3073
3074     if (type == TRUETYPE_FONTTYPE)
3075     {
3076         (*enumed)++;
3077         test_text_metrics(lf, (const NEWTEXTMETRIC *)ntm);
3078     }
3079     return 1;
3080 }
3081
3082 static void test_GetTextMetrics(void)
3083 {
3084     LOGFONTA lf;
3085     HDC hdc;
3086     INT enumed;
3087
3088     /* Report only once */
3089     if(!pGetGlyphIndicesA)
3090         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
3091
3092     hdc = GetDC(0);
3093
3094     memset(&lf, 0, sizeof(lf));
3095     lf.lfCharSet = DEFAULT_CHARSET;
3096     enumed = 0;
3097     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
3098     trace("Tested metrics of %d truetype fonts\n", enumed);
3099
3100     ReleaseDC(0, hdc);
3101 }
3102
3103 static void test_nonexistent_font(void)
3104 {
3105     static const struct
3106     {
3107         const char *name;
3108         int charset;
3109     } font_subst[] =
3110     {
3111         { "Times New Roman Baltic", 186 },
3112         { "Times New Roman CE", 238 },
3113         { "Times New Roman CYR", 204 },
3114         { "Times New Roman Greek", 161 },
3115         { "Times New Roman TUR", 162 }
3116     };
3117     LOGFONTA lf;
3118     HDC hdc;
3119     HFONT hfont;
3120     CHARSETINFO csi;
3121     INT cs, expected_cs, i;
3122     char buf[LF_FACESIZE];
3123
3124     if (!is_truetype_font_installed("Arial") ||
3125         !is_truetype_font_installed("Times New Roman"))
3126     {
3127         skip("Arial or Times New Roman not installed\n");
3128         return;
3129     }
3130
3131     expected_cs = GetACP();
3132     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
3133     {
3134         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
3135         return;
3136     }
3137     expected_cs = csi.ciCharset;
3138     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
3139
3140     hdc = GetDC(0);
3141
3142     memset(&lf, 0, sizeof(lf));
3143     lf.lfHeight = 100;
3144     lf.lfWeight = FW_REGULAR;
3145     lf.lfCharSet = ANSI_CHARSET;
3146     lf.lfPitchAndFamily = FF_SWISS;
3147     strcpy(lf.lfFaceName, "Nonexistent font");
3148     hfont = CreateFontIndirectA(&lf);
3149     hfont = SelectObject(hdc, hfont);
3150     GetTextFaceA(hdc, sizeof(buf), buf);
3151     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3152     cs = GetTextCharset(hdc);
3153     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3154     DeleteObject(SelectObject(hdc, hfont));
3155
3156     memset(&lf, 0, sizeof(lf));
3157     lf.lfHeight = -13;
3158     lf.lfWeight = FW_DONTCARE;
3159     strcpy(lf.lfFaceName, "Nonexistent font");
3160     hfont = CreateFontIndirectA(&lf);
3161     hfont = SelectObject(hdc, hfont);
3162     GetTextFaceA(hdc, sizeof(buf), buf);
3163 todo_wine /* Wine uses Arial for all substitutions */
3164     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3165        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3166        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3167        "Got %s\n", buf);
3168     cs = GetTextCharset(hdc);
3169     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3170     DeleteObject(SelectObject(hdc, hfont));
3171
3172     memset(&lf, 0, sizeof(lf));
3173     lf.lfHeight = -13;
3174     lf.lfWeight = FW_REGULAR;
3175     strcpy(lf.lfFaceName, "Nonexistent font");
3176     hfont = CreateFontIndirectA(&lf);
3177     hfont = SelectObject(hdc, hfont);
3178     GetTextFaceA(hdc, sizeof(buf), buf);
3179     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3180        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3181     cs = GetTextCharset(hdc);
3182     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3183     DeleteObject(SelectObject(hdc, hfont));
3184
3185     memset(&lf, 0, sizeof(lf));
3186     lf.lfHeight = -13;
3187     lf.lfWeight = FW_DONTCARE;
3188     strcpy(lf.lfFaceName, "Times New Roman");
3189     hfont = CreateFontIndirectA(&lf);
3190     hfont = SelectObject(hdc, hfont);
3191     GetTextFaceA(hdc, sizeof(buf), buf);
3192     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3193     cs = GetTextCharset(hdc);
3194     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3195     DeleteObject(SelectObject(hdc, hfont));
3196
3197     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3198     {
3199         memset(&lf, 0, sizeof(lf));
3200         lf.lfHeight = -13;
3201         lf.lfWeight = FW_REGULAR;
3202         strcpy(lf.lfFaceName, font_subst[i].name);
3203         hfont = CreateFontIndirectA(&lf);
3204         hfont = SelectObject(hdc, hfont);
3205         cs = GetTextCharset(hdc);
3206         if (font_subst[i].charset == expected_cs)
3207         {
3208             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3209             GetTextFaceA(hdc, sizeof(buf), buf);
3210             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3211         }
3212         else
3213         {
3214             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3215             GetTextFaceA(hdc, sizeof(buf), buf);
3216             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3217                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3218         }
3219         DeleteObject(SelectObject(hdc, hfont));
3220
3221         memset(&lf, 0, sizeof(lf));
3222         lf.lfHeight = -13;
3223         lf.lfWeight = FW_DONTCARE;
3224         strcpy(lf.lfFaceName, font_subst[i].name);
3225         hfont = CreateFontIndirectA(&lf);
3226         hfont = SelectObject(hdc, hfont);
3227         GetTextFaceA(hdc, sizeof(buf), buf);
3228         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3229            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3230            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3231            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3232            "got %s for font %s\n", buf, font_subst[i].name);
3233         cs = GetTextCharset(hdc);
3234         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3235         DeleteObject(SelectObject(hdc, hfont));
3236     }
3237
3238     ReleaseDC(0, hdc);
3239 }
3240
3241 static void test_GdiRealizationInfo(void)
3242 {
3243     HDC hdc;
3244     DWORD info[4];
3245     BOOL r;
3246     HFONT hfont, hfont_old;
3247     LOGFONTA lf;
3248
3249     if(!pGdiRealizationInfo)
3250     {
3251         win_skip("GdiRealizationInfo not available\n");
3252         return;
3253     }
3254
3255     hdc = GetDC(0);
3256
3257     memset(info, 0xcc, sizeof(info));
3258     r = pGdiRealizationInfo(hdc, info);
3259     ok(r != 0, "ret 0\n");
3260     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3261     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3262
3263     if (!is_truetype_font_installed("Arial"))
3264     {
3265         skip("skipping GdiRealizationInfo with truetype font\n");
3266         goto end;
3267     }
3268
3269     memset(&lf, 0, sizeof(lf));
3270     strcpy(lf.lfFaceName, "Arial");
3271     lf.lfHeight = 20;
3272     lf.lfWeight = FW_NORMAL;
3273     hfont = CreateFontIndirectA(&lf);
3274     hfont_old = SelectObject(hdc, hfont);
3275
3276     memset(info, 0xcc, sizeof(info));
3277     r = pGdiRealizationInfo(hdc, info);
3278     ok(r != 0, "ret 0\n");
3279     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3280     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3281
3282     DeleteObject(SelectObject(hdc, hfont_old));
3283
3284  end:
3285     ReleaseDC(0, hdc);
3286 }
3287
3288 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3289    the nul in the count of characters copied when the face name buffer is not
3290    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3291    always includes it.  */
3292 static void test_GetTextFace(void)
3293 {
3294     static const char faceA[] = "Tahoma";
3295     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3296     LOGFONTA fA = {0};
3297     LOGFONTW fW = {0};
3298     char bufA[LF_FACESIZE];
3299     WCHAR bufW[LF_FACESIZE];
3300     HFONT f, g;
3301     HDC dc;
3302     int n;
3303
3304     if(!is_font_installed("Tahoma"))
3305     {
3306         skip("Tahoma is not installed so skipping this test\n");
3307         return;
3308     }
3309
3310     /* 'A' case.  */
3311     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3312     f = CreateFontIndirectA(&fA);
3313     ok(f != NULL, "CreateFontIndirectA failed\n");
3314
3315     dc = GetDC(NULL);
3316     g = SelectObject(dc, f);
3317     n = GetTextFaceA(dc, sizeof bufA, bufA);
3318     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3319     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3320
3321     /* Play with the count arg.  */
3322     bufA[0] = 'x';
3323     n = GetTextFaceA(dc, 0, bufA);
3324     ok(n == 0, "GetTextFaceA returned %d\n", n);
3325     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3326
3327     bufA[0] = 'x';
3328     n = GetTextFaceA(dc, 1, bufA);
3329     ok(n == 0, "GetTextFaceA returned %d\n", n);
3330     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3331
3332     bufA[0] = 'x'; bufA[1] = 'y';
3333     n = GetTextFaceA(dc, 2, bufA);
3334     ok(n == 1, "GetTextFaceA returned %d\n", n);
3335     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3336
3337     n = GetTextFaceA(dc, 0, NULL);
3338     ok(n == sizeof faceA ||
3339        broken(n == 0), /* win98, winMe */
3340        "GetTextFaceA returned %d\n", n);
3341
3342     DeleteObject(SelectObject(dc, g));
3343     ReleaseDC(NULL, dc);
3344
3345     /* 'W' case.  */
3346     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3347     SetLastError(0xdeadbeef);
3348     f = CreateFontIndirectW(&fW);
3349     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3350     {
3351         win_skip("CreateFontIndirectW is not implemented\n");
3352         return;
3353     }
3354     ok(f != NULL, "CreateFontIndirectW failed\n");
3355
3356     dc = GetDC(NULL);
3357     g = SelectObject(dc, f);
3358     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3359     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3360     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3361
3362     /* Play with the count arg.  */
3363     bufW[0] = 'x';
3364     n = GetTextFaceW(dc, 0, bufW);
3365     ok(n == 0, "GetTextFaceW returned %d\n", n);
3366     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3367
3368     bufW[0] = 'x';
3369     n = GetTextFaceW(dc, 1, bufW);
3370     ok(n == 1, "GetTextFaceW returned %d\n", n);
3371     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3372
3373     bufW[0] = 'x'; bufW[1] = 'y';
3374     n = GetTextFaceW(dc, 2, bufW);
3375     ok(n == 2, "GetTextFaceW returned %d\n", n);
3376     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3377
3378     n = GetTextFaceW(dc, 0, NULL);
3379     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3380
3381     DeleteObject(SelectObject(dc, g));
3382     ReleaseDC(NULL, dc);
3383 }
3384
3385 static void test_orientation(void)
3386 {
3387     static const char test_str[11] = "Test String";
3388     HDC hdc;
3389     LOGFONTA lf;
3390     HFONT hfont, old_hfont;
3391     SIZE size;
3392
3393     if (!is_truetype_font_installed("Arial"))
3394     {
3395         skip("Arial is not installed\n");
3396         return;
3397     }
3398
3399     hdc = CreateCompatibleDC(0);
3400     memset(&lf, 0, sizeof(lf));
3401     lstrcpyA(lf.lfFaceName, "Arial");
3402     lf.lfHeight = 72;
3403     lf.lfOrientation = lf.lfEscapement = 900;
3404     hfont = create_font("orientation", &lf);
3405     old_hfont = SelectObject(hdc, hfont);
3406     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3407     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3408     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3409     SelectObject(hdc, old_hfont);
3410     DeleteObject(hfont);
3411     DeleteDC(hdc);
3412 }
3413
3414 static void test_oemcharset(void)
3415 {
3416     HDC hdc;
3417     LOGFONTA lf, clf;
3418     HFONT hfont, old_hfont;
3419     int charset;
3420
3421     hdc = CreateCompatibleDC(0);
3422     ZeroMemory(&lf, sizeof(lf));
3423     lf.lfHeight = 12;
3424     lf.lfCharSet = OEM_CHARSET;
3425     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3426     lstrcpyA(lf.lfFaceName, "Terminal");
3427     hfont = CreateFontIndirectA(&lf);
3428     old_hfont = SelectObject(hdc, hfont);
3429     charset = GetTextCharset(hdc);
3430 todo_wine
3431     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3432     hfont = SelectObject(hdc, old_hfont);
3433     GetObjectA(hfont, sizeof(clf), &clf);
3434     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3435     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3436     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3437     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3438     DeleteObject(hfont);
3439     DeleteDC(hdc);
3440 }
3441
3442 static void test_GetGlyphOutline(void)
3443 {
3444     HDC hdc;
3445     GLYPHMETRICS gm, gm2;
3446     LOGFONTA lf;
3447     HFONT hfont, old_hfont;
3448     INT ret, ret2;
3449     static const struct
3450     {
3451         UINT cs;
3452         UINT a;
3453         UINT w;
3454     } c[] =
3455     {
3456         {ANSI_CHARSET, 0x30, 0x30},
3457         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3458         {HANGEUL_CHARSET, 0x8141, 0xac02},
3459         {JOHAB_CHARSET, 0x8446, 0x3135},
3460         {GB2312_CHARSET, 0x8141, 0x4e04},
3461         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3462     };
3463     UINT i;
3464
3465     if (!is_truetype_font_installed("Tahoma"))
3466     {
3467         skip("Tahoma is not installed\n");
3468         return;
3469     }
3470
3471     hdc = CreateCompatibleDC(0);
3472     memset(&lf, 0, sizeof(lf));
3473     lf.lfHeight = 72;
3474     lstrcpyA(lf.lfFaceName, "Tahoma");
3475     SetLastError(0xdeadbeef);
3476     hfont = CreateFontIndirectA(&lf);
3477     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3478     old_hfont = SelectObject(hdc, hfont);
3479
3480     memset(&gm, 0, sizeof(gm));
3481     SetLastError(0xdeadbeef);
3482     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3483     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3484
3485     memset(&gm, 0, sizeof(gm));
3486     SetLastError(0xdeadbeef);
3487     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3488     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3489     ok(GetLastError() == 0xdeadbeef ||
3490        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3491        "expected 0xdeadbeef, got %u\n", GetLastError());
3492
3493     memset(&gm, 0, sizeof(gm));
3494     SetLastError(0xdeadbeef);
3495     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3496     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3497         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3498
3499     memset(&gm, 0, sizeof(gm));
3500     SetLastError(0xdeadbeef);
3501     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3502     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3503     {
3504        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3505        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3506     }
3507
3508     /* test for needed buffer size request on space char */
3509     memset(&gm, 0, sizeof(gm));
3510     SetLastError(0xdeadbeef);
3511     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3512     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3513         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3514
3515     /* requesting buffer size for space char + error */
3516     memset(&gm, 0, sizeof(gm));
3517     SetLastError(0xdeadbeef);
3518     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3519     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3520     {
3521        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3522        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3523     }
3524
3525     SelectObject(hdc, old_hfont);
3526     DeleteObject(hfont);
3527
3528     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3529     {
3530         lf.lfFaceName[0] = '\0';
3531         lf.lfCharSet = c[i].cs;
3532         lf.lfPitchAndFamily = 0;
3533         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3534         {
3535             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3536             continue;
3537         }
3538
3539         old_hfont = SelectObject(hdc, hfont);
3540
3541         /* expected to ignore superfluous bytes (sigle-byte character) */
3542         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3543         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3544         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3545
3546         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3547         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3548            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3549
3550         /* expected to ignore superfluous bytes (double-byte character) */
3551         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3552         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3553         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3554            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3555
3556         /* expected to match wide-char version results */
3557         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3558         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3559
3560         hfont = SelectObject(hdc, old_hfont);
3561         DeleteObject(hfont);
3562     }
3563
3564     DeleteDC(hdc);
3565 }
3566
3567 /* bug #9995: there is a limit to the character width that can be specified */
3568 static void test_GetTextMetrics2(const char *fontname, int font_height)
3569 {
3570     HFONT of, hf;
3571     HDC hdc;
3572     TEXTMETRICA tm;
3573     BOOL ret;
3574     int ave_width, height, width, ratio, scale;
3575
3576     if (!is_truetype_font_installed( fontname)) {
3577         skip("%s is not installed\n", fontname);
3578         return;
3579     }
3580     hdc = CreateCompatibleDC(0);
3581     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3582     /* select width = 0 */
3583     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3584             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3585             DEFAULT_QUALITY, VARIABLE_PITCH,
3586             fontname);
3587     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3588     of = SelectObject( hdc, hf);
3589     ret = GetTextMetricsA( hdc, &tm);
3590     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3591     height = tm.tmHeight;
3592     ave_width = tm.tmAveCharWidth;
3593     SelectObject( hdc, of);
3594     DeleteObject( hf);
3595
3596     trace("height %d, ave width %d\n", height, ave_width);
3597
3598     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3599     {
3600         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3601                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3602                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3603         ok(hf != 0, "CreateFont failed\n");
3604         of = SelectObject(hdc, hf);
3605         ret = GetTextMetrics(hdc, &tm);
3606         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3607         SelectObject(hdc, of);
3608         DeleteObject(hf);
3609
3610         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3611             break;
3612     }
3613
3614     DeleteDC(hdc);
3615
3616     ratio = width / height;
3617     scale = width / ave_width;
3618
3619     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3620           width, height, ratio, width, ave_width, scale);
3621
3622     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3623 }
3624
3625 static void test_CreateFontIndirect(void)
3626 {
3627     LOGFONTA lf, getobj_lf;
3628     int ret, i;
3629     HFONT hfont;
3630     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3631
3632     memset(&lf, 0, sizeof(lf));
3633     lf.lfCharSet = ANSI_CHARSET;
3634     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3635     lf.lfHeight = 16;
3636     lf.lfWidth = 16;
3637     lf.lfQuality = DEFAULT_QUALITY;
3638     lf.lfItalic = FALSE;
3639     lf.lfWeight = FW_DONTCARE;
3640
3641     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3642     {
3643         lstrcpyA(lf.lfFaceName, TestName[i]);
3644         hfont = CreateFontIndirectA(&lf);
3645         ok(hfont != 0, "CreateFontIndirectA failed\n");
3646         SetLastError(0xdeadbeef);
3647         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3648         ok(ret, "GetObject failed: %d\n", GetLastError());
3649         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3650         ok(lf.lfWeight == getobj_lf.lfWeight ||
3651            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3652            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3653         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3654            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3655            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3656         DeleteObject(hfont);
3657     }
3658 }
3659
3660 static void test_CreateFontIndirectEx(void)
3661 {
3662     ENUMLOGFONTEXDVA lfex;
3663     HFONT hfont;
3664
3665     if (!pCreateFontIndirectExA)
3666     {
3667         win_skip("CreateFontIndirectExA is not available\n");
3668         return;
3669     }
3670
3671     if (!is_truetype_font_installed("Arial"))
3672     {
3673         skip("Arial is not installed\n");
3674         return;
3675     }
3676
3677     SetLastError(0xdeadbeef);
3678     hfont = pCreateFontIndirectExA(NULL);
3679     ok(hfont == NULL, "got %p\n", hfont);
3680     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3681
3682     memset(&lfex, 0, sizeof(lfex));
3683     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3684     hfont = pCreateFontIndirectExA(&lfex);
3685     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3686     if (hfont)
3687         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3688     DeleteObject(hfont);
3689 }
3690
3691 static void free_font(void *font)
3692 {
3693     UnmapViewOfFile(font);
3694 }
3695
3696 static void *load_font(const char *font_name, DWORD *font_size)
3697 {
3698     char file_name[MAX_PATH];
3699     HANDLE file, mapping;
3700     void *font;
3701
3702     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3703     strcat(file_name, "\\fonts\\");
3704     strcat(file_name, font_name);
3705
3706     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3707     if (file == INVALID_HANDLE_VALUE) return NULL;
3708
3709     *font_size = GetFileSize(file, NULL);
3710
3711     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3712     if (!mapping)
3713     {
3714         CloseHandle(file);
3715         return NULL;
3716     }
3717
3718     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3719
3720     CloseHandle(file);
3721     CloseHandle(mapping);
3722     return font;
3723 }
3724
3725 static void test_AddFontMemResource(void)
3726 {
3727     void *font;
3728     DWORD font_size, num_fonts;
3729     HANDLE ret;
3730     BOOL bRet;
3731
3732     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3733     {
3734         win_skip("AddFontMemResourceEx is not available on this platform\n");
3735         return;
3736     }
3737
3738     font = load_font("sserife.fon", &font_size);
3739     if (!font)
3740     {
3741         skip("Unable to locate and load font sserife.fon\n");
3742         return;
3743     }
3744
3745     SetLastError(0xdeadbeef);
3746     ret = pAddFontMemResourceEx(NULL, 0, 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, 10, NULL, NULL);
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, 0, 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(NULL, 10, NULL, &num_fonts);
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, 0, 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     SetLastError(0xdeadbeef);
3781     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3782     ok(!ret, "AddFontMemResourceEx should fail\n");
3783     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3784        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3785        GetLastError());
3786
3787     num_fonts = 0xdeadbeef;
3788     SetLastError(0xdeadbeef);
3789     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
3790     ok(!ret, "AddFontMemResourceEx should fail\n");
3791     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3792        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3793        GetLastError());
3794     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3795
3796     if (0) /* hangs under windows 2000 */
3797     {
3798         num_fonts = 0xdeadbeef;
3799         SetLastError(0xdeadbeef);
3800         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3801         ok(!ret, "AddFontMemResourceEx should fail\n");
3802         ok(GetLastError() == 0xdeadbeef,
3803            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3804            GetLastError());
3805         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3806     }
3807
3808     num_fonts = 0xdeadbeef;
3809     SetLastError(0xdeadbeef);
3810     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3811     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3812     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3813     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3814
3815     free_font(font);
3816
3817     SetLastError(0xdeadbeef);
3818     bRet = pRemoveFontMemResourceEx(ret);
3819     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3820
3821     /* test invalid pointer to number of loaded fonts */
3822     font = load_font("sserife.fon", &font_size);
3823     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3824
3825     SetLastError(0xdeadbeef);
3826     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3827     ok(!ret, "AddFontMemResourceEx should fail\n");
3828     ok(GetLastError() == 0xdeadbeef,
3829        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3830        GetLastError());
3831
3832     SetLastError(0xdeadbeef);
3833     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3834     ok(!ret, "AddFontMemResourceEx should fail\n");
3835     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3836        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3837        GetLastError());
3838
3839     free_font(font);
3840 }
3841
3842 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3843 {
3844     LOGFONT *lf;
3845
3846     if (type != TRUETYPE_FONTTYPE) return 1;
3847
3848     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3849
3850     lf = (LOGFONT *)lparam;
3851     *lf = *elf;
3852     return 0;
3853 }
3854
3855 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3856 {
3857     int ret;
3858     LOGFONT *lf;
3859
3860     if (type != TRUETYPE_FONTTYPE) return 1;
3861
3862     lf = (LOGFONT *)lparam;
3863     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3864     if(ret == 0)
3865     {
3866         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3867         *lf = *elf;
3868         return 0;
3869     }
3870     return 1;
3871 }
3872
3873 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3874 {
3875     return lparam;
3876 }
3877
3878 static void test_EnumFonts(void)
3879 {
3880     int ret;
3881     LOGFONT lf;
3882     HDC hdc;
3883
3884     if (!is_truetype_font_installed("Arial"))
3885     {
3886         skip("Arial is not installed\n");
3887         return;
3888     }
3889
3890     /* Windows uses localized font face names, so Arial Bold won't be found */
3891     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3892     {
3893         skip("User locale is not English, skipping the test\n");
3894         return;
3895     }
3896
3897     hdc = CreateCompatibleDC(0);
3898
3899     /* check that the enumproc's retval is returned */
3900     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
3901     ok(ret == 0xcafe, "got %08x\n", ret);
3902
3903     ret = EnumFontFamilies(hdc, "Arial", enum_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     lstrcpy(lf.lfFaceName, "Arial");
3910     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3911     ok(!ret, "font Arial is not enumerated\n");
3912     ret = strcmp(lf.lfFaceName, "Arial");
3913     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3914     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3915
3916     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3917     ok(!ret, "font Arial Bold is not enumerated\n");
3918     ret = strcmp(lf.lfFaceName, "Arial");
3919     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3920     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3921
3922     lstrcpy(lf.lfFaceName, "Arial Bold");
3923     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3924     ok(ret, "font Arial Bold should not be enumerated\n");
3925
3926     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3927     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3928     ret = strcmp(lf.lfFaceName, "Arial");
3929     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3930     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3931
3932     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3933     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3934     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3935
3936     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3937     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3938
3939     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3940     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3941     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3942
3943     DeleteDC(hdc);
3944 }
3945
3946 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3947 {
3948     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3949     const char *fullname = (const char *)lParam;
3950
3951     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
3952
3953     return 1;
3954 }
3955
3956 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
3957 {
3958     HDC hdc = GetDC(0);
3959     BOOL ret = FALSE;
3960
3961     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
3962         ret = TRUE;
3963
3964     ReleaseDC(0, hdc);
3965     return ret;
3966 }
3967
3968 static void test_fullname(void)
3969 {
3970     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
3971     char buf[LF_FULLFACESIZE];
3972     HFONT hfont, of;
3973     LOGFONTA lf;
3974     HDC hdc;
3975     int i;
3976
3977     hdc = CreateCompatibleDC(0);
3978     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3979
3980     memset(&lf, 0, sizeof(lf));
3981     lf.lfCharSet = ANSI_CHARSET;
3982     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3983     lf.lfHeight = 16;
3984     lf.lfWidth = 16;
3985     lf.lfQuality = DEFAULT_QUALITY;
3986     lf.lfItalic = FALSE;
3987     lf.lfWeight = FW_DONTCARE;
3988
3989     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3990     {
3991         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
3992         {
3993             skip("%s is not installed\n", TestName[i]);
3994             continue;
3995         }
3996
3997         lstrcpyA(lf.lfFaceName, TestName[i]);
3998         hfont = CreateFontIndirectA(&lf);
3999         ok(hfont != 0, "CreateFontIndirectA failed\n");
4000
4001         of = SelectObject(hdc, hfont);
4002         buf[0] = 0;
4003         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
4004            "face full name could not be read\n");
4005         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
4006         SelectObject(hdc, of);
4007         DeleteObject(hfont);
4008     }
4009     DeleteDC(hdc);
4010 }
4011
4012 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
4013 {
4014     char tmp_path[MAX_PATH];
4015     HRSRC rsrc;
4016     void *rsrc_data;
4017     DWORD rsrc_size;
4018     HANDLE hfile;
4019     BOOL ret;
4020
4021     SetLastError(0xdeadbeef);
4022     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4023     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4024     if (!rsrc) return FALSE;
4025     SetLastError(0xdeadbeef);
4026     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4027     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4028     if (!rsrc_data) return FALSE;
4029     SetLastError(0xdeadbeef);
4030     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4031     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4032     if (!rsrc_size) return FALSE;
4033
4034     SetLastError(0xdeadbeef);
4035     ret = GetTempPath(MAX_PATH, tmp_path);
4036     ok(ret, "GetTempPath() error %d\n", GetLastError());
4037     SetLastError(0xdeadbeef);
4038     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4039     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4040
4041     SetLastError(0xdeadbeef);
4042     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4043     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4044     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4045
4046     SetLastError(0xdeadbeef);
4047     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4048     ok(ret, "WriteFile() error %d\n", GetLastError());
4049
4050     CloseHandle(hfile);
4051     return ret;
4052 }
4053
4054 static void test_CreateScalableFontResource(void)
4055 {
4056     char ttf_name[MAX_PATH];
4057     char tmp_path[MAX_PATH];
4058     char fot_name[MAX_PATH];
4059     char *file_part;
4060     DWORD ret;
4061
4062     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4063     {
4064         win_skip("AddFontResourceExA is not available on this platform\n");
4065         return;
4066     }
4067
4068     if (!write_ttf_file("wine_test.ttf", ttf_name))
4069     {
4070         skip("Failed to create ttf file for testing\n");
4071         return;
4072     }
4073
4074     trace("created %s\n", ttf_name);
4075
4076     ret = is_truetype_font_installed("wine_test");
4077     ok(!ret, "font wine_test should not be enumerated\n");
4078
4079     ret = GetTempPath(MAX_PATH, tmp_path);
4080     ok(ret, "GetTempPath() error %d\n", GetLastError());
4081     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4082     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4083
4084     ret = GetFileAttributes(fot_name);
4085     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4086
4087     SetLastError(0xdeadbeef);
4088     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4089     ok(!ret, "CreateScalableFontResource() should fail\n");
4090     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4091
4092     SetLastError(0xdeadbeef);
4093     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4094     ok(!ret, "CreateScalableFontResource() should fail\n");
4095     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4096
4097     file_part = strrchr(ttf_name, '\\');
4098     SetLastError(0xdeadbeef);
4099     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4100     ok(!ret, "CreateScalableFontResource() should fail\n");
4101     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4102
4103     SetLastError(0xdeadbeef);
4104     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4105     ok(!ret, "CreateScalableFontResource() should fail\n");
4106     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4107
4108     SetLastError(0xdeadbeef);
4109     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4110     ok(!ret, "CreateScalableFontResource() should fail\n");
4111     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4112
4113     ret = DeleteFile(fot_name);
4114     ok(ret, "DeleteFile() error %d\n", GetLastError());
4115
4116     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4117 todo_wine
4118     ok(!ret, "RemoveFontResourceEx() should fail\n");
4119
4120     /* test public font resource */
4121     SetLastError(0xdeadbeef);
4122     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4123     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4124
4125     ret = is_truetype_font_installed("wine_test");
4126     ok(!ret, "font wine_test should not be enumerated\n");
4127
4128     SetLastError(0xdeadbeef);
4129     ret = pAddFontResourceExA(fot_name, 0, 0);
4130     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4131
4132     ret = is_truetype_font_installed("wine_test");
4133     ok(ret, "font wine_test should be enumerated\n");
4134
4135     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4136 todo_wine
4137     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4138
4139     SetLastError(0xdeadbeef);
4140     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4141     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4142
4143     ret = is_truetype_font_installed("wine_test");
4144 todo_wine
4145     ok(!ret, "font wine_test should not be enumerated\n");
4146
4147     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
4148     if (ret)
4149     {
4150         /* remove once RemoveFontResource is implemented */
4151         DeleteFile(fot_name);
4152         DeleteFile(ttf_name);
4153         return;
4154     }
4155
4156     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4157     ok(!ret, "RemoveFontResourceEx() should fail\n");
4158
4159     DeleteFile(fot_name);
4160
4161     /* test hidden font resource */
4162     SetLastError(0xdeadbeef);
4163     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4164     ok(ret, "CreateScalableFontResource() 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     SetLastError(0xdeadbeef);
4170     ret = pAddFontResourceExA(fot_name, 0, 0);
4171     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4172
4173     ret = is_truetype_font_installed("wine_test");
4174     ok(!ret, "font wine_test should not be enumerated\n");
4175
4176     /* XP allows removing a private font added with 0 flags */
4177     SetLastError(0xdeadbeef);
4178     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4179     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4180
4181     ret = is_truetype_font_installed("wine_test");
4182     ok(!ret, "font wine_test should not be enumerated\n");
4183
4184     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4185     ok(!ret, "RemoveFontResourceEx() should fail\n");
4186
4187     DeleteFile(fot_name);
4188     DeleteFile(ttf_name);
4189 }
4190
4191 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4192 {
4193     LOGFONTA lf;
4194     HFONT hfont, hfont_prev;
4195     HDC hdc;
4196     char facename[100];
4197     DWORD ret;
4198     static const WCHAR str[] = { 0x2025 };
4199
4200     *installed = is_truetype_font_installed(name);
4201
4202     lf.lfHeight = -18;
4203     lf.lfWidth = 0;
4204     lf.lfEscapement = 0;
4205     lf.lfOrientation = 0;
4206     lf.lfWeight = FW_DONTCARE;
4207     lf.lfItalic = 0;
4208     lf.lfUnderline = 0;
4209     lf.lfStrikeOut = 0;
4210     lf.lfCharSet = DEFAULT_CHARSET;
4211     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4212     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4213     lf.lfQuality = DEFAULT_QUALITY;
4214     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4215     strcpy(lf.lfFaceName, name);
4216
4217     hfont = CreateFontIndirectA(&lf);
4218     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4219
4220     hdc = GetDC(NULL);
4221
4222     hfont_prev = SelectObject(hdc, hfont);
4223     ok(hfont_prev != NULL, "SelectObject failed\n");
4224
4225     ret = GetTextFaceA(hdc, sizeof facename, facename);
4226     ok(ret, "GetTextFaceA failed\n");
4227     *selected = !strcmp(facename, name);
4228
4229     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4230     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4231     if (!*selected)
4232         memset(gm, 0, sizeof *gm);
4233
4234     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4235     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4236
4237     SelectObject(hdc, hfont_prev);
4238     DeleteObject(hfont);
4239     ReleaseDC(NULL, hdc);
4240 }
4241
4242 static void test_vertical_font(void)
4243 {
4244     char ttf_name[MAX_PATH];
4245     int num;
4246     BOOL ret, installed, selected;
4247     GLYPHMETRICS gm;
4248     WORD hgi, vgi;
4249
4250     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4251     {
4252         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4253         return;
4254     }
4255
4256     if (!write_ttf_file("vertical.ttf", ttf_name))
4257     {
4258         skip("Failed to create ttf file for testing\n");
4259         return;
4260     }
4261
4262     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4263     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4264
4265     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
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 greater than gmBlackBoxY(%u) if horizontal\n",
4270        gm.gmBlackBoxX, gm.gmBlackBoxY);
4271
4272     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4273     ok(installed, "@@WineTestVertical is not installed\n");
4274     ok(selected, "@@WineTestVertical is not selected\n");
4275     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4276        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4277        gm.gmBlackBoxX, gm.gmBlackBoxY);
4278
4279     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4280
4281     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4282     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4283
4284     DeleteFile(ttf_name);
4285 }
4286
4287 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4288                                            DWORD type, LPARAM lParam)
4289 {
4290     if (lf->lfFaceName[0] == '@') {
4291         return 0;
4292     }
4293     return 1;
4294 }
4295
4296 static void test_east_asian_font_selection(void)
4297 {
4298     HDC hdc;
4299     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4300                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4301     size_t i;
4302
4303     hdc = GetDC(NULL);
4304
4305     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4306     {
4307         LOGFONTA lf;
4308         HFONT hfont;
4309         char face_name[LF_FACESIZE];
4310         int ret;
4311
4312         memset(&lf, 0, sizeof lf);
4313         lf.lfFaceName[0] = '\0';
4314         lf.lfCharSet = charset[i];
4315
4316         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4317         {
4318             skip("Vertical font for charset %u is not installed\n", charset[i]);
4319             continue;
4320         }
4321
4322         hfont = CreateFontIndirectA(&lf);
4323         hfont = SelectObject(hdc, hfont);
4324         memset(face_name, 0, sizeof face_name);
4325         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4326         ok(ret && face_name[0] != '@',
4327            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4328         DeleteObject(SelectObject(hdc, hfont));
4329
4330         memset(&lf, 0, sizeof lf);
4331         strcpy(lf.lfFaceName, "@");
4332         lf.lfCharSet = charset[i];
4333         hfont = CreateFontIndirectA(&lf);
4334         hfont = SelectObject(hdc, hfont);
4335         memset(face_name, 0, sizeof face_name);
4336         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4337         ok(ret && face_name[0] == '@',
4338            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4339         DeleteObject(SelectObject(hdc, hfont));
4340     }
4341     ReleaseDC(NULL, hdc);
4342 }
4343
4344 START_TEST(font)
4345 {
4346     init();
4347
4348     test_logfont();
4349     test_bitmap_font();
4350     test_outline_font();
4351     test_bitmap_font_metrics();
4352     test_GdiGetCharDimensions();
4353     test_GetCharABCWidths();
4354     test_text_extents();
4355     test_GetGlyphIndices();
4356     test_GetKerningPairs();
4357     test_GetOutlineTextMetrics();
4358     test_SetTextJustification();
4359     test_font_charset();
4360     test_GetFontUnicodeRanges();
4361     test_nonexistent_font();
4362     test_orientation();
4363     test_height_selection();
4364     test_AddFontMemResource();
4365     test_EnumFonts();
4366
4367     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4368      * I'd like to avoid them in this test.
4369      */
4370     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4371     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4372     if (is_truetype_font_installed("Arial Black") &&
4373         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4374     {
4375         test_EnumFontFamilies("", ANSI_CHARSET);
4376         test_EnumFontFamilies("", SYMBOL_CHARSET);
4377         test_EnumFontFamilies("", DEFAULT_CHARSET);
4378     }
4379     else
4380         skip("Arial Black or Symbol/Wingdings is not installed\n");
4381     test_EnumFontFamiliesEx_default_charset();
4382     test_GetTextMetrics();
4383     test_GdiRealizationInfo();
4384     test_GetTextFace();
4385     test_GetGlyphOutline();
4386     test_GetTextMetrics2("Tahoma", -11);
4387     test_GetTextMetrics2("Tahoma", -55);
4388     test_GetTextMetrics2("Tahoma", -110);
4389     test_GetTextMetrics2("Arial", -11);
4390     test_GetTextMetrics2("Arial", -55);
4391     test_GetTextMetrics2("Arial", -110);
4392     test_CreateFontIndirect();
4393     test_CreateFontIndirectEx();
4394     test_oemcharset();
4395     test_fullname();
4396     test_east_asian_font_selection();
4397
4398     /* These tests should be last test until RemoveFontResource
4399      * is properly implemented.
4400      */
4401     test_vertical_font();
4402     test_CreateScalableFontResource();
4403 }