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