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