gdi32: Enumerated font size should not be too large.
[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
2060     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2061     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2062
2063     if (type != TRUETYPE_FONTTYPE) return 1;
2064     if (0) /* Disabled to limit console spam */
2065         trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
2066               lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2067     if (efd->total < MAX_ENUM_FONTS)
2068         efd->lf[efd->total++] = *lf;
2069     else
2070         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2071
2072     return 1;
2073 }
2074
2075 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
2076 {
2077     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
2078
2079     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
2080     ok(lf->lfHeight > 0 && lf->lfHeight < 200, "enumerated font height %d\n", lf->lfHeight);
2081
2082     if (type != TRUETYPE_FONTTYPE) return 1;
2083     if (0) /* Disabled to limit console spam */
2084         trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
2085               wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
2086     if (efd->total < MAX_ENUM_FONTS)
2087         efd->lf[efd->total++] = *lf;
2088     else
2089         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2090
2091     return 1;
2092 }
2093
2094 static void get_charset_stats(struct enum_font_data *efd,
2095                               int *ansi_charset, int *symbol_charset,
2096                               int *russian_charset)
2097 {
2098     int i;
2099
2100     *ansi_charset = 0;
2101     *symbol_charset = 0;
2102     *russian_charset = 0;
2103
2104     for (i = 0; i < efd->total; i++)
2105     {
2106         switch (efd->lf[i].lfCharSet)
2107         {
2108         case ANSI_CHARSET:
2109             (*ansi_charset)++;
2110             break;
2111         case SYMBOL_CHARSET:
2112             (*symbol_charset)++;
2113             break;
2114         case RUSSIAN_CHARSET:
2115             (*russian_charset)++;
2116             break;
2117         }
2118     }
2119 }
2120
2121 static void get_charset_statsW(struct enum_font_dataW *efd,
2122                               int *ansi_charset, int *symbol_charset,
2123                               int *russian_charset)
2124 {
2125     int i;
2126
2127     *ansi_charset = 0;
2128     *symbol_charset = 0;
2129     *russian_charset = 0;
2130
2131     for (i = 0; i < efd->total; i++)
2132     {
2133         switch (efd->lf[i].lfCharSet)
2134         {
2135         case ANSI_CHARSET:
2136             (*ansi_charset)++;
2137             break;
2138         case SYMBOL_CHARSET:
2139             (*symbol_charset)++;
2140             break;
2141         case RUSSIAN_CHARSET:
2142             (*russian_charset)++;
2143             break;
2144         }
2145     }
2146 }
2147
2148 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
2149 {
2150     struct enum_font_data efd;
2151     struct enum_font_dataW efdw;
2152     LOGFONT lf;
2153     HDC hdc;
2154     int i, ret, ansi_charset, symbol_charset, russian_charset;
2155
2156     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
2157
2158     if (*font_name && !is_truetype_font_installed(font_name))
2159     {
2160         skip("%s is not installed\n", font_name);
2161         return;
2162     }
2163
2164     hdc = GetDC(0);
2165
2166     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
2167      * while EnumFontFamiliesEx doesn't.
2168      */
2169     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
2170     {
2171         /*
2172          * Use EnumFontFamiliesW since win98 crashes when the
2173          *    second parameter is NULL using EnumFontFamilies
2174          */
2175         efdw.total = 0;
2176         SetLastError(0xdeadbeef);
2177         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
2178         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
2179         if(ret)
2180         {
2181             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2182             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2183                   ansi_charset, symbol_charset, russian_charset);
2184             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2185             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2186             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2187             ok(russian_charset > 0 ||
2188                broken(russian_charset == 0), /* NT4 */
2189                "NULL family should enumerate RUSSIAN_CHARSET\n");
2190         }
2191
2192         efdw.total = 0;
2193         SetLastError(0xdeadbeef);
2194         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
2195         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
2196         if(ret)
2197         {
2198             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
2199             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
2200                   ansi_charset, symbol_charset, russian_charset);
2201             ok(efdw.total > 0, "fonts enumerated: NULL\n");
2202             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
2203             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
2204             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
2205         }
2206     }
2207
2208     efd.total = 0;
2209     SetLastError(0xdeadbeef);
2210     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
2211     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
2212     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2213     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
2214           ansi_charset, symbol_charset, russian_charset,
2215           *font_name ? font_name : "<empty>");
2216     if (*font_name)
2217         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2218     else
2219         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
2220     for (i = 0; i < efd.total; i++)
2221     {
2222 /* FIXME: remove completely once Wine is fixed */
2223 if (efd.lf[i].lfCharSet != font_charset)
2224 {
2225 todo_wine
2226     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2227 }
2228 else
2229         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2230         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2231            font_name, efd.lf[i].lfFaceName);
2232     }
2233
2234     memset(&lf, 0, sizeof(lf));
2235     lf.lfCharSet = ANSI_CHARSET;
2236     lstrcpy(lf.lfFaceName, font_name);
2237     efd.total = 0;
2238     SetLastError(0xdeadbeef);
2239     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2240     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2241     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2242     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
2243           ansi_charset, symbol_charset, russian_charset,
2244           *font_name ? font_name : "<empty>");
2245     if (font_charset == SYMBOL_CHARSET)
2246     {
2247         if (*font_name)
2248             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
2249         else
2250             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
2251     }
2252     else
2253     {
2254         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
2255         for (i = 0; i < efd.total; i++)
2256         {
2257             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2258             if (*font_name)
2259                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2260                    font_name, efd.lf[i].lfFaceName);
2261         }
2262     }
2263
2264     /* DEFAULT_CHARSET should enumerate all available charsets */
2265     memset(&lf, 0, sizeof(lf));
2266     lf.lfCharSet = DEFAULT_CHARSET;
2267     lstrcpy(lf.lfFaceName, font_name);
2268     efd.total = 0;
2269     SetLastError(0xdeadbeef);
2270     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2271     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2272     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2273     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
2274           ansi_charset, symbol_charset, russian_charset,
2275           *font_name ? font_name : "<empty>");
2276     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
2277     for (i = 0; i < efd.total; i++)
2278     {
2279         if (*font_name)
2280             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2281                font_name, efd.lf[i].lfFaceName);
2282     }
2283     if (*font_name)
2284     {
2285         switch (font_charset)
2286         {
2287         case ANSI_CHARSET:
2288             ok(ansi_charset > 0,
2289                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2290             ok(!symbol_charset,
2291                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
2292             ok(russian_charset > 0,
2293                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2294             break;
2295         case SYMBOL_CHARSET:
2296             ok(!ansi_charset,
2297                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
2298             ok(symbol_charset,
2299                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2300             ok(!russian_charset,
2301                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
2302             break;
2303         case DEFAULT_CHARSET:
2304             ok(ansi_charset > 0,
2305                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
2306             ok(symbol_charset > 0,
2307                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
2308             ok(russian_charset > 0,
2309                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
2310             break;
2311         }
2312     }
2313     else
2314     {
2315         ok(ansi_charset > 0,
2316            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2317         ok(symbol_charset > 0,
2318            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2319         ok(russian_charset > 0,
2320            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2321     }
2322
2323     memset(&lf, 0, sizeof(lf));
2324     lf.lfCharSet = SYMBOL_CHARSET;
2325     lstrcpy(lf.lfFaceName, font_name);
2326     efd.total = 0;
2327     SetLastError(0xdeadbeef);
2328     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
2329     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
2330     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
2331     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
2332           ansi_charset, symbol_charset, russian_charset,
2333           *font_name ? font_name : "<empty>");
2334     if (*font_name && font_charset == ANSI_CHARSET)
2335         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
2336     else
2337     {
2338         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
2339         for (i = 0; i < efd.total; i++)
2340         {
2341             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
2342             if (*font_name)
2343                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
2344                    font_name, efd.lf[i].lfFaceName);
2345         }
2346
2347         ok(!ansi_charset,
2348            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2349         ok(symbol_charset > 0,
2350            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2351         ok(!russian_charset,
2352            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
2353     }
2354
2355     ReleaseDC(0, hdc);
2356 }
2357
2358 static INT CALLBACK enum_font_data_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2359 {
2360     struct enum_font_data *efd = (struct enum_font_data *)lParam;
2361
2362     if (type != TRUETYPE_FONTTYPE) return 1;
2363
2364     if (efd->total < MAX_ENUM_FONTS)
2365         efd->lf[efd->total++] = *lf;
2366     else
2367         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
2368
2369     return 1;
2370 }
2371
2372 static void test_EnumFontFamiliesEx_default_charset(void)
2373 {
2374     struct enum_font_data efd;
2375     LOGFONT gui_font, enum_font;
2376     DWORD ret;
2377     HDC hdc;
2378
2379     ret = GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(gui_font), &gui_font);
2380     ok(ret, "GetObject failed.\n");
2381     if (!ret)
2382         return;
2383
2384     efd.total = 0;
2385
2386     hdc = GetDC(0);
2387     memset(&enum_font, 0, sizeof(enum_font));
2388     lstrcpy(enum_font.lfFaceName, gui_font.lfFaceName);
2389     enum_font.lfCharSet = DEFAULT_CHARSET;
2390     EnumFontFamiliesEx(hdc, &enum_font, enum_font_data_proc, (LPARAM)&efd, 0);
2391     ReleaseDC(0, hdc);
2392
2393     if (efd.total == 0) {
2394         skip("'%s' is not found or not a TrueType font.\n", gui_font.lfFaceName);
2395         return;
2396     }
2397     trace("'%s' has %d charsets.\n", gui_font.lfFaceName, efd.total);
2398
2399     ok(efd.lf[0].lfCharSet == gui_font.lfCharSet,
2400        "(%s) got charset %d expected %d\n",
2401        efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, gui_font.lfCharSet);
2402
2403     return;
2404 }
2405
2406 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
2407 {
2408     HFONT hfont, hfont_prev;
2409     DWORD ret;
2410     GLYPHMETRICS gm1, gm2;
2411     LOGFONTA lf2 = *lf;
2412     WORD idx;
2413
2414     if(!pGetGlyphIndicesA)
2415         return;
2416
2417     /* negative widths are handled just as positive ones */
2418     lf2.lfWidth = -lf->lfWidth;
2419
2420     SetLastError(0xdeadbeef);
2421     hfont = CreateFontIndirectA(lf);
2422     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2423     check_font("original", lf, hfont);
2424
2425     hfont_prev = SelectObject(hdc, hfont);
2426
2427     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
2428     if (ret == GDI_ERROR || idx == 0xffff)
2429     {
2430         SelectObject(hdc, hfont_prev);
2431         DeleteObject(hfont);
2432         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
2433         return;
2434     }
2435
2436     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
2437     memset(&gm1, 0xab, sizeof(gm1));
2438     SetLastError(0xdeadbeef);
2439     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
2440     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2441
2442     SelectObject(hdc, hfont_prev);
2443     DeleteObject(hfont);
2444
2445     SetLastError(0xdeadbeef);
2446     hfont = CreateFontIndirectA(&lf2);
2447     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2448     check_font("negative width", &lf2, hfont);
2449
2450     hfont_prev = SelectObject(hdc, hfont);
2451
2452     memset(&gm2, 0xbb, sizeof(gm2));
2453     SetLastError(0xdeadbeef);
2454     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2455     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2456
2457     SelectObject(hdc, hfont_prev);
2458     DeleteObject(hfont);
2459
2460     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2461        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2462        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2463        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2464        gm1.gmCellIncX == gm2.gmCellIncX &&
2465        gm1.gmCellIncY == gm2.gmCellIncY,
2466        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2467        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2468        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2469        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2470        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2471 }
2472
2473 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2474 #include "pshpack2.h"
2475 typedef struct
2476 {
2477     USHORT version;
2478     SHORT xAvgCharWidth;
2479     USHORT usWeightClass;
2480     USHORT usWidthClass;
2481     SHORT fsType;
2482     SHORT ySubscriptXSize;
2483     SHORT ySubscriptYSize;
2484     SHORT ySubscriptXOffset;
2485     SHORT ySubscriptYOffset;
2486     SHORT ySuperscriptXSize;
2487     SHORT ySuperscriptYSize;
2488     SHORT ySuperscriptXOffset;
2489     SHORT ySuperscriptYOffset;
2490     SHORT yStrikeoutSize;
2491     SHORT yStrikeoutPosition;
2492     SHORT sFamilyClass;
2493     PANOSE panose;
2494     ULONG ulUnicodeRange1;
2495     ULONG ulUnicodeRange2;
2496     ULONG ulUnicodeRange3;
2497     ULONG ulUnicodeRange4;
2498     CHAR achVendID[4];
2499     USHORT fsSelection;
2500     USHORT usFirstCharIndex;
2501     USHORT usLastCharIndex;
2502     /* According to the Apple spec, original version didn't have the below fields,
2503      * version numbers were taken from the OpenType spec.
2504      */
2505     /* version 0 (TrueType 1.5) */
2506     USHORT sTypoAscender;
2507     USHORT sTypoDescender;
2508     USHORT sTypoLineGap;
2509     USHORT usWinAscent;
2510     USHORT usWinDescent;
2511     /* version 1 (TrueType 1.66) */
2512     ULONG ulCodePageRange1;
2513     ULONG ulCodePageRange2;
2514     /* version 2 (OpenType 1.2) */
2515     SHORT sxHeight;
2516     SHORT sCapHeight;
2517     USHORT usDefaultChar;
2518     USHORT usBreakChar;
2519     USHORT usMaxContext;
2520 } TT_OS2_V2;
2521 #include "poppack.h"
2522
2523 #ifdef WORDS_BIGENDIAN
2524 #define GET_BE_WORD(x) (x)
2525 #define GET_BE_DWORD(x) (x)
2526 #else
2527 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2528 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2529 #endif
2530
2531 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2532                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2533                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2534 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2535 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2536 #define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
2537
2538 typedef struct
2539 {
2540     USHORT version;
2541     USHORT num_tables;
2542 } cmap_header;
2543
2544 typedef struct
2545 {
2546     USHORT plat_id;
2547     USHORT enc_id;
2548     ULONG offset;
2549 } cmap_encoding_record;
2550
2551 typedef struct
2552 {
2553     USHORT format;
2554     USHORT length;
2555     USHORT language;
2556
2557     BYTE glyph_ids[256];
2558 } cmap_format_0;
2559
2560 typedef struct
2561 {
2562     USHORT format;
2563     USHORT length;
2564     USHORT language;
2565
2566     USHORT seg_countx2;
2567     USHORT search_range;
2568     USHORT entry_selector;
2569     USHORT range_shift;
2570
2571     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2572 /* Then follows:
2573     USHORT pad;
2574     USHORT start_count[seg_countx2 / 2];
2575     USHORT id_delta[seg_countx2 / 2];
2576     USHORT id_range_offset[seg_countx2 / 2];
2577     USHORT glyph_ids[];
2578 */
2579 } cmap_format_4;
2580
2581 typedef struct
2582 {
2583     USHORT end_count;
2584     USHORT start_count;
2585     USHORT id_delta;
2586     USHORT id_range_offset;
2587 } cmap_format_4_seg;
2588
2589 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2590 {
2591     ok((tmA->tmPitchAndFamily & 0xf0) == family ||
2592        broken(PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH),
2593        "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2594        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2595        os2->panose.bWeight, os2->panose.bProportion);
2596 }
2597
2598 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2599 {
2600     int i;
2601     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2602
2603     *first = 256;
2604
2605     for(i = 0; i < 256; i++)
2606     {
2607         if(cmap->glyph_ids[i] == 0) continue;
2608         *last = i;
2609         if(*first == 256) *first = i;
2610     }
2611     if(*first == 256) return FALSE;
2612     return TRUE;
2613 }
2614
2615 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2616 {
2617     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2618     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2619     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2620     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2621     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2622 }
2623
2624 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit)
2625 {
2626     int i;
2627     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2628     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2629     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2630
2631     *first = 0x10000;
2632
2633     for(i = 0; i < seg_count; i++)
2634     {
2635         DWORD code, index;
2636         cmap_format_4_seg seg;
2637
2638         get_seg4(cmap, i, &seg);
2639         for(code = seg.start_count; code <= seg.end_count; code++)
2640         {
2641             if(seg.id_range_offset == 0)
2642                 index = (seg.id_delta + code) & 0xffff;
2643             else
2644             {
2645                 index = seg.id_range_offset / 2
2646                     + code - seg.start_count
2647                     + i - seg_count;
2648
2649                 /* some fonts have broken last segment */
2650                 if ((char *)(glyph_ids + index + 1) < (char *)ptr + limit)
2651                     index = GET_BE_WORD(glyph_ids[index]);
2652                 else
2653                 {
2654                     trace("segment %04x/%04x index %04x points to nowhere\n",
2655                           seg.start_count, seg.end_count, index);
2656                     index = 0;
2657                 }
2658                 if(index) index += seg.id_delta;
2659             }
2660             if(*first == 0x10000)
2661                 *last = *first = code;
2662             else if(index)
2663                 *last = code;
2664         }
2665     }
2666
2667     if(*first == 0x10000) return FALSE;
2668     return TRUE;
2669 }
2670
2671 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2672 {
2673     USHORT i;
2674     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2675
2676     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2677     {
2678         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2679             return (BYTE *)header + GET_BE_DWORD(record->offset);
2680         record++;
2681     }
2682     return NULL;
2683 }
2684
2685 typedef enum
2686 {
2687     cmap_none,
2688     cmap_ms_unicode,
2689     cmap_ms_symbol
2690 } cmap_type;
2691
2692 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2693 {
2694     LONG size, ret;
2695     cmap_header *header;
2696     void *cmap;
2697     BOOL r = FALSE;
2698     WORD format;
2699
2700     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2701     ok(size != GDI_ERROR, "no cmap table found\n");
2702     if(size == GDI_ERROR) return FALSE;
2703
2704     header = HeapAlloc(GetProcessHeap(), 0, size);
2705     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2706     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2707     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2708
2709     cmap = get_cmap(header, 3, 1);
2710     if(cmap)
2711         *cmap_type = cmap_ms_unicode;
2712     else
2713     {
2714         cmap = get_cmap(header, 3, 0);
2715         if(cmap) *cmap_type = cmap_ms_symbol;
2716     }
2717     if(!cmap)
2718     {
2719         *cmap_type = cmap_none;
2720         goto end;
2721     }
2722
2723     format = GET_BE_WORD(*(WORD *)cmap);
2724     switch(format)
2725     {
2726     case 0:
2727         r = get_first_last_from_cmap0(cmap, first, last);
2728         break;
2729     case 4:
2730         r = get_first_last_from_cmap4(cmap, first, last, size);
2731         break;
2732     default:
2733         trace("unhandled cmap format %d\n", format);
2734         break;
2735     }
2736
2737 end:
2738     HeapFree(GetProcessHeap(), 0, header);
2739     return r;
2740 }
2741
2742 #define TT_PLATFORM_MICROSOFT 3
2743 #define TT_MS_ID_UNICODE_CS 1
2744 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
2745 #define TT_NAME_ID_FULL_NAME 4
2746
2747 static BOOL get_ttf_nametable_entry(HDC hdc, WORD name_id, char *out_buf, SIZE_T out_size)
2748 {
2749     struct sfnt_name_header
2750     {
2751         USHORT format;
2752         USHORT number_of_record;
2753         USHORT storage_offset;
2754     } *header;
2755     struct sfnt_name
2756     {
2757         USHORT platform_id;
2758         USHORT encoding_id;
2759         USHORT language_id;
2760         USHORT name_id;
2761         USHORT length;
2762         USHORT offset;
2763     } *entry;
2764     BOOL r = FALSE;
2765     LONG size, offset, length;
2766     LONG c, ret;
2767     WCHAR *name;
2768     BYTE *data;
2769     USHORT i;
2770
2771     size = GetFontData(hdc, MS_NAME_TAG, 0, NULL, 0);
2772     ok(size != GDI_ERROR, "no name table found\n");
2773     if(size == GDI_ERROR) return FALSE;
2774
2775     data = HeapAlloc(GetProcessHeap(), 0, size);
2776     ret = GetFontData(hdc, MS_NAME_TAG, 0, data, size);
2777     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2778
2779     header = (void *)data;
2780     header->format = GET_BE_WORD(header->format);
2781     header->number_of_record = GET_BE_WORD(header->number_of_record);
2782     header->storage_offset = GET_BE_WORD(header->storage_offset);
2783     if (header->format != 0)
2784     {
2785         trace("got format %u\n", header->format);
2786         goto out;
2787     }
2788     if (header->number_of_record == 0 || sizeof(*header) + header->number_of_record * sizeof(*entry) > size)
2789     {
2790         trace("number records out of range: %d\n", header->number_of_record);
2791         goto out;
2792     }
2793     if (header->storage_offset >= size)
2794     {
2795         trace("storage_offset %u > size %u\n", header->storage_offset, size);
2796         goto out;
2797     }
2798
2799     entry = (void *)&header[1];
2800     for (i = 0; i < header->number_of_record; i++)
2801     {
2802         if (GET_BE_WORD(entry[i].platform_id) != TT_PLATFORM_MICROSOFT ||
2803             GET_BE_WORD(entry[i].encoding_id) != TT_MS_ID_UNICODE_CS ||
2804             GET_BE_WORD(entry[i].language_id) != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
2805             GET_BE_WORD(entry[i].name_id) != name_id)
2806         {
2807             continue;
2808         }
2809
2810         offset = header->storage_offset + GET_BE_WORD(entry[i].offset);
2811         length = GET_BE_WORD(entry[i].length);
2812         if (offset + length > size)
2813         {
2814             trace("entry %d is out of range\n", i);
2815             break;
2816         }
2817         if (length >= out_size)
2818         {
2819             trace("buffer too small for entry %d\n", i);
2820             break;
2821         }
2822
2823         name = (WCHAR *)(data + offset);
2824         for (c = 0; c < length / 2; c++)
2825             out_buf[c] = GET_BE_WORD(name[c]);
2826         out_buf[c] = 0;
2827
2828         r = TRUE;
2829         break;
2830     }
2831
2832 out:
2833     HeapFree(GetProcessHeap(), 0, data);
2834     return r;
2835 }
2836
2837 static void test_text_metrics(const LOGFONTA *lf)
2838 {
2839     HDC hdc;
2840     HFONT hfont, hfont_old;
2841     TEXTMETRICA tmA;
2842     TT_OS2_V2 tt_os2;
2843     LONG size, ret;
2844     const char *font_name = lf->lfFaceName;
2845     DWORD cmap_first = 0, cmap_last = 0;
2846     cmap_type cmap_type;
2847     BOOL sys_lang_non_english;
2848
2849     sys_lang_non_english = PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH;
2850     hdc = GetDC(0);
2851
2852     SetLastError(0xdeadbeef);
2853     hfont = CreateFontIndirectA(lf);
2854     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2855
2856     hfont_old = SelectObject(hdc, hfont);
2857
2858     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2859     if (size == GDI_ERROR)
2860     {
2861         trace("OS/2 chunk was not found\n");
2862         goto end_of_test;
2863     }
2864     if (size > sizeof(tt_os2))
2865     {
2866         trace("got too large OS/2 chunk of size %u\n", size);
2867         size = sizeof(tt_os2);
2868     }
2869
2870     memset(&tt_os2, 0, sizeof(tt_os2));
2871     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2872     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2873
2874     SetLastError(0xdeadbeef);
2875     ret = GetTextMetricsA(hdc, &tmA);
2876     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2877
2878     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2879     {
2880         skip("Unable to retrieve first and last glyphs from cmap\n");
2881     }
2882     else
2883     {
2884         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2885         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2886         UINT os2_first_char, os2_last_char, default_char, break_char;
2887         USHORT version;
2888         TEXTMETRICW tmW;
2889
2890         version = GET_BE_WORD(tt_os2.version);
2891
2892         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2893         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2894         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2895         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2896
2897         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2898               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2899               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2900
2901         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2902         {
2903             expect_first_W    = 0;
2904             switch(GetACP())
2905             {
2906             case 1257:  /* Baltic */
2907                 expect_last_W = 0xf8fd;
2908                 break;
2909             default:
2910                 expect_last_W = 0xf0ff;
2911             }
2912             expect_break_W    = 0x20;
2913             expect_default_W  = expect_break_W - 1;
2914             expect_first_A    = 0x1e;
2915             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2916         }
2917         else
2918         {
2919             expect_first_W    = cmap_first;
2920             expect_last_W     = min(cmap_last, os2_last_char);
2921             if(os2_first_char <= 1)
2922                 expect_break_W = os2_first_char + 2;
2923             else if(os2_first_char > 0xff)
2924                 expect_break_W = 0x20;
2925             else
2926                 expect_break_W = os2_first_char;
2927             expect_default_W  = expect_break_W - 1;
2928             expect_first_A    = expect_default_W - 1;
2929             expect_last_A     = min(expect_last_W, 0xff);
2930         }
2931         expect_break_A    = expect_break_W;
2932         expect_default_A  = expect_default_W;
2933
2934         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2935         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2936             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2937                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2938                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2939         else
2940             ok(tmA.tmFirstChar == expect_first_A ||
2941                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2942                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2943         if (pGdiGetCodePage == NULL || ! IsDBCSLeadByteEx(pGdiGetCodePage(hdc), tmA.tmLastChar))
2944             ok(tmA.tmLastChar == expect_last_A ||
2945                tmA.tmLastChar == 0xff /* win9x */,
2946                "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2947         else
2948            skip("tmLastChar is DBCS lead byte\n");
2949         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2950            font_name, tmA.tmBreakChar, expect_break_A);
2951         ok(tmA.tmDefaultChar == expect_default_A || broken(sys_lang_non_english),
2952            "A: tmDefaultChar for %s got %02x expected %02x\n",
2953            font_name, tmA.tmDefaultChar, expect_default_A);
2954
2955
2956         SetLastError(0xdeadbeef);
2957         ret = GetTextMetricsW(hdc, &tmW);
2958         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2959            "GetTextMetricsW error %u\n", GetLastError());
2960         if (ret)
2961         {
2962             /* Wine uses the os2 first char */
2963             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2964                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2965                              font_name, tmW.tmFirstChar, expect_first_W);
2966             else
2967                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2968                    font_name, tmW.tmFirstChar, expect_first_W);
2969
2970             /* Wine uses the os2 last char */
2971             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2972                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2973                              font_name, tmW.tmLastChar, expect_last_W);
2974             else
2975                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2976                    font_name, tmW.tmLastChar, expect_last_W);
2977             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2978                font_name, tmW.tmBreakChar, expect_break_W);
2979             ok(tmW.tmDefaultChar == expect_default_W || broken(sys_lang_non_english),
2980                "W: tmDefaultChar for %s got %02x expected %02x\n",
2981                font_name, tmW.tmDefaultChar, expect_default_W);
2982
2983             /* Test the aspect ratio while we have tmW */
2984             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2985             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2986                tmW.tmDigitizedAspectX, ret);
2987             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2988             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2989                tmW.tmDigitizedAspectX, ret);
2990         }
2991     }
2992
2993     /* test FF_ values */
2994     switch(tt_os2.panose.bFamilyType)
2995     {
2996     case PAN_ANY:
2997     case PAN_NO_FIT:
2998     case PAN_FAMILY_TEXT_DISPLAY:
2999     case PAN_FAMILY_PICTORIAL:
3000     default:
3001         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
3002            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
3003         {
3004             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
3005             break;
3006         }
3007         switch(tt_os2.panose.bSerifStyle)
3008         {
3009         case PAN_ANY:
3010         case PAN_NO_FIT:
3011         default:
3012             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
3013             break;
3014
3015         case PAN_SERIF_COVE:
3016         case PAN_SERIF_OBTUSE_COVE:
3017         case PAN_SERIF_SQUARE_COVE:
3018         case PAN_SERIF_OBTUSE_SQUARE_COVE:
3019         case PAN_SERIF_SQUARE:
3020         case PAN_SERIF_THIN:
3021         case PAN_SERIF_BONE:
3022         case PAN_SERIF_EXAGGERATED:
3023         case PAN_SERIF_TRIANGLE:
3024             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
3025             break;
3026
3027         case PAN_SERIF_NORMAL_SANS:
3028         case PAN_SERIF_OBTUSE_SANS:
3029         case PAN_SERIF_PERP_SANS:
3030         case PAN_SERIF_FLARED:
3031         case PAN_SERIF_ROUNDED:
3032             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
3033             break;
3034         }
3035         break;
3036
3037     case PAN_FAMILY_SCRIPT:
3038         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
3039         break;
3040
3041     case PAN_FAMILY_DECORATIVE:
3042         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
3043         break;
3044     }
3045
3046     test_negative_width(hdc, lf);
3047
3048 end_of_test:
3049     SelectObject(hdc, hfont_old);
3050     DeleteObject(hfont);
3051
3052     ReleaseDC(0, hdc);
3053 }
3054
3055 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3056 {
3057     INT *enumed = (INT *)lParam;
3058
3059     if (type == TRUETYPE_FONTTYPE)
3060     {
3061         (*enumed)++;
3062         test_text_metrics(lf);
3063     }
3064     return 1;
3065 }
3066
3067 static void test_GetTextMetrics(void)
3068 {
3069     LOGFONTA lf;
3070     HDC hdc;
3071     INT enumed;
3072
3073     /* Report only once */
3074     if(!pGetGlyphIndicesA)
3075         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
3076
3077     hdc = GetDC(0);
3078
3079     memset(&lf, 0, sizeof(lf));
3080     lf.lfCharSet = DEFAULT_CHARSET;
3081     enumed = 0;
3082     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
3083     trace("Tested metrics of %d truetype fonts\n", enumed);
3084
3085     ReleaseDC(0, hdc);
3086 }
3087
3088 static void test_nonexistent_font(void)
3089 {
3090     static const struct
3091     {
3092         const char *name;
3093         int charset;
3094     } font_subst[] =
3095     {
3096         { "Times New Roman Baltic", 186 },
3097         { "Times New Roman CE", 238 },
3098         { "Times New Roman CYR", 204 },
3099         { "Times New Roman Greek", 161 },
3100         { "Times New Roman TUR", 162 }
3101     };
3102     LOGFONTA lf;
3103     HDC hdc;
3104     HFONT hfont;
3105     CHARSETINFO csi;
3106     INT cs, expected_cs, i;
3107     char buf[LF_FACESIZE];
3108
3109     if (!is_truetype_font_installed("Arial") ||
3110         !is_truetype_font_installed("Times New Roman"))
3111     {
3112         skip("Arial or Times New Roman not installed\n");
3113         return;
3114     }
3115
3116     expected_cs = GetACP();
3117     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
3118     {
3119         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
3120         return;
3121     }
3122     expected_cs = csi.ciCharset;
3123     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
3124
3125     hdc = GetDC(0);
3126
3127     memset(&lf, 0, sizeof(lf));
3128     lf.lfHeight = 100;
3129     lf.lfWeight = FW_REGULAR;
3130     lf.lfCharSet = ANSI_CHARSET;
3131     lf.lfPitchAndFamily = FF_SWISS;
3132     strcpy(lf.lfFaceName, "Nonexistent font");
3133     hfont = CreateFontIndirectA(&lf);
3134     hfont = SelectObject(hdc, hfont);
3135     GetTextFaceA(hdc, sizeof(buf), buf);
3136     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
3137     cs = GetTextCharset(hdc);
3138     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3139     DeleteObject(SelectObject(hdc, hfont));
3140
3141     memset(&lf, 0, sizeof(lf));
3142     lf.lfHeight = -13;
3143     lf.lfWeight = FW_DONTCARE;
3144     strcpy(lf.lfFaceName, "Nonexistent font");
3145     hfont = CreateFontIndirectA(&lf);
3146     hfont = SelectObject(hdc, hfont);
3147     GetTextFaceA(hdc, sizeof(buf), buf);
3148 todo_wine /* Wine uses Arial for all substitutions */
3149     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
3150        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
3151        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3152        "Got %s\n", buf);
3153     cs = GetTextCharset(hdc);
3154     ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d\n", expected_cs, cs);
3155     DeleteObject(SelectObject(hdc, hfont));
3156
3157     memset(&lf, 0, sizeof(lf));
3158     lf.lfHeight = -13;
3159     lf.lfWeight = FW_REGULAR;
3160     strcpy(lf.lfFaceName, "Nonexistent font");
3161     hfont = CreateFontIndirectA(&lf);
3162     hfont = SelectObject(hdc, hfont);
3163     GetTextFaceA(hdc, sizeof(buf), buf);
3164     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3165        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
3166     cs = GetTextCharset(hdc);
3167     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3168     DeleteObject(SelectObject(hdc, hfont));
3169
3170     memset(&lf, 0, sizeof(lf));
3171     lf.lfHeight = -13;
3172     lf.lfWeight = FW_DONTCARE;
3173     strcpy(lf.lfFaceName, "Times New Roman");
3174     hfont = CreateFontIndirectA(&lf);
3175     hfont = SelectObject(hdc, hfont);
3176     GetTextFaceA(hdc, sizeof(buf), buf);
3177     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
3178     cs = GetTextCharset(hdc);
3179     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
3180     DeleteObject(SelectObject(hdc, hfont));
3181
3182     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
3183     {
3184         memset(&lf, 0, sizeof(lf));
3185         lf.lfHeight = -13;
3186         lf.lfWeight = FW_REGULAR;
3187         strcpy(lf.lfFaceName, font_subst[i].name);
3188         hfont = CreateFontIndirectA(&lf);
3189         hfont = SelectObject(hdc, hfont);
3190         cs = GetTextCharset(hdc);
3191         if (font_subst[i].charset == expected_cs)
3192         {
3193             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3194             GetTextFaceA(hdc, sizeof(buf), buf);
3195             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
3196         }
3197         else
3198         {
3199             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
3200             GetTextFaceA(hdc, sizeof(buf), buf);
3201             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
3202                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
3203         }
3204         DeleteObject(SelectObject(hdc, hfont));
3205
3206         memset(&lf, 0, sizeof(lf));
3207         lf.lfHeight = -13;
3208         lf.lfWeight = FW_DONTCARE;
3209         strcpy(lf.lfFaceName, font_subst[i].name);
3210         hfont = CreateFontIndirectA(&lf);
3211         hfont = SelectObject(hdc, hfont);
3212         GetTextFaceA(hdc, sizeof(buf), buf);
3213         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
3214            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
3215            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
3216            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
3217            "got %s for font %s\n", buf, font_subst[i].name);
3218         cs = GetTextCharset(hdc);
3219         ok(cs == expected_cs || cs == ANSI_CHARSET, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
3220         DeleteObject(SelectObject(hdc, hfont));
3221     }
3222
3223     ReleaseDC(0, hdc);
3224 }
3225
3226 static void test_GdiRealizationInfo(void)
3227 {
3228     HDC hdc;
3229     DWORD info[4];
3230     BOOL r;
3231     HFONT hfont, hfont_old;
3232     LOGFONTA lf;
3233
3234     if(!pGdiRealizationInfo)
3235     {
3236         win_skip("GdiRealizationInfo not available\n");
3237         return;
3238     }
3239
3240     hdc = GetDC(0);
3241
3242     memset(info, 0xcc, sizeof(info));
3243     r = pGdiRealizationInfo(hdc, info);
3244     ok(r != 0, "ret 0\n");
3245     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
3246     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3247
3248     if (!is_truetype_font_installed("Arial"))
3249     {
3250         skip("skipping GdiRealizationInfo with truetype font\n");
3251         goto end;
3252     }
3253
3254     memset(&lf, 0, sizeof(lf));
3255     strcpy(lf.lfFaceName, "Arial");
3256     lf.lfHeight = 20;
3257     lf.lfWeight = FW_NORMAL;
3258     hfont = CreateFontIndirectA(&lf);
3259     hfont_old = SelectObject(hdc, hfont);
3260
3261     memset(info, 0xcc, sizeof(info));
3262     r = pGdiRealizationInfo(hdc, info);
3263     ok(r != 0, "ret 0\n");
3264     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
3265     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
3266
3267     DeleteObject(SelectObject(hdc, hfont_old));
3268
3269  end:
3270     ReleaseDC(0, hdc);
3271 }
3272
3273 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
3274    the nul in the count of characters copied when the face name buffer is not
3275    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
3276    always includes it.  */
3277 static void test_GetTextFace(void)
3278 {
3279     static const char faceA[] = "Tahoma";
3280     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
3281     LOGFONTA fA = {0};
3282     LOGFONTW fW = {0};
3283     char bufA[LF_FACESIZE];
3284     WCHAR bufW[LF_FACESIZE];
3285     HFONT f, g;
3286     HDC dc;
3287     int n;
3288
3289     if(!is_font_installed("Tahoma"))
3290     {
3291         skip("Tahoma is not installed so skipping this test\n");
3292         return;
3293     }
3294
3295     /* 'A' case.  */
3296     memcpy(fA.lfFaceName, faceA, sizeof faceA);
3297     f = CreateFontIndirectA(&fA);
3298     ok(f != NULL, "CreateFontIndirectA failed\n");
3299
3300     dc = GetDC(NULL);
3301     g = SelectObject(dc, f);
3302     n = GetTextFaceA(dc, sizeof bufA, bufA);
3303     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
3304     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
3305
3306     /* Play with the count arg.  */
3307     bufA[0] = 'x';
3308     n = GetTextFaceA(dc, 0, bufA);
3309     ok(n == 0, "GetTextFaceA returned %d\n", n);
3310     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3311
3312     bufA[0] = 'x';
3313     n = GetTextFaceA(dc, 1, bufA);
3314     ok(n == 0, "GetTextFaceA returned %d\n", n);
3315     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
3316
3317     bufA[0] = 'x'; bufA[1] = 'y';
3318     n = GetTextFaceA(dc, 2, bufA);
3319     ok(n == 1, "GetTextFaceA returned %d\n", n);
3320     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
3321
3322     n = GetTextFaceA(dc, 0, NULL);
3323     ok(n == sizeof faceA ||
3324        broken(n == 0), /* win98, winMe */
3325        "GetTextFaceA returned %d\n", n);
3326
3327     DeleteObject(SelectObject(dc, g));
3328     ReleaseDC(NULL, dc);
3329
3330     /* 'W' case.  */
3331     memcpy(fW.lfFaceName, faceW, sizeof faceW);
3332     SetLastError(0xdeadbeef);
3333     f = CreateFontIndirectW(&fW);
3334     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3335     {
3336         win_skip("CreateFontIndirectW is not implemented\n");
3337         return;
3338     }
3339     ok(f != NULL, "CreateFontIndirectW failed\n");
3340
3341     dc = GetDC(NULL);
3342     g = SelectObject(dc, f);
3343     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
3344     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3345     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
3346
3347     /* Play with the count arg.  */
3348     bufW[0] = 'x';
3349     n = GetTextFaceW(dc, 0, bufW);
3350     ok(n == 0, "GetTextFaceW returned %d\n", n);
3351     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3352
3353     bufW[0] = 'x';
3354     n = GetTextFaceW(dc, 1, bufW);
3355     ok(n == 1, "GetTextFaceW returned %d\n", n);
3356     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
3357
3358     bufW[0] = 'x'; bufW[1] = 'y';
3359     n = GetTextFaceW(dc, 2, bufW);
3360     ok(n == 2, "GetTextFaceW returned %d\n", n);
3361     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
3362
3363     n = GetTextFaceW(dc, 0, NULL);
3364     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
3365
3366     DeleteObject(SelectObject(dc, g));
3367     ReleaseDC(NULL, dc);
3368 }
3369
3370 static void test_orientation(void)
3371 {
3372     static const char test_str[11] = "Test String";
3373     HDC hdc;
3374     LOGFONTA lf;
3375     HFONT hfont, old_hfont;
3376     SIZE size;
3377
3378     if (!is_truetype_font_installed("Arial"))
3379     {
3380         skip("Arial is not installed\n");
3381         return;
3382     }
3383
3384     hdc = CreateCompatibleDC(0);
3385     memset(&lf, 0, sizeof(lf));
3386     lstrcpyA(lf.lfFaceName, "Arial");
3387     lf.lfHeight = 72;
3388     lf.lfOrientation = lf.lfEscapement = 900;
3389     hfont = create_font("orientation", &lf);
3390     old_hfont = SelectObject(hdc, hfont);
3391     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
3392     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
3393     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
3394     SelectObject(hdc, old_hfont);
3395     DeleteObject(hfont);
3396     DeleteDC(hdc);
3397 }
3398
3399 static void test_oemcharset(void)
3400 {
3401     HDC hdc;
3402     LOGFONTA lf, clf;
3403     HFONT hfont, old_hfont;
3404     int charset;
3405
3406     hdc = CreateCompatibleDC(0);
3407     ZeroMemory(&lf, sizeof(lf));
3408     lf.lfHeight = 12;
3409     lf.lfCharSet = OEM_CHARSET;
3410     lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
3411     lstrcpyA(lf.lfFaceName, "Terminal");
3412     hfont = CreateFontIndirectA(&lf);
3413     old_hfont = SelectObject(hdc, hfont);
3414     charset = GetTextCharset(hdc);
3415 todo_wine
3416     ok(charset == OEM_CHARSET, "expected %d charset, got %d\n", OEM_CHARSET, charset);
3417     hfont = SelectObject(hdc, old_hfont);
3418     GetObjectA(hfont, sizeof(clf), &clf);
3419     ok(!lstrcmpA(clf.lfFaceName, lf.lfFaceName), "expected %s face name, got %s\n", lf.lfFaceName, clf.lfFaceName);
3420     ok(clf.lfPitchAndFamily == lf.lfPitchAndFamily, "expected %x family, got %x\n", lf.lfPitchAndFamily, clf.lfPitchAndFamily);
3421     ok(clf.lfCharSet == lf.lfCharSet, "expected %d charset, got %d\n", lf.lfCharSet, clf.lfCharSet);
3422     ok(clf.lfHeight == lf.lfHeight, "expected %d height, got %d\n", lf.lfHeight, clf.lfHeight);
3423     DeleteObject(hfont);
3424     DeleteDC(hdc);
3425 }
3426
3427 static void test_GetGlyphOutline(void)
3428 {
3429     HDC hdc;
3430     GLYPHMETRICS gm, gm2;
3431     LOGFONTA lf;
3432     HFONT hfont, old_hfont;
3433     INT ret, ret2;
3434     static const struct
3435     {
3436         UINT cs;
3437         UINT a;
3438         UINT w;
3439     } c[] =
3440     {
3441         {ANSI_CHARSET, 0x30, 0x30},
3442         {SHIFTJIS_CHARSET, 0x82a0, 0x3042},
3443         {HANGEUL_CHARSET, 0x8141, 0xac02},
3444         {JOHAB_CHARSET, 0x8446, 0x3135},
3445         {GB2312_CHARSET, 0x8141, 0x4e04},
3446         {CHINESEBIG5_CHARSET, 0xa142, 0x3001}
3447     };
3448     UINT i;
3449
3450     if (!is_truetype_font_installed("Tahoma"))
3451     {
3452         skip("Tahoma is not installed\n");
3453         return;
3454     }
3455
3456     hdc = CreateCompatibleDC(0);
3457     memset(&lf, 0, sizeof(lf));
3458     lf.lfHeight = 72;
3459     lstrcpyA(lf.lfFaceName, "Tahoma");
3460     SetLastError(0xdeadbeef);
3461     hfont = CreateFontIndirectA(&lf);
3462     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
3463     old_hfont = SelectObject(hdc, hfont);
3464
3465     memset(&gm, 0, sizeof(gm));
3466     SetLastError(0xdeadbeef);
3467     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3468     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
3469
3470     memset(&gm, 0, sizeof(gm));
3471     SetLastError(0xdeadbeef);
3472     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3473     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
3474     ok(GetLastError() == 0xdeadbeef ||
3475        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
3476        "expected 0xdeadbeef, got %u\n", GetLastError());
3477
3478     memset(&gm, 0, sizeof(gm));
3479     SetLastError(0xdeadbeef);
3480     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
3481     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3482         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
3483
3484     memset(&gm, 0, sizeof(gm));
3485     SetLastError(0xdeadbeef);
3486     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
3487     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3488     {
3489        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
3490        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3491     }
3492
3493     /* test for needed buffer size request on space char */
3494     memset(&gm, 0, sizeof(gm));
3495     SetLastError(0xdeadbeef);
3496     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
3497     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3498         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
3499
3500     /* requesting buffer size for space char + error */
3501     memset(&gm, 0, sizeof(gm));
3502     SetLastError(0xdeadbeef);
3503     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
3504     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
3505     {
3506        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
3507        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
3508     }
3509
3510     SelectObject(hdc, old_hfont);
3511     DeleteObject(hfont);
3512
3513     for (i = 0; i < sizeof c / sizeof c[0]; ++i)
3514     {
3515         lf.lfFaceName[0] = '\0';
3516         lf.lfCharSet = c[i].cs;
3517         lf.lfPitchAndFamily = 0;
3518         if (EnumFontFamiliesEx(hdc, &lf, create_font_proc, (LPARAM)&hfont, 0))
3519         {
3520             skip("TrueType font for charset %u is not installed\n", c[i].cs);
3521             continue;
3522         }
3523
3524         old_hfont = SelectObject(hdc, hfont);
3525
3526         /* expected to ignore superfluous bytes (sigle-byte character) */
3527         ret = GetGlyphOutlineA(hdc, 0x8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3528         ret2 = GetGlyphOutlineA(hdc, 0x41, GGO_BITMAP, &gm2, 0, NULL, &mat);
3529         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3530
3531         ret = GetGlyphOutlineA(hdc, 0xcc8041, GGO_BITMAP, &gm, 0, NULL, &mat);
3532         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3533            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3534
3535         /* expected to ignore superfluous bytes (double-byte character) */
3536         ret = GetGlyphOutlineA(hdc, c[i].a, GGO_BITMAP, &gm, 0, NULL, &mat);
3537         ret2 = GetGlyphOutlineA(hdc, c[i].a | 0xdead0000, GGO_BITMAP, &gm2, 0, NULL, &mat);
3538         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0,
3539            "Expected to ignore superfluous bytes, got %d %d\n", ret, ret2);
3540
3541         /* expected to match wide-char version results */
3542         ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
3543         ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
3544
3545         hfont = SelectObject(hdc, old_hfont);
3546         DeleteObject(hfont);
3547     }
3548
3549     DeleteDC(hdc);
3550 }
3551
3552 /* bug #9995: there is a limit to the character width that can be specified */
3553 static void test_GetTextMetrics2(const char *fontname, int font_height)
3554 {
3555     HFONT of, hf;
3556     HDC hdc;
3557     TEXTMETRICA tm;
3558     BOOL ret;
3559     int ave_width, height, width, ratio, scale;
3560
3561     if (!is_truetype_font_installed( fontname)) {
3562         skip("%s is not installed\n", fontname);
3563         return;
3564     }
3565     hdc = CreateCompatibleDC(0);
3566     ok( hdc != NULL, "CreateCompatibleDC failed\n");
3567     /* select width = 0 */
3568     hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3569             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3570             DEFAULT_QUALITY, VARIABLE_PITCH,
3571             fontname);
3572     ok( hf != NULL, "CreateFontA(%s, %d) failed\n", fontname, font_height);
3573     of = SelectObject( hdc, hf);
3574     ret = GetTextMetricsA( hdc, &tm);
3575     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
3576     height = tm.tmHeight;
3577     ave_width = tm.tmAveCharWidth;
3578     SelectObject( hdc, of);
3579     DeleteObject( hf);
3580
3581     trace("height %d, ave width %d\n", height, ave_width);
3582
3583     for (width = ave_width * 2; /* nothing*/; width += ave_width)
3584     {
3585         hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
3586                         DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
3587                         DEFAULT_QUALITY, VARIABLE_PITCH, fontname);
3588         ok(hf != 0, "CreateFont failed\n");
3589         of = SelectObject(hdc, hf);
3590         ret = GetTextMetrics(hdc, &tm);
3591         ok(ret, "GetTextMetrics error %u\n", GetLastError());
3592         SelectObject(hdc, of);
3593         DeleteObject(hf);
3594
3595         if (match_off_by_1(tm.tmAveCharWidth, ave_width) || width / height > 200)
3596             break;
3597     }
3598
3599     DeleteDC(hdc);
3600
3601     ratio = width / height;
3602     scale = width / ave_width;
3603
3604     trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n",
3605           width, height, ratio, width, ave_width, scale);
3606
3607     ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
3608 }
3609
3610 static void test_CreateFontIndirect(void)
3611 {
3612     LOGFONTA lf, getobj_lf;
3613     int ret, i;
3614     HFONT hfont;
3615     char TestName[][16] = {"Arial", "Arial Bold", "Arial Italic", "Arial Baltic"};
3616
3617     memset(&lf, 0, sizeof(lf));
3618     lf.lfCharSet = ANSI_CHARSET;
3619     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3620     lf.lfHeight = 16;
3621     lf.lfWidth = 16;
3622     lf.lfQuality = DEFAULT_QUALITY;
3623     lf.lfItalic = FALSE;
3624     lf.lfWeight = FW_DONTCARE;
3625
3626     for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
3627     {
3628         lstrcpyA(lf.lfFaceName, TestName[i]);
3629         hfont = CreateFontIndirectA(&lf);
3630         ok(hfont != 0, "CreateFontIndirectA failed\n");
3631         SetLastError(0xdeadbeef);
3632         ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
3633         ok(ret, "GetObject failed: %d\n", GetLastError());
3634         ok(lf.lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf.lfItalic, getobj_lf.lfItalic);
3635         ok(lf.lfWeight == getobj_lf.lfWeight ||
3636            broken((SHORT)lf.lfWeight == getobj_lf.lfWeight), /* win9x */
3637            "lfWeight: expect %08x got %08x\n", lf.lfWeight, getobj_lf.lfWeight);
3638         ok(!lstrcmpA(lf.lfFaceName, getobj_lf.lfFaceName) ||
3639            broken(!memcmp(lf.lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
3640            "font names don't match: %s != %s\n", lf.lfFaceName, getobj_lf.lfFaceName);
3641         DeleteObject(hfont);
3642     }
3643 }
3644
3645 static void test_CreateFontIndirectEx(void)
3646 {
3647     ENUMLOGFONTEXDVA lfex;
3648     HFONT hfont;
3649
3650     if (!pCreateFontIndirectExA)
3651     {
3652         win_skip("CreateFontIndirectExA is not available\n");
3653         return;
3654     }
3655
3656     if (!is_truetype_font_installed("Arial"))
3657     {
3658         skip("Arial is not installed\n");
3659         return;
3660     }
3661
3662     SetLastError(0xdeadbeef);
3663     hfont = pCreateFontIndirectExA(NULL);
3664     ok(hfont == NULL, "got %p\n", hfont);
3665     ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3666
3667     memset(&lfex, 0, sizeof(lfex));
3668     lstrcpyA(lfex.elfEnumLogfontEx.elfLogFont.lfFaceName, "Arial");
3669     hfont = pCreateFontIndirectExA(&lfex);
3670     ok(hfont != 0, "CreateFontIndirectEx failed\n");
3671     if (hfont)
3672         check_font("Arial", &lfex.elfEnumLogfontEx.elfLogFont, hfont);
3673     DeleteObject(hfont);
3674 }
3675
3676 static void free_font(void *font)
3677 {
3678     UnmapViewOfFile(font);
3679 }
3680
3681 static void *load_font(const char *font_name, DWORD *font_size)
3682 {
3683     char file_name[MAX_PATH];
3684     HANDLE file, mapping;
3685     void *font;
3686
3687     if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
3688     strcat(file_name, "\\fonts\\");
3689     strcat(file_name, font_name);
3690
3691     file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
3692     if (file == INVALID_HANDLE_VALUE) return NULL;
3693
3694     *font_size = GetFileSize(file, NULL);
3695
3696     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
3697     if (!mapping)
3698     {
3699         CloseHandle(file);
3700         return NULL;
3701     }
3702
3703     font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
3704
3705     CloseHandle(file);
3706     CloseHandle(mapping);
3707     return font;
3708 }
3709
3710 static void test_AddFontMemResource(void)
3711 {
3712     void *font;
3713     DWORD font_size, num_fonts;
3714     HANDLE ret;
3715     BOOL bRet;
3716
3717     if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
3718     {
3719         win_skip("AddFontMemResourceEx is not available on this platform\n");
3720         return;
3721     }
3722
3723     font = load_font("sserife.fon", &font_size);
3724     if (!font)
3725     {
3726         skip("Unable to locate and load font sserife.fon\n");
3727         return;
3728     }
3729
3730     SetLastError(0xdeadbeef);
3731     ret = pAddFontMemResourceEx(NULL, 0, NULL, NULL);
3732     ok(!ret, "AddFontMemResourceEx should fail\n");
3733     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3734        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3735        GetLastError());
3736
3737     SetLastError(0xdeadbeef);
3738     ret = pAddFontMemResourceEx(NULL, 10, NULL, NULL);
3739     ok(!ret, "AddFontMemResourceEx should fail\n");
3740     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3741        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3742        GetLastError());
3743
3744     SetLastError(0xdeadbeef);
3745     ret = pAddFontMemResourceEx(NULL, 0, NULL, &num_fonts);
3746     ok(!ret, "AddFontMemResourceEx should fail\n");
3747     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3748        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3749        GetLastError());
3750
3751     SetLastError(0xdeadbeef);
3752     ret = pAddFontMemResourceEx(NULL, 10, NULL, &num_fonts);
3753     ok(!ret, "AddFontMemResourceEx should fail\n");
3754     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3755        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3756        GetLastError());
3757
3758     SetLastError(0xdeadbeef);
3759     ret = pAddFontMemResourceEx(font, 0, NULL, NULL);
3760     ok(!ret, "AddFontMemResourceEx should fail\n");
3761     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3762        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3763        GetLastError());
3764
3765     SetLastError(0xdeadbeef);
3766     ret = pAddFontMemResourceEx(font, 10, NULL, NULL);
3767     ok(!ret, "AddFontMemResourceEx should fail\n");
3768     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3769        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3770        GetLastError());
3771
3772     num_fonts = 0xdeadbeef;
3773     SetLastError(0xdeadbeef);
3774     ret = pAddFontMemResourceEx(font, 0, NULL, &num_fonts);
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     ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3780
3781     if (0) /* hangs under windows 2000 */
3782     {
3783         num_fonts = 0xdeadbeef;
3784         SetLastError(0xdeadbeef);
3785         ret = pAddFontMemResourceEx(font, 10, NULL, &num_fonts);
3786         ok(!ret, "AddFontMemResourceEx should fail\n");
3787         ok(GetLastError() == 0xdeadbeef,
3788            "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3789            GetLastError());
3790         ok(num_fonts == 0xdeadbeef, "number of loaded fonts should be 0xdeadbeef\n");
3791     }
3792
3793     num_fonts = 0xdeadbeef;
3794     SetLastError(0xdeadbeef);
3795     ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
3796     ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
3797     ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
3798     ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
3799
3800     free_font(font);
3801
3802     SetLastError(0xdeadbeef);
3803     bRet = pRemoveFontMemResourceEx(ret);
3804     ok(bRet, "RemoveFontMemResourceEx error %d\n", GetLastError());
3805
3806     /* test invalid pointer to number of loaded fonts */
3807     font = load_font("sserife.fon", &font_size);
3808     ok(font != NULL, "Unable to locate and load font sserife.fon\n");
3809
3810     SetLastError(0xdeadbeef);
3811     ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
3812     ok(!ret, "AddFontMemResourceEx should fail\n");
3813     ok(GetLastError() == 0xdeadbeef,
3814        "Expected GetLastError() to return 0xdeadbeef, got %u\n",
3815        GetLastError());
3816
3817     SetLastError(0xdeadbeef);
3818     ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
3819     ok(!ret, "AddFontMemResourceEx should fail\n");
3820     ok(GetLastError() == ERROR_INVALID_PARAMETER,
3821        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
3822        GetLastError());
3823
3824     free_font(font);
3825 }
3826
3827 static INT CALLBACK enum_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3828 {
3829     LOGFONT *lf;
3830
3831     if (type != TRUETYPE_FONTTYPE) return 1;
3832
3833     ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3834
3835     lf = (LOGFONT *)lparam;
3836     *lf = *elf;
3837     return 0;
3838 }
3839
3840 static INT CALLBACK enum_all_fonts_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3841 {
3842     int ret;
3843     LOGFONT *lf;
3844
3845     if (type != TRUETYPE_FONTTYPE) return 1;
3846
3847     lf = (LOGFONT *)lparam;
3848     ret = strcmp(lf->lfFaceName, elf->lfFaceName);
3849     if(ret == 0)
3850     {
3851         ok(ntm->tmWeight == elf->lfWeight, "expected %d got %d\n", ntm->tmWeight, elf->lfWeight);
3852         *lf = *elf;
3853         return 0;
3854     }
3855     return 1;
3856 }
3857
3858 static INT CALLBACK enum_with_magic_retval_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lparam)
3859 {
3860     return lparam;
3861 }
3862
3863 static void test_EnumFonts(void)
3864 {
3865     int ret;
3866     LOGFONT lf;
3867     HDC hdc;
3868
3869     if (!is_truetype_font_installed("Arial"))
3870     {
3871         skip("Arial is not installed\n");
3872         return;
3873     }
3874
3875     /* Windows uses localized font face names, so Arial Bold won't be found */
3876     if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
3877     {
3878         skip("User locale is not English, skipping the test\n");
3879         return;
3880     }
3881
3882     hdc = CreateCompatibleDC(0);
3883
3884     /* check that the enumproc's retval is returned */
3885     ret = EnumFontFamilies(hdc, NULL, enum_with_magic_retval_proc, 0xcafe);
3886     ok(ret == 0xcafe, "got %08x\n", ret);
3887
3888     ret = EnumFontFamilies(hdc, "Arial", enum_fonts_proc, (LPARAM)&lf);
3889     ok(!ret, "font Arial is not enumerated\n");
3890     ret = strcmp(lf.lfFaceName, "Arial");
3891     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3892     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3893
3894     lstrcpy(lf.lfFaceName, "Arial");
3895     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3896     ok(!ret, "font Arial is not enumerated\n");
3897     ret = strcmp(lf.lfFaceName, "Arial");
3898     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3899     ok(lf.lfWeight == FW_NORMAL, "expected FW_NORMAL got %d\n", lf.lfWeight);
3900
3901     ret = EnumFontFamilies(hdc, "Arial Bold", enum_fonts_proc, (LPARAM)&lf);
3902     ok(!ret, "font Arial Bold is not enumerated\n");
3903     ret = strcmp(lf.lfFaceName, "Arial");
3904     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3905     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3906
3907     lstrcpy(lf.lfFaceName, "Arial Bold");
3908     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3909     ok(ret, "font Arial Bold should not be enumerated\n");
3910
3911     ret = EnumFontFamilies(hdc, "Arial Bold Italic", enum_fonts_proc, (LPARAM)&lf);
3912     ok(!ret, "font Arial Bold Italic is not enumerated\n");
3913     ret = strcmp(lf.lfFaceName, "Arial");
3914     ok(!ret, "expected Arial got %s\n", lf.lfFaceName);
3915     ok(lf.lfWeight == FW_BOLD, "expected FW_BOLD got %d\n", lf.lfWeight);
3916
3917     lstrcpy(lf.lfFaceName, "Arial Bold Italic");
3918     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3919     ok(ret, "font Arial Bold Italic should not be enumerated\n");
3920
3921     ret = EnumFontFamilies(hdc, "Arial Italic Bold", enum_fonts_proc, (LPARAM)&lf);
3922     ok(ret, "font Arial Italic Bold  should not be enumerated\n");
3923
3924     lstrcpy(lf.lfFaceName, "Arial Italic Bold");
3925     ret = EnumFontFamilies(hdc, NULL, enum_all_fonts_proc, (LPARAM)&lf);
3926     ok(ret, "font Arial Italic Bold should not be enumerated\n");
3927
3928     DeleteDC(hdc);
3929 }
3930
3931 static INT CALLBACK is_font_installed_fullname_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
3932 {
3933     const ENUMLOGFONT *elf = (const ENUMLOGFONT *)lf;
3934     const char *fullname = (const char *)lParam;
3935
3936     if (!strcmp((const char *)elf->elfFullName, fullname)) return 0;
3937
3938     return 1;
3939 }
3940
3941 static BOOL is_font_installed_fullname(const char *family, const char *fullname)
3942 {
3943     HDC hdc = GetDC(0);
3944     BOOL ret = FALSE;
3945
3946     if(!EnumFontFamiliesA(hdc, family, is_font_installed_fullname_proc, (LPARAM)fullname))
3947         ret = TRUE;
3948
3949     ReleaseDC(0, hdc);
3950     return ret;
3951 }
3952
3953 static void test_fullname(void)
3954 {
3955     static const char *TestName[] = {"Lucida Sans Demibold Roman", "Lucida Sans Italic", "Lucida Sans Regular"};
3956     char buf[LF_FULLFACESIZE];
3957     HFONT hfont, of;
3958     LOGFONTA lf;
3959     HDC hdc;
3960     int i;
3961
3962     hdc = CreateCompatibleDC(0);
3963     ok(hdc != NULL, "CreateCompatibleDC failed\n");
3964
3965     memset(&lf, 0, sizeof(lf));
3966     lf.lfCharSet = ANSI_CHARSET;
3967     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
3968     lf.lfHeight = 16;
3969     lf.lfWidth = 16;
3970     lf.lfQuality = DEFAULT_QUALITY;
3971     lf.lfItalic = FALSE;
3972     lf.lfWeight = FW_DONTCARE;
3973
3974     for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
3975     {
3976         if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
3977         {
3978             skip("%s is not installed\n", TestName[i]);
3979             continue;
3980         }
3981
3982         lstrcpyA(lf.lfFaceName, TestName[i]);
3983         hfont = CreateFontIndirectA(&lf);
3984         ok(hfont != 0, "CreateFontIndirectA failed\n");
3985
3986         of = SelectObject(hdc, hfont);
3987         buf[0] = 0;
3988         ok(get_ttf_nametable_entry(hdc, TT_NAME_ID_FULL_NAME, buf, sizeof(buf)),
3989            "face full name could not be read\n");
3990         ok(!lstrcmpA(buf, TestName[i]), "font full names don't match: %s != %s\n", TestName[i], buf);
3991         SelectObject(hdc, of);
3992         DeleteObject(hfont);
3993     }
3994     DeleteDC(hdc);
3995 }
3996
3997 static BOOL write_ttf_file(const char *fontname, char *tmp_name)
3998 {
3999     char tmp_path[MAX_PATH];
4000     HRSRC rsrc;
4001     void *rsrc_data;
4002     DWORD rsrc_size;
4003     HANDLE hfile;
4004     BOOL ret;
4005
4006     SetLastError(0xdeadbeef);
4007     rsrc = FindResource(GetModuleHandle(0), fontname, RT_RCDATA);
4008     ok(rsrc != 0, "FindResource error %d\n", GetLastError());
4009     if (!rsrc) return FALSE;
4010     SetLastError(0xdeadbeef);
4011     rsrc_data = LockResource(LoadResource(GetModuleHandle(0), rsrc));
4012     ok(rsrc_data != 0, "LockResource error %d\n", GetLastError());
4013     if (!rsrc_data) return FALSE;
4014     SetLastError(0xdeadbeef);
4015     rsrc_size = SizeofResource(GetModuleHandle(0), rsrc);
4016     ok(rsrc_size != 0, "SizeofResource error %d\n", GetLastError());
4017     if (!rsrc_size) return FALSE;
4018
4019     SetLastError(0xdeadbeef);
4020     ret = GetTempPath(MAX_PATH, tmp_path);
4021     ok(ret, "GetTempPath() error %d\n", GetLastError());
4022     SetLastError(0xdeadbeef);
4023     ret = GetTempFileName(tmp_path, "ttf", 0, tmp_name);
4024     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4025
4026     SetLastError(0xdeadbeef);
4027     hfile = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4028     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile() error %d\n", GetLastError());
4029     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
4030
4031     SetLastError(0xdeadbeef);
4032     ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
4033     ok(ret, "WriteFile() error %d\n", GetLastError());
4034
4035     CloseHandle(hfile);
4036     return ret;
4037 }
4038
4039 static void test_CreateScalableFontResource(void)
4040 {
4041     char ttf_name[MAX_PATH];
4042     char tmp_path[MAX_PATH];
4043     char fot_name[MAX_PATH];
4044     char *file_part;
4045     DWORD ret;
4046
4047     if (!pAddFontResourceExA || !pRemoveFontResourceExA)
4048     {
4049         win_skip("AddFontResourceExA is not available on this platform\n");
4050         return;
4051     }
4052
4053     if (!write_ttf_file("wine_test.ttf", ttf_name))
4054     {
4055         skip("Failed to create ttf file for testing\n");
4056         return;
4057     }
4058
4059     trace("created %s\n", ttf_name);
4060
4061     ret = is_truetype_font_installed("wine_test");
4062     ok(!ret, "font wine_test should not be enumerated\n");
4063
4064     ret = GetTempPath(MAX_PATH, tmp_path);
4065     ok(ret, "GetTempPath() error %d\n", GetLastError());
4066     ret = GetTempFileName(tmp_path, "fot", 0, fot_name);
4067     ok(ret, "GetTempFileName() error %d\n", GetLastError());
4068
4069     ret = GetFileAttributes(fot_name);
4070     ok(ret != INVALID_FILE_ATTRIBUTES, "file %s does not exist\n", fot_name);
4071
4072     SetLastError(0xdeadbeef);
4073     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4074     ok(!ret, "CreateScalableFontResource() should fail\n");
4075     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4076
4077     SetLastError(0xdeadbeef);
4078     ret = CreateScalableFontResource(0, fot_name, ttf_name, "");
4079     ok(!ret, "CreateScalableFontResource() should fail\n");
4080     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4081
4082     file_part = strrchr(ttf_name, '\\');
4083     SetLastError(0xdeadbeef);
4084     ret = CreateScalableFontResource(0, fot_name, file_part, tmp_path);
4085     ok(!ret, "CreateScalableFontResource() should fail\n");
4086     ok(GetLastError() == ERROR_FILE_EXISTS, "not expected error %d\n", GetLastError());
4087
4088     SetLastError(0xdeadbeef);
4089     ret = CreateScalableFontResource(0, fot_name, "random file name", tmp_path);
4090     ok(!ret, "CreateScalableFontResource() should fail\n");
4091     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4092
4093     SetLastError(0xdeadbeef);
4094     ret = CreateScalableFontResource(0, fot_name, NULL, ttf_name);
4095     ok(!ret, "CreateScalableFontResource() should fail\n");
4096     ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
4097
4098     ret = DeleteFile(fot_name);
4099     ok(ret, "DeleteFile() error %d\n", GetLastError());
4100
4101     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4102 todo_wine
4103     ok(!ret, "RemoveFontResourceEx() should fail\n");
4104
4105     /* test public font resource */
4106     SetLastError(0xdeadbeef);
4107     ret = CreateScalableFontResource(0, fot_name, ttf_name, NULL);
4108     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4109
4110     ret = is_truetype_font_installed("wine_test");
4111     ok(!ret, "font wine_test should not be enumerated\n");
4112
4113     SetLastError(0xdeadbeef);
4114     ret = pAddFontResourceExA(fot_name, 0, 0);
4115     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4116
4117     ret = is_truetype_font_installed("wine_test");
4118     ok(ret, "font wine_test should be enumerated\n");
4119
4120     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4121 todo_wine
4122     ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n");
4123
4124     SetLastError(0xdeadbeef);
4125     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4126     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4127
4128     ret = is_truetype_font_installed("wine_test");
4129 todo_wine
4130     ok(!ret, "font wine_test should not be enumerated\n");
4131
4132     /* FIXME: since RemoveFontResource is a stub correct testing is impossible */
4133     if (ret)
4134     {
4135         /* remove once RemoveFontResource is implemented */
4136         DeleteFile(fot_name);
4137         DeleteFile(ttf_name);
4138         return;
4139     }
4140
4141     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4142     ok(!ret, "RemoveFontResourceEx() should fail\n");
4143
4144     DeleteFile(fot_name);
4145
4146     /* test hidden font resource */
4147     SetLastError(0xdeadbeef);
4148     ret = CreateScalableFontResource(1, fot_name, ttf_name, NULL);
4149     ok(ret, "CreateScalableFontResource() error %d\n", GetLastError());
4150
4151     ret = is_truetype_font_installed("wine_test");
4152     ok(!ret, "font wine_test should not be enumerated\n");
4153
4154     SetLastError(0xdeadbeef);
4155     ret = pAddFontResourceExA(fot_name, 0, 0);
4156     ok(ret, "AddFontResourceEx() error %d\n", GetLastError());
4157
4158     ret = is_truetype_font_installed("wine_test");
4159     ok(!ret, "font wine_test should not be enumerated\n");
4160
4161     /* XP allows removing a private font added with 0 flags */
4162     SetLastError(0xdeadbeef);
4163     ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
4164     ok(ret, "RemoveFontResourceEx() 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     ret = pRemoveFontResourceExA(fot_name, 0, 0);
4170     ok(!ret, "RemoveFontResourceEx() should fail\n");
4171
4172     DeleteFile(fot_name);
4173     DeleteFile(ttf_name);
4174 }
4175
4176 static void check_vertical_font(const char *name, BOOL *installed, BOOL *selected, GLYPHMETRICS *gm, WORD *gi)
4177 {
4178     LOGFONTA lf;
4179     HFONT hfont, hfont_prev;
4180     HDC hdc;
4181     char facename[100];
4182     DWORD ret;
4183     static const WCHAR str[] = { 0x2025 };
4184
4185     *installed = is_truetype_font_installed(name);
4186
4187     lf.lfHeight = -18;
4188     lf.lfWidth = 0;
4189     lf.lfEscapement = 0;
4190     lf.lfOrientation = 0;
4191     lf.lfWeight = FW_DONTCARE;
4192     lf.lfItalic = 0;
4193     lf.lfUnderline = 0;
4194     lf.lfStrikeOut = 0;
4195     lf.lfCharSet = DEFAULT_CHARSET;
4196     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4197     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
4198     lf.lfQuality = DEFAULT_QUALITY;
4199     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
4200     strcpy(lf.lfFaceName, name);
4201
4202     hfont = CreateFontIndirectA(&lf);
4203     ok(hfont != NULL, "CreateFontIndirectA failed\n");
4204
4205     hdc = GetDC(NULL);
4206
4207     hfont_prev = SelectObject(hdc, hfont);
4208     ok(hfont_prev != NULL, "SelectObject failed\n");
4209
4210     ret = GetTextFaceA(hdc, sizeof facename, facename);
4211     ok(ret, "GetTextFaceA failed\n");
4212     *selected = !strcmp(facename, name);
4213
4214     ret = GetGlyphOutlineW(hdc, 0x2025, GGO_METRICS, gm, 0, NULL, &mat);
4215     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
4216     if (!*selected)
4217         memset(gm, 0, sizeof *gm);
4218
4219     ret = pGetGlyphIndicesW(hdc, str, 1, gi, 0);
4220     ok(ret != GDI_ERROR, "GetGlyphIndicesW failed\n");
4221
4222     SelectObject(hdc, hfont_prev);
4223     DeleteObject(hfont);
4224     ReleaseDC(NULL, hdc);
4225 }
4226
4227 static void test_vertical_font(void)
4228 {
4229     char ttf_name[MAX_PATH];
4230     int num;
4231     BOOL ret, installed, selected;
4232     GLYPHMETRICS gm;
4233     WORD hgi, vgi;
4234
4235     if (!pAddFontResourceExA || !pRemoveFontResourceExA || !pGetGlyphIndicesW)
4236     {
4237         win_skip("AddFontResourceExA or GetGlyphIndicesW is not available on this platform\n");
4238         return;
4239     }
4240
4241     if (!write_ttf_file("vertical.ttf", ttf_name))
4242     {
4243         skip("Failed to create ttf file for testing\n");
4244         return;
4245     }
4246
4247     num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0);
4248     ok(num == 2, "AddFontResourceExA should add 2 fonts from vertical.ttf\n");
4249
4250     check_vertical_font("@WineTestVertical", &installed, &selected, &gm, &hgi);
4251     ok(installed, "@WineTestVertical is not installed\n");
4252     ok(selected, "@WineTestVertical is not selected\n");
4253     ok(gm.gmBlackBoxX > gm.gmBlackBoxY,
4254        "gmBlackBoxX(%u) should be greater than gmBlackBoxY(%u) if horizontal\n",
4255        gm.gmBlackBoxX, gm.gmBlackBoxY);
4256
4257     check_vertical_font("@@WineTestVertical", &installed, &selected, &gm, &vgi);
4258     ok(installed, "@@WineTestVertical is not installed\n");
4259     ok(selected, "@@WineTestVertical is not selected\n");
4260     ok(gm.gmBlackBoxX < gm.gmBlackBoxY,
4261        "gmBlackBoxX(%u) should be less than gmBlackBoxY(%u) if vertical\n",
4262        gm.gmBlackBoxX, gm.gmBlackBoxY);
4263
4264     ok(hgi == vgi, "different glyph h:%u v:%u\n", hgi, vgi);
4265
4266     ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
4267     ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError());
4268
4269     DeleteFile(ttf_name);
4270 }
4271
4272 static INT CALLBACK has_vertical_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm,
4273                                            DWORD type, LPARAM lParam)
4274 {
4275     if (lf->lfFaceName[0] == '@') {
4276         return 0;
4277     }
4278     return 1;
4279 }
4280
4281 static void test_east_asian_font_selection(void)
4282 {
4283     HDC hdc;
4284     UINT charset[] = { SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET,
4285                        GB2312_CHARSET, CHINESEBIG5_CHARSET };
4286     size_t i;
4287
4288     hdc = GetDC(NULL);
4289
4290     for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
4291     {
4292         LOGFONTA lf;
4293         HFONT hfont;
4294         char face_name[LF_FACESIZE];
4295         int ret;
4296
4297         memset(&lf, 0, sizeof lf);
4298         lf.lfFaceName[0] = '\0';
4299         lf.lfCharSet = charset[i];
4300
4301         if (EnumFontFamiliesEx(hdc, &lf, has_vertical_font_proc, 0, 0))
4302         {
4303             skip("Vertical font for charset %u is not installed\n", charset[i]);
4304             continue;
4305         }
4306
4307         hfont = CreateFontIndirectA(&lf);
4308         hfont = SelectObject(hdc, hfont);
4309         memset(face_name, 0, sizeof face_name);
4310         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4311         ok(ret && face_name[0] != '@',
4312            "expected non-vertical face for charset %u, got %s\n", charset[i], face_name);
4313         DeleteObject(SelectObject(hdc, hfont));
4314
4315         memset(&lf, 0, sizeof lf);
4316         strcpy(lf.lfFaceName, "@");
4317         lf.lfCharSet = charset[i];
4318         hfont = CreateFontIndirectA(&lf);
4319         hfont = SelectObject(hdc, hfont);
4320         memset(face_name, 0, sizeof face_name);
4321         ret = GetTextFaceA(hdc, sizeof face_name, face_name);
4322         ok(ret && face_name[0] == '@',
4323            "expected vertical face for charset %u, got %s\n", charset[i], face_name);
4324         DeleteObject(SelectObject(hdc, hfont));
4325     }
4326     ReleaseDC(NULL, hdc);
4327 }
4328
4329 START_TEST(font)
4330 {
4331     init();
4332
4333     test_logfont();
4334     test_bitmap_font();
4335     test_outline_font();
4336     test_bitmap_font_metrics();
4337     test_GdiGetCharDimensions();
4338     test_GetCharABCWidths();
4339     test_text_extents();
4340     test_GetGlyphIndices();
4341     test_GetKerningPairs();
4342     test_GetOutlineTextMetrics();
4343     test_SetTextJustification();
4344     test_font_charset();
4345     test_GetFontUnicodeRanges();
4346     test_nonexistent_font();
4347     test_orientation();
4348     test_height_selection();
4349     test_AddFontMemResource();
4350     test_EnumFonts();
4351
4352     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
4353      * I'd like to avoid them in this test.
4354      */
4355     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
4356     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
4357     if (is_truetype_font_installed("Arial Black") &&
4358         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
4359     {
4360         test_EnumFontFamilies("", ANSI_CHARSET);
4361         test_EnumFontFamilies("", SYMBOL_CHARSET);
4362         test_EnumFontFamilies("", DEFAULT_CHARSET);
4363     }
4364     else
4365         skip("Arial Black or Symbol/Wingdings is not installed\n");
4366     test_EnumFontFamiliesEx_default_charset();
4367     test_GetTextMetrics();
4368     test_GdiRealizationInfo();
4369     test_GetTextFace();
4370     test_GetGlyphOutline();
4371     test_GetTextMetrics2("Tahoma", -11);
4372     test_GetTextMetrics2("Tahoma", -55);
4373     test_GetTextMetrics2("Tahoma", -110);
4374     test_GetTextMetrics2("Arial", -11);
4375     test_GetTextMetrics2("Arial", -55);
4376     test_GetTextMetrics2("Arial", -110);
4377     test_CreateFontIndirect();
4378     test_CreateFontIndirectEx();
4379     test_oemcharset();
4380     test_fullname();
4381     test_east_asian_font_selection();
4382
4383     /* These tests should be last test until RemoveFontResource
4384      * is properly implemented.
4385      */
4386     test_vertical_font();
4387     test_CreateScalableFontResource();
4388 }