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