gdi32: Set the font family as FF_MODERN if the panose marks it as monospaced.
[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 #define near_match(a, b) (abs((a) - (b)) <= 6)
34 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
35
36 LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
37 BOOL  (WINAPI *pGetCharABCWidthsI)(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPABC abc);
38 BOOL  (WINAPI *pGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
39 DWORD (WINAPI *pGetFontUnicodeRanges)(HDC hdc, LPGLYPHSET lpgs);
40 DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
41 DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
42 BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
43
44 static HMODULE hgdi32 = 0;
45
46 static void init(void)
47 {
48     hgdi32 = GetModuleHandleA("gdi32.dll");
49
50     pGdiGetCharDimensions = (void *)GetProcAddress(hgdi32, "GdiGetCharDimensions");
51     pGetCharABCWidthsI = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsI");
52     pGetCharABCWidthsW = (void *)GetProcAddress(hgdi32, "GetCharABCWidthsW");
53     pGetFontUnicodeRanges = (void *)GetProcAddress(hgdi32, "GetFontUnicodeRanges");
54     pGetGlyphIndicesA = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesA");
55     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
56     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
57 }
58
59 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
60 {
61     if (type != TRUETYPE_FONTTYPE) return 1;
62
63     return 0;
64 }
65
66 static BOOL is_truetype_font_installed(const char *name)
67 {
68     HDC hdc = GetDC(0);
69     BOOL ret = FALSE;
70
71     if (!EnumFontFamiliesA(hdc, name, is_truetype_font_installed_proc, 0))
72         ret = TRUE;
73
74     ReleaseDC(0, hdc);
75     return ret;
76 }
77
78 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
79 {
80     return 0;
81 }
82
83 static BOOL is_font_installed(const char *name)
84 {
85     HDC hdc = GetDC(0);
86     BOOL ret = FALSE;
87
88     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
89         ret = TRUE;
90
91     ReleaseDC(0, hdc);
92     return ret;
93 }
94
95 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
96 {
97     LOGFONTA getobj_lf;
98     int ret, minlen = 0;
99
100     if (!hfont)
101         return;
102
103     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
104     /* NT4 tries to be clever and only returns the minimum length */
105     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
106         minlen++;
107     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
108     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
109     ok(lf->lfHeight == getobj_lf.lfHeight ||
110        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
111        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
112     ok(lf->lfWidth == getobj_lf.lfWidth ||
113        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
114        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
115     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
116        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
117        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
118     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
119        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
120        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
121     ok(lf->lfWeight == getobj_lf.lfWeight ||
122        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
123        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
124     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
125     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
126     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
127     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
128     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
129     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
130     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
131     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
132     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
133        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
134        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
135 }
136
137 static HFONT create_font(const char* test, const LOGFONTA* lf)
138 {
139     HFONT hfont = CreateFontIndirectA(lf);
140     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
141     if (hfont)
142         check_font(test, lf, hfont);
143     return hfont;
144 }
145
146 static void test_logfont(void)
147 {
148     LOGFONTA lf;
149     HFONT hfont;
150
151     memset(&lf, 0, sizeof lf);
152
153     lf.lfCharSet = ANSI_CHARSET;
154     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
155     lf.lfWeight = FW_DONTCARE;
156     lf.lfHeight = 16;
157     lf.lfWidth = 16;
158     lf.lfQuality = DEFAULT_QUALITY;
159
160     lstrcpyA(lf.lfFaceName, "Arial");
161     hfont = create_font("Arial", &lf);
162     DeleteObject(hfont);
163
164     memset(&lf, 'A', sizeof(lf));
165     hfont = CreateFontIndirectA(&lf);
166     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
167     
168     lf.lfFaceName[LF_FACESIZE - 1] = 0;
169     check_font("AAA...", &lf, hfont);
170     DeleteObject(hfont);
171 }
172
173 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
174 {
175     if (type & RASTER_FONTTYPE)
176     {
177         LOGFONT *lf = (LOGFONT *)lParam;
178         *lf = *elf;
179         return 0; /* stop enumeration */
180     }
181
182     return 1; /* continue enumeration */
183 }
184
185 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
186 {
187     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
188     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
189     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
190     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
191     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
192     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
193     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
194     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
195     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
196     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
197     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
198     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
199     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
200     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
201     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
202     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
203     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
204     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
205     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
206     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
207 }
208
209 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
210                               LONG lfWidth, const char *test_str,
211                               INT test_str_len, const TEXTMETRICA *tm_orig,
212                               const SIZE *size_orig, INT width_of_A_orig,
213                               INT scale_x, INT scale_y)
214 {
215     LOGFONTA lf;
216     OUTLINETEXTMETRIC otm;
217     TEXTMETRICA tm;
218     SIZE size;
219     INT width_of_A, cx, cy;
220     UINT ret;
221
222     if (!hfont)
223         return;
224
225     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
226
227     GetObjectA(hfont, sizeof(lf), &lf);
228
229     if (GetOutlineTextMetricsA(hdc, 0, NULL))
230     {
231         otm.otmSize = sizeof(otm) / 2;
232         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
233         ok(ret == sizeof(otm)/2 /* XP */ ||
234            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
235
236         memset(&otm, 0x1, sizeof(otm));
237         otm.otmSize = sizeof(otm);
238         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
239         ok(ret == sizeof(otm) /* XP */ ||
240            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
241
242         memset(&tm, 0x2, sizeof(tm));
243         ret = GetTextMetricsA(hdc, &tm);
244         ok(ret, "GetTextMetricsA failed\n");
245         /* the structure size is aligned */
246         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
247         {
248             ok(0, "tm != otm\n");
249             compare_tm(&tm, &otm.otmTextMetrics);
250         }
251
252         tm = otm.otmTextMetrics;
253 if (0) /* these metrics are scaled too, but with rounding errors */
254 {
255         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
256         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
257 }
258         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
259         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
260         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
261         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
262         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
263         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
264     }
265     else
266     {
267         ret = GetTextMetricsA(hdc, &tm);
268         ok(ret, "GetTextMetricsA failed\n");
269     }
270
271     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
272     cy = tm.tmHeight / tm_orig->tmHeight;
273     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
274        lfHeight, scale_x, scale_y, cx, cy);
275     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
276     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
277     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
278     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
279     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
280
281     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
282     if (lf.lfHeight)
283     {
284         if (lf.lfWidth)
285             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
286     }
287     else
288         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
289
290     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
291
292     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
293     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
294
295     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
296
297     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);
298 }
299
300 /* Test how GDI scales bitmap font metrics */
301 static void test_bitmap_font(void)
302 {
303     static const char test_str[11] = "Test String";
304     HDC hdc;
305     LOGFONTA bitmap_lf;
306     HFONT hfont, old_hfont;
307     TEXTMETRICA tm_orig;
308     SIZE size_orig;
309     INT ret, i, width_orig, height_orig, scale, lfWidth;
310
311     hdc = GetDC(0);
312
313     /* "System" has only 1 pixel size defined, otherwise the test breaks */
314     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
315     if (ret)
316     {
317         ReleaseDC(0, hdc);
318         trace("no bitmap fonts were found, skipping the test\n");
319         return;
320     }
321
322     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
323
324     height_orig = bitmap_lf.lfHeight;
325     lfWidth = bitmap_lf.lfWidth;
326
327     hfont = create_font("bitmap", &bitmap_lf);
328     old_hfont = SelectObject(hdc, hfont);
329     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
330     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
331     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
332     SelectObject(hdc, old_hfont);
333     DeleteObject(hfont);
334
335     bitmap_lf.lfHeight = 0;
336     bitmap_lf.lfWidth = 4;
337     hfont = create_font("bitmap", &bitmap_lf);
338     old_hfont = SelectObject(hdc, hfont);
339     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
340     SelectObject(hdc, old_hfont);
341     DeleteObject(hfont);
342
343     bitmap_lf.lfHeight = height_orig;
344     bitmap_lf.lfWidth = lfWidth;
345
346     /* test fractional scaling */
347     for (i = 1; i <= height_orig * 3; i++)
348     {
349         INT nearest_height;
350
351         bitmap_lf.lfHeight = i;
352         hfont = create_font("fractional", &bitmap_lf);
353         scale = (i + height_orig - 1) / height_orig;
354         nearest_height = scale * height_orig;
355         /* XP allows not more than 10% deviation */
356         if (scale > 1 && nearest_height - i > nearest_height / 10) scale--;
357         old_hfont = SelectObject(hdc, hfont);
358         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
359         SelectObject(hdc, old_hfont);
360         DeleteObject(hfont);
361     }
362
363     /* test integer scaling 3x2 */
364     bitmap_lf.lfHeight = height_orig * 2;
365     bitmap_lf.lfWidth *= 3;
366     hfont = create_font("3x2", &bitmap_lf);
367     old_hfont = SelectObject(hdc, hfont);
368     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
369     SelectObject(hdc, old_hfont);
370     DeleteObject(hfont);
371
372     /* test integer scaling 3x3 */
373     bitmap_lf.lfHeight = height_orig * 3;
374     bitmap_lf.lfWidth = 0;
375     hfont = create_font("3x3", &bitmap_lf);
376     old_hfont = SelectObject(hdc, hfont);
377     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
378     SelectObject(hdc, old_hfont);
379     DeleteObject(hfont);
380
381     ReleaseDC(0, hdc);
382 }
383
384 /* Test how GDI scales outline font metrics */
385 static void test_outline_font(void)
386 {
387     static const char test_str[11] = "Test String";
388     HDC hdc, hdc_2;
389     LOGFONTA lf;
390     HFONT hfont, old_hfont, old_hfont_2;
391     OUTLINETEXTMETRICA otm;
392     SIZE size_orig;
393     INT width_orig, height_orig, lfWidth;
394     XFORM xform;
395     GLYPHMETRICS gm;
396     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
397     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
398     POINT pt;
399     INT ret;
400
401     if (!is_truetype_font_installed("Arial"))
402     {
403         skip("Arial is not installed\n");
404         return;
405     }
406
407     hdc = CreateCompatibleDC(0);
408
409     memset(&lf, 0, sizeof(lf));
410     strcpy(lf.lfFaceName, "Arial");
411     lf.lfHeight = 72;
412     hfont = create_font("outline", &lf);
413     old_hfont = SelectObject(hdc, hfont);
414     otm.otmSize = sizeof(otm);
415     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
416     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
417     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
418
419     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
420     SelectObject(hdc, old_hfont);
421     DeleteObject(hfont);
422
423     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
424     lf.lfHeight = otm.otmEMSquare;
425     lf.lfHeight = -lf.lfHeight;
426     hfont = create_font("outline", &lf);
427     old_hfont = SelectObject(hdc, hfont);
428     otm.otmSize = sizeof(otm);
429     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
430     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
431     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
432     SelectObject(hdc, old_hfont);
433     DeleteObject(hfont);
434
435     height_orig = otm.otmTextMetrics.tmHeight;
436     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
437
438     /* test integer scaling 3x2 */
439     lf.lfHeight = height_orig * 2;
440     lf.lfWidth = lfWidth * 3;
441     hfont = create_font("3x2", &lf);
442     old_hfont = SelectObject(hdc, hfont);
443     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
444     SelectObject(hdc, old_hfont);
445     DeleteObject(hfont);
446
447     /* test integer scaling 3x3 */
448     lf.lfHeight = height_orig * 3;
449     lf.lfWidth = lfWidth * 3;
450     hfont = create_font("3x3", &lf);
451     old_hfont = SelectObject(hdc, hfont);
452     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
453     SelectObject(hdc, old_hfont);
454     DeleteObject(hfont);
455
456     /* test integer scaling 1x1 */
457     lf.lfHeight = height_orig * 1;
458     lf.lfWidth = lfWidth * 1;
459     hfont = create_font("1x1", &lf);
460     old_hfont = SelectObject(hdc, hfont);
461     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
462     SelectObject(hdc, old_hfont);
463     DeleteObject(hfont);
464
465     /* test integer scaling 1x1 */
466     lf.lfHeight = height_orig;
467     lf.lfWidth = 0;
468     hfont = create_font("1x1", &lf);
469     old_hfont = SelectObject(hdc, hfont);
470     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
471
472     /* with an identity matrix */
473     memset(&gm, 0, sizeof(gm));
474     SetLastError(0xdeadbeef);
475     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
476     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
477     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
478     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
479     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
480     /* with a custom matrix */
481     memset(&gm, 0, sizeof(gm));
482     SetLastError(0xdeadbeef);
483     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
484     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
485     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
486     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
487     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
488
489     /* Test that changing the DC transformation affects only the font
490      * selected on this DC and doesn't affect the same font selected on
491      * another DC.
492      */
493     hdc_2 = CreateCompatibleDC(0);
494     old_hfont_2 = SelectObject(hdc_2, hfont);
495     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
496
497     SetMapMode(hdc, MM_ANISOTROPIC);
498
499     /* font metrics on another DC should be unchanged */
500     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
501
502     /* test restrictions of compatibility mode GM_COMPATIBLE */
503     /*  part 1: rescaling only X should not change font scaling on screen.
504                 So compressing the X axis by 2 is not done, and this
505                 appears as X scaling of 2 that no one requested. */
506     SetWindowExtEx(hdc, 100, 100, NULL);
507     SetViewportExtEx(hdc, 50, 100, NULL);
508     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
509     /* font metrics on another DC should be unchanged */
510     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
511
512     /*  part 2: rescaling only Y should change font scaling.
513                 As also X is scaled by a factor of 2, but this is not
514                 requested by the DC transformation, we get a scaling factor
515                 of 2 in the X coordinate. */
516     SetViewportExtEx(hdc, 100, 200, NULL);
517     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
518     /* font metrics on another DC should be unchanged */
519     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
520
521     /* restore scaling */
522     SetMapMode(hdc, MM_TEXT);
523
524     /* font metrics on another DC should be unchanged */
525     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
526
527     SelectObject(hdc_2, old_hfont_2);
528     DeleteDC(hdc_2);
529
530     if (!SetGraphicsMode(hdc, GM_ADVANCED))
531     {
532         SelectObject(hdc, old_hfont);
533         DeleteObject(hfont);
534         DeleteDC(hdc);
535         skip("GM_ADVANCED is not supported on this platform\n");
536         return;
537     }
538
539     xform.eM11 = 20.0f;
540     xform.eM12 = 0.0f;
541     xform.eM21 = 0.0f;
542     xform.eM22 = 20.0f;
543     xform.eDx = 0.0f;
544     xform.eDy = 0.0f;
545
546     SetLastError(0xdeadbeef);
547     ret = SetWorldTransform(hdc, &xform);
548     ok(ret, "SetWorldTransform error %u\n", GetLastError());
549
550     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
551
552     /* with an identity matrix */
553     memset(&gm, 0, sizeof(gm));
554     SetLastError(0xdeadbeef);
555     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
556     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
557     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
558     pt.x = width_orig; pt.y = 0;
559     LPtoDP(hdc, &pt, 1);
560     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
561     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
562     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
563     /* with a custom matrix */
564     memset(&gm, 0, sizeof(gm));
565     SetLastError(0xdeadbeef);
566     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
567     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
568     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
569     pt.x = width_orig; pt.y = 0;
570     LPtoDP(hdc, &pt, 1);
571     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
572     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
573     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
574
575     SetLastError(0xdeadbeef);
576     ret = SetMapMode(hdc, MM_LOMETRIC);
577     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
578
579     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
580
581     /* with an identity matrix */
582     memset(&gm, 0, sizeof(gm));
583     SetLastError(0xdeadbeef);
584     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
585     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
586     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
587     pt.x = width_orig; pt.y = 0;
588     LPtoDP(hdc, &pt, 1);
589     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
590     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
591     /* with a custom matrix */
592     memset(&gm, 0, sizeof(gm));
593     SetLastError(0xdeadbeef);
594     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
595     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
596     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
597     pt.x = width_orig; pt.y = 0;
598     LPtoDP(hdc, &pt, 1);
599     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
600     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
601
602     SetLastError(0xdeadbeef);
603     ret = SetMapMode(hdc, MM_TEXT);
604     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
605
606     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
607
608     /* with an identity matrix */
609     memset(&gm, 0, sizeof(gm));
610     SetLastError(0xdeadbeef);
611     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
612     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
613     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
614     pt.x = width_orig; pt.y = 0;
615     LPtoDP(hdc, &pt, 1);
616     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
617     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
618     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
619     /* with a custom matrix */
620     memset(&gm, 0, sizeof(gm));
621     SetLastError(0xdeadbeef);
622     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
623     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
624     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
625     pt.x = width_orig; pt.y = 0;
626     LPtoDP(hdc, &pt, 1);
627     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
628     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
629     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
630
631     SelectObject(hdc, old_hfont);
632     DeleteObject(hfont);
633     DeleteDC(hdc);
634 }
635
636 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
637 {
638     LOGFONT *lf = (LOGFONT *)lParam;
639
640     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
641     {
642         *lf = *elf;
643         return 0; /* stop enumeration */
644     }
645     return 1; /* continue enumeration */
646 }
647
648 static void test_bitmap_font_metrics(void)
649 {
650     static const struct font_data
651     {
652         const char face_name[LF_FACESIZE];
653         int weight, height, ascent, descent, int_leading, ext_leading;
654         int ave_char_width, max_char_width;
655         DWORD ansi_bitfield;
656     } fd[] =
657     {
658         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
659         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
660         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, FS_LATIN1 | FS_CYRILLIC },
661         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, FS_LATIN2 },
662         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, FS_LATIN1 },
663         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, FS_LATIN2 },
664         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, FS_CYRILLIC },
665         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, FS_LATIN1 },
666         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, FS_LATIN2 },
667         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, FS_CYRILLIC },
668         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
669         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, FS_LATIN1 | FS_LATIN2 },
670         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, FS_CYRILLIC },
671         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
672         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, FS_LATIN1 },
673         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, FS_LATIN2 | FS_CYRILLIC },
674         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, FS_LATIN1 | FS_LATIN2 },
675         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, FS_CYRILLIC },
676         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, FS_LATIN1 | FS_LATIN2 },
677         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, FS_CYRILLIC },
678         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, FS_LATIN1 },
679         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, FS_LATIN2 },
680         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, FS_CYRILLIC },
681         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, FS_LATIN1 },
682         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, FS_LATIN2 },
683         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, FS_CYRILLIC },
684         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, FS_LATIN1 | FS_LATIN2 },
685         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, FS_CYRILLIC },
686         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
687         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
688         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
689         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, FS_LATIN1 },
690         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, FS_LATIN2 | FS_CYRILLIC },
691 /*
692  * TODO:  the system for CP932 should be NORMAL, not BOLD.  However that would
693  *        require a new system.sfd for that font
694  */
695         { "System", FW_BOLD, 18, 16, 2, 0, 2, 8, 16, FS_JISJAPAN },
696         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, FS_LATIN1 },
697         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, FS_LATIN2 | FS_CYRILLIC },
698         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, FS_JISJAPAN },
699         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, FS_LATIN1 },
700         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, FS_LATIN2 | FS_CYRILLIC },
701         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, FS_JISJAPAN },
702         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, FS_LATIN1 },
703         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, FS_LATIN2 | FS_CYRILLIC },
704         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, FS_JISJAPAN },
705         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, FS_LATIN1 },
706         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, FS_LATIN2 | FS_CYRILLIC },
707         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, FS_JISJAPAN },
708         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, FS_LATIN1 | FS_LATIN2 },
709         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, FS_CYRILLIC },
710         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, FS_JISJAPAN },
711         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
712         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, FS_JISJAPAN },
713         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, FS_LATIN1 | FS_LATIN2 },
714         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, FS_CYRILLIC },
715         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, FS_JISJAPAN }
716
717         /* FIXME: add "Terminal" */
718     };
719     HDC hdc;
720     LOGFONT lf;
721     HFONT hfont, old_hfont;
722     TEXTMETRIC tm;
723     INT ret, i;
724
725     hdc = CreateCompatibleDC(0);
726     assert(hdc);
727
728     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
729     {
730         int bit;
731
732         memset(&lf, 0, sizeof(lf));
733
734         lf.lfHeight = fd[i].height;
735         strcpy(lf.lfFaceName, fd[i].face_name);
736
737         for(bit = 0; bit < 32; bit++)
738         {
739             DWORD fs[2];
740             CHARSETINFO csi;
741
742             fs[0] = 1L << bit;
743             fs[1] = 0;
744             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
745             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
746
747             lf.lfCharSet = csi.ciCharset;
748             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
749             if (ret) continue;
750
751             trace("found font %s, height %d charset %x\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet);
752
753             hfont = create_font(lf.lfFaceName, &lf);
754             old_hfont = SelectObject(hdc, hfont);
755             ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %d\n", GetLastError());
756
757             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);
758             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);
759             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);
760             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);
761             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);
762             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);
763             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);
764
765             /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
766                that make the max width bigger */
767             if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
768                 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);
769
770             SelectObject(hdc, old_hfont);
771             DeleteObject(hfont);
772         }
773     }
774
775     DeleteDC(hdc);
776 }
777
778 static void test_GdiGetCharDimensions(void)
779 {
780     HDC hdc;
781     TEXTMETRICW tm;
782     LONG ret;
783     SIZE size;
784     LONG avgwidth, height;
785     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
786
787     if (!pGdiGetCharDimensions)
788     {
789         skip("GdiGetCharDimensions not available on this platform\n");
790         return;
791     }
792
793     hdc = CreateCompatibleDC(NULL);
794
795     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
796     avgwidth = ((size.cx / 26) + 1) / 2;
797
798     ret = pGdiGetCharDimensions(hdc, &tm, &height);
799     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
800     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
801
802     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
803     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
804
805     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
806     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
807
808     height = 0;
809     ret = pGdiGetCharDimensions(hdc, NULL, &height);
810     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
811     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
812
813     DeleteDC(hdc);
814 }
815
816 static void test_GetCharABCWidths(void)
817 {
818     static const WCHAR str[] = {'a',0};
819     BOOL ret;
820     HDC hdc;
821     LOGFONTA lf;
822     HFONT hfont;
823     ABC abc[1];
824     WORD glyphs[1];
825     DWORD nb;
826
827     if (!pGetCharABCWidthsW || !pGetCharABCWidthsI)
828     {
829         skip("GetCharABCWidthsW/I not available on this platform\n");
830         return;
831     }
832
833     memset(&lf, 0, sizeof(lf));
834     strcpy(lf.lfFaceName, "System");
835     lf.lfHeight = 20;
836
837     hfont = CreateFontIndirectA(&lf);
838     hdc = GetDC(0);
839     hfont = SelectObject(hdc, hfont);
840
841     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
842     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
843
844     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
845     ok(!ret, "GetCharABCWidthsI should have failed\n");
846
847     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
848     ok(!ret, "GetCharABCWidthsI should have failed\n");
849
850     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
851     ok(ret, "GetCharABCWidthsI should have succeeded\n");
852
853     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
854     ok(!ret, "GetCharABCWidthsW should have failed\n");
855
856     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
857     ok(!ret, "GetCharABCWidthsW should have failed\n");
858
859     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
860     ok(!ret, "GetCharABCWidthsW should have failed\n");
861
862     hfont = SelectObject(hdc, hfont);
863     DeleteObject(hfont);
864     ReleaseDC(NULL, hdc);
865 }
866
867 static void test_text_extents(void)
868 {
869     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
870     LPINT extents;
871     INT i, len, fit1, fit2;
872     LOGFONTA lf;
873     TEXTMETRICA tm;
874     HDC hdc;
875     HFONT hfont;
876     SIZE sz;
877     SIZE sz1, sz2;
878
879     memset(&lf, 0, sizeof(lf));
880     strcpy(lf.lfFaceName, "Arial");
881     lf.lfHeight = 20;
882
883     hfont = CreateFontIndirectA(&lf);
884     hdc = GetDC(0);
885     hfont = SelectObject(hdc, hfont);
886     GetTextMetricsA(hdc, &tm);
887     GetTextExtentPointA(hdc, "o", 1, &sz);
888     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
889
890     SetLastError(0xdeadbeef);
891     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
892     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
893     {
894         skip("Skipping remainder of text extents test on a Win9x platform\n");
895         hfont = SelectObject(hdc, hfont);
896         DeleteObject(hfont);
897         ReleaseDC(0, hdc);
898         return;
899     }
900
901     len = lstrlenW(wt);
902     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
903     extents[0] = 1;         /* So that the increasing sequence test will fail
904                                if the extents array is untouched.  */
905     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
906     GetTextExtentPointW(hdc, wt, len, &sz2);
907     ok(sz1.cy == sz2.cy,
908        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
909     /* Because of the '\n' in the string GetTextExtentExPoint and
910        GetTextExtentPoint return different widths under Win2k, but
911        under WinXP they return the same width.  So we don't test that
912        here. */
913
914     for (i = 1; i < len; ++i)
915         ok(extents[i-1] <= extents[i],
916            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
917            i);
918     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
919     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
920     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
921     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
922     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
923     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
924     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
925     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
926     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
927     ok(extents[0] == extents[2] && extents[1] == extents[3],
928        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
929     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
930     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
931        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
932     HeapFree(GetProcessHeap(), 0, extents);
933
934     hfont = SelectObject(hdc, hfont);
935     DeleteObject(hfont);
936     ReleaseDC(NULL, hdc);
937 }
938
939 static void test_GetGlyphIndices(void)
940 {
941     HDC      hdc;
942     HFONT    hfont;
943     DWORD    charcount;
944     LOGFONTA lf;
945     DWORD    flags = 0;
946     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
947     WORD     glyphs[(sizeof(testtext)/2)-1];
948     TEXTMETRIC textm;
949     HFONT hOldFont;
950
951     if (!pGetGlyphIndicesW) {
952         skip("GetGlyphIndicesW not available on platform\n");
953         return;
954     }
955
956     hdc = GetDC(0);
957
958     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
959     flags |= GGI_MARK_NONEXISTING_GLYPHS;
960     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
961     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
962     ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
963     flags = 0;
964     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
965     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
966     ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
967                     textm.tmDefaultChar, glyphs[4]);
968
969     if(!is_font_installed("Tahoma"))
970     {
971         skip("Tahoma is not installed so skipping this test\n");
972         return;
973     }
974     memset(&lf, 0, sizeof(lf));
975     strcpy(lf.lfFaceName, "Tahoma");
976     lf.lfHeight = 20;
977
978     hfont = CreateFontIndirectA(&lf);
979     hOldFont = SelectObject(hdc, hfont);
980     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
981     flags |= GGI_MARK_NONEXISTING_GLYPHS;
982     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
983     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
984     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
985     flags = 0;
986     testtext[0] = textm.tmDefaultChar;
987     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
988     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
989     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
990     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
991     DeleteObject(SelectObject(hdc, hOldFont));
992 }
993
994 static void test_GetKerningPairs(void)
995 {
996     static const struct kerning_data
997     {
998         const char face_name[LF_FACESIZE];
999         LONG height;
1000         /* some interesting fields from OUTLINETEXTMETRIC */
1001         LONG tmHeight, tmAscent, tmDescent;
1002         UINT otmEMSquare;
1003         INT  otmAscent;
1004         INT  otmDescent;
1005         UINT otmLineGap;
1006         UINT otmsCapEmHeight;
1007         UINT otmsXHeight;
1008         INT  otmMacAscent;
1009         INT  otmMacDescent;
1010         UINT otmMacLineGap;
1011         UINT otmusMinimumPPEM;
1012         /* small subset of kerning pairs to test */
1013         DWORD total_kern_pairs;
1014         const KERNINGPAIR kern_pair[26];
1015     } kd[] =
1016     {
1017         {"Arial", 12, 12, 9, 3,
1018                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1019                   26,
1020             {
1021                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1022                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1023                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1024                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1025                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1026                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1027                 {933,970,+1},{933,972,-1}
1028                 }
1029         },
1030         {"Arial", -34, 39, 32, 7,
1031                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1032                   26,
1033             {
1034                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1035                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1036                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1037                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1038                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1039                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1040                 {933,970,+2},{933,972,-3}
1041             }
1042         },
1043         { "Arial", 120, 120, 97, 23,
1044                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1045                    26,
1046             {
1047                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1048                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1049                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1050                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1051                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1052                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1053                 {933,970,+6},{933,972,-10}
1054             }
1055         },
1056 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1057         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1058                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1059                    26,
1060             {
1061                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1062                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1063                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1064                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1065                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1066                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1067                 {933,970,+54},{933,972,-83}
1068             }
1069         }
1070 #endif
1071     };
1072     LOGFONT lf;
1073     HFONT hfont, hfont_old;
1074     KERNINGPAIR *kern_pair;
1075     HDC hdc;
1076     DWORD total_kern_pairs, ret, i, n, matches;
1077
1078     hdc = GetDC(0);
1079
1080     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1081      * which may render this test unusable, so we're trying to avoid that.
1082      */
1083     SetLastError(0xdeadbeef);
1084     GetKerningPairsW(hdc, 0, NULL);
1085     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1086     {
1087         skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1088         ReleaseDC(0, hdc);
1089         return;
1090     }
1091
1092     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1093     {
1094         OUTLINETEXTMETRICW otm;
1095
1096         if (!is_font_installed(kd[i].face_name))
1097         {
1098             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1099             continue;
1100         }
1101
1102         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1103
1104         memset(&lf, 0, sizeof(lf));
1105         strcpy(lf.lfFaceName, kd[i].face_name);
1106         lf.lfHeight = kd[i].height;
1107         hfont = CreateFontIndirect(&lf);
1108         assert(hfont != 0);
1109
1110         hfont_old = SelectObject(hdc, hfont);
1111
1112         SetLastError(0xdeadbeef);
1113         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1114         ok(GetOutlineTextMetricsW(hdc, sizeof(otm), &otm) == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1115
1116         ok(kd[i].tmHeight == otm.otmTextMetrics.tmHeight, "expected %d, got %d\n",
1117            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1118         ok(kd[i].tmAscent == otm.otmTextMetrics.tmAscent, "expected %d, got %d\n",
1119            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1120         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1121            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1122
1123         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1124            kd[i].otmEMSquare, otm.otmEMSquare);
1125         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1126            kd[i].otmAscent, otm.otmAscent);
1127         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1128            kd[i].otmDescent, otm.otmDescent);
1129         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1130            kd[i].otmLineGap, otm.otmLineGap);
1131         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1132            kd[i].otmMacDescent, otm.otmMacDescent);
1133 todo_wine {
1134         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1135            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1136         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1137            kd[i].otmsXHeight, otm.otmsXHeight);
1138         ok(kd[i].otmMacAscent == otm.otmMacAscent, "expected %d, got %d\n",
1139            kd[i].otmMacAscent, otm.otmMacAscent);
1140         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1141         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1142            kd[i].otmMacLineGap, otm.otmMacLineGap);
1143         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1144            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1145 }
1146
1147         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1148         trace("total_kern_pairs %u\n", total_kern_pairs);
1149         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1150
1151 #if 0 /* Win98 (GetKerningPairsA) and XP behave differently here, the test passes on XP */
1152         SetLastError(0xdeadbeef);
1153         ret = GetKerningPairsW(hdc, 0, kern_pair);
1154         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1155            "got error %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1156         ok(ret == 0, "got %lu, expected 0\n", ret);
1157 #endif
1158
1159         ret = GetKerningPairsW(hdc, 100, NULL);
1160         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1161
1162         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1163         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1164
1165         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1166         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1167
1168         matches = 0;
1169
1170         for (n = 0; n < ret; n++)
1171         {
1172             DWORD j;
1173 #if 0
1174             if (kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1175                 trace("{'%c','%c',%d},\n",
1176                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1177 #endif
1178             for (j = 0; j < kd[i].total_kern_pairs; j++)
1179             {
1180                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1181                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1182                 {
1183                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1184                        "pair %d:%d got %d, expected %d\n",
1185                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1186                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1187                     matches++;
1188                 }
1189             }
1190         }
1191
1192         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1193            matches, kd[i].total_kern_pairs);
1194
1195         HeapFree(GetProcessHeap(), 0, kern_pair);
1196
1197         SelectObject(hdc, hfont_old);
1198         DeleteObject(hfont);
1199     }
1200
1201     ReleaseDC(0, hdc);
1202 }
1203
1204 static void test_GetOutlineTextMetrics(void)
1205 {
1206     OUTLINETEXTMETRIC *otm;
1207     LOGFONT lf;
1208     HFONT hfont, hfont_old;
1209     HDC hdc;
1210     DWORD ret, otm_size;
1211     LPSTR unset_ptr;
1212
1213     if (!is_font_installed("Arial"))
1214     {
1215         skip("Arial is not installed\n");
1216         return;
1217     }
1218
1219     hdc = GetDC(0);
1220
1221     memset(&lf, 0, sizeof(lf));
1222     strcpy(lf.lfFaceName, "Arial");
1223     lf.lfHeight = -13;
1224     lf.lfWeight = FW_NORMAL;
1225     lf.lfPitchAndFamily = DEFAULT_PITCH;
1226     lf.lfQuality = PROOF_QUALITY;
1227     hfont = CreateFontIndirect(&lf);
1228     assert(hfont != 0);
1229
1230     hfont_old = SelectObject(hdc, hfont);
1231     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1232     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1233
1234     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1235
1236     memset(otm, 0xAA, otm_size);
1237     SetLastError(0xdeadbeef);
1238     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1239     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1240     ok(ret == 1 /* Win9x */ ||
1241        ret == otm->otmSize /* XP*/,
1242        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1243     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1244     {
1245         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1246         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1247         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1248         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1249     }
1250
1251     memset(otm, 0xAA, otm_size);
1252     SetLastError(0xdeadbeef);
1253     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1254     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1255     ok(ret == 1 /* Win9x */ ||
1256        ret == otm->otmSize /* XP*/,
1257        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1258     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1259     {
1260         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1261         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1262         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1263         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1264     }
1265
1266     /* ask about truncated data */
1267     memset(otm, 0xAA, otm_size);
1268     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1269     SetLastError(0xdeadbeef);
1270     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1271     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1272     ok(ret == 1 /* Win9x */ ||
1273        ret == otm->otmSize /* XP*/,
1274        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1275     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1276     {
1277         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1278         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1279         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1280     }
1281     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1282
1283     HeapFree(GetProcessHeap(), 0, otm);
1284
1285     SelectObject(hdc, hfont_old);
1286     DeleteObject(hfont);
1287
1288     ReleaseDC(0, hdc);
1289 }
1290
1291 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1292 {
1293     INT         x, y,
1294                 breakCount,
1295                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1296                 areaWidth = clientArea->right - clientArea->left,
1297                 nErrors = 0, e;
1298     BOOL        lastExtent = FALSE;
1299     PSTR        pFirstChar, pLastChar;
1300     SIZE        size;
1301     TEXTMETRICA tm;
1302     struct err
1303     {
1304         char extent[100];
1305         int  GetTextExtentExPointWWidth;
1306     } error[10];
1307
1308     GetTextMetricsA(hdc, &tm);
1309     y = clientArea->top;
1310     do {
1311         breakCount = 0;
1312         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1313         pFirstChar = str;
1314
1315         do {
1316             pLastChar = str;
1317
1318             /* if not at the end of the string, ... */
1319             if (*str == '\0') break;
1320             /* ... add the next word to the current extent */
1321             while (*str != '\0' && *str++ != tm.tmBreakChar);
1322             breakCount++;
1323             SetTextJustification(hdc, 0, 0);
1324             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1325         } while ((int) size.cx < areaWidth);
1326
1327         /* ignore trailing break chars */
1328         breakCount--;
1329         while (*(pLastChar - 1) == tm.tmBreakChar)
1330         {
1331             pLastChar--;
1332             breakCount--;
1333         }
1334
1335         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1336
1337         SetTextJustification(hdc, 0, 0);
1338         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1339
1340         /* do not justify the last extent */
1341         if (*str != '\0' && breakCount > 0)
1342         {
1343             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1344             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1345             justifiedWidth = size.cx;
1346         }
1347         else lastExtent = TRUE;
1348
1349         x = clientArea->left;
1350
1351         /* catch errors and report them */
1352         if (!lastExtent && (justifiedWidth != areaWidth))
1353         {
1354             memset(error[nErrors].extent, 0, 100);
1355             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1356             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1357             nErrors++;
1358         }
1359
1360         y += size.cy;
1361         str = pLastChar;
1362     } while (*str && y < clientArea->bottom);
1363
1364     for (e = 0; e < nErrors; e++)
1365     {
1366         /* The width returned by GetTextExtentPoint32() is exactly the same
1367            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1368         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1369             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1370             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1371     }
1372 }
1373
1374 static void test_SetTextJustification(void)
1375 {
1376     HDC hdc;
1377     RECT clientArea;
1378     LOGFONTA lf;
1379     HFONT hfont;
1380     HWND hwnd;
1381     static char testText[] =
1382             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1383             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1384             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1385             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1386             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1387             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1388             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1389
1390     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1391     GetClientRect( hwnd, &clientArea );
1392     hdc = GetDC( hwnd );
1393
1394     memset(&lf, 0, sizeof lf);
1395     lf.lfCharSet = ANSI_CHARSET;
1396     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1397     lf.lfWeight = FW_DONTCARE;
1398     lf.lfHeight = 20;
1399     lf.lfQuality = DEFAULT_QUALITY;
1400     lstrcpyA(lf.lfFaceName, "Times New Roman");
1401     hfont = create_font("Times New Roman", &lf);
1402     SelectObject(hdc, hfont);
1403
1404     testJustification(hdc, testText, &clientArea);
1405
1406     DeleteObject(hfont);
1407     ReleaseDC(hwnd, hdc);
1408     DestroyWindow(hwnd);
1409 }
1410
1411 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1412 {
1413     HDC hdc;
1414     LOGFONTA lf;
1415     HFONT hfont, hfont_old;
1416     CHARSETINFO csi;
1417     FONTSIGNATURE fs;
1418     INT cs;
1419     DWORD i, ret;
1420     char name[64];
1421
1422     assert(count <= 128);
1423
1424     memset(&lf, 0, sizeof(lf));
1425
1426     lf.lfCharSet = charset;
1427     lf.lfHeight = 10;
1428     lstrcpyA(lf.lfFaceName, "Arial");
1429     SetLastError(0xdeadbeef);
1430     hfont = CreateFontIndirectA(&lf);
1431     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1432
1433     hdc = GetDC(0);
1434     hfont_old = SelectObject(hdc, hfont);
1435
1436     cs = GetTextCharsetInfo(hdc, &fs, 0);
1437     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1438
1439     SetLastError(0xdeadbeef);
1440     ret = GetTextFaceA(hdc, sizeof(name), name);
1441     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1442
1443     if (charset == SYMBOL_CHARSET)
1444     {
1445         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1446         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1447     }
1448     else
1449     {
1450         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1451         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1452     }
1453
1454     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1455     {
1456         trace("Can't find codepage for charset %d\n", cs);
1457         ReleaseDC(0, hdc);
1458         return FALSE;
1459     }
1460     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1461
1462     if (unicode)
1463     {
1464         char ansi_buf[128];
1465         WCHAR unicode_buf[128];
1466
1467         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1468
1469         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1470
1471         SetLastError(0xdeadbeef);
1472         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1473         ok(ret == count, "GetGlyphIndicesW error %u\n", GetLastError());
1474     }
1475     else
1476     {
1477         char ansi_buf[128];
1478
1479         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1480
1481         SetLastError(0xdeadbeef);
1482         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1483         ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
1484     }
1485
1486     SelectObject(hdc, hfont_old);
1487     DeleteObject(hfont);
1488
1489     ReleaseDC(0, hdc);
1490
1491     return TRUE;
1492 }
1493
1494 static void test_font_charset(void)
1495 {
1496     static struct charset_data
1497     {
1498         INT charset;
1499         UINT code_page;
1500         WORD font_idxA[128], font_idxW[128];
1501     } cd[] =
1502     {
1503         { ANSI_CHARSET, 1252 },
1504         { RUSSIAN_CHARSET, 1251 },
1505         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1506     };
1507     int i;
1508
1509     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1510     {
1511         skip("Skipping the font charset test on a Win9x platform\n");
1512         return;
1513     }
1514
1515     if (!is_font_installed("Arial"))
1516     {
1517         skip("Arial is not installed\n");
1518         return;
1519     }
1520
1521     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1522     {
1523         if (cd[i].charset == SYMBOL_CHARSET)
1524         {
1525             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1526             {
1527                 skip("Symbol or Wingdings is not installed\n");
1528                 break;
1529             }
1530         }
1531         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
1532         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
1533         ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1534     }
1535
1536     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1537     if (i > 2)
1538     {
1539         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1540         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1541     }
1542     else
1543         skip("Symbol or Wingdings is not installed\n");
1544 }
1545
1546 static void test_GetFontUnicodeRanges(void)
1547 {
1548     LOGFONTA lf;
1549     HDC hdc;
1550     HFONT hfont, hfont_old;
1551     DWORD size;
1552     GLYPHSET *gs;
1553
1554     if (!pGetFontUnicodeRanges)
1555     {
1556         skip("GetFontUnicodeRanges not available before W2K\n");
1557         return;
1558     }
1559
1560     memset(&lf, 0, sizeof(lf));
1561     lstrcpyA(lf.lfFaceName, "Arial");
1562     hfont = create_font("Arial", &lf);
1563
1564     hdc = GetDC(0);
1565     hfont_old = SelectObject(hdc, hfont);
1566
1567     size = pGetFontUnicodeRanges(NULL, NULL);
1568     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1569
1570     size = pGetFontUnicodeRanges(hdc, NULL);
1571     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1572
1573     gs = HeapAlloc(GetProcessHeap(), 0, size);
1574
1575     size = pGetFontUnicodeRanges(hdc, gs);
1576     ok(size, "GetFontUnicodeRanges failed\n");
1577 #if 0
1578     for (i = 0; i < gs->cRanges; i++)
1579         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1580 #endif
1581     trace("found %u ranges\n", gs->cRanges);
1582
1583     HeapFree(GetProcessHeap(), 0, gs);
1584
1585     SelectObject(hdc, hfont_old);
1586     DeleteObject(hfont);
1587     ReleaseDC(NULL, hdc);
1588 }
1589
1590 #define MAX_ENUM_FONTS 4096
1591
1592 struct enum_font_data
1593 {
1594     int total;
1595     LOGFONT lf[MAX_ENUM_FONTS];
1596 };
1597
1598 struct enum_font_dataW
1599 {
1600     int total;
1601     LOGFONTW lf[MAX_ENUM_FONTS];
1602 };
1603
1604 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1605 {
1606     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1607
1608     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1609
1610     if (type != TRUETYPE_FONTTYPE) return 1;
1611 #if 0
1612     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1613           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1614 #endif
1615     if (efd->total < MAX_ENUM_FONTS)
1616         efd->lf[efd->total++] = *lf;
1617     else
1618         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1619
1620     return 1;
1621 }
1622
1623 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1624 {
1625     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1626
1627     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1628
1629     if (type != TRUETYPE_FONTTYPE) return 1;
1630 #if 0
1631     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1632           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1633 #endif
1634     if (efd->total < MAX_ENUM_FONTS)
1635         efd->lf[efd->total++] = *lf;
1636     else
1637         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1638
1639     return 1;
1640 }
1641
1642 static void get_charset_stats(struct enum_font_data *efd,
1643                               int *ansi_charset, int *symbol_charset,
1644                               int *russian_charset)
1645 {
1646     int i;
1647
1648     *ansi_charset = 0;
1649     *symbol_charset = 0;
1650     *russian_charset = 0;
1651
1652     for (i = 0; i < efd->total; i++)
1653     {
1654         switch (efd->lf[i].lfCharSet)
1655         {
1656         case ANSI_CHARSET:
1657             (*ansi_charset)++;
1658             break;
1659         case SYMBOL_CHARSET:
1660             (*symbol_charset)++;
1661             break;
1662         case RUSSIAN_CHARSET:
1663             (*russian_charset)++;
1664             break;
1665         }
1666     }
1667 }
1668
1669 static void get_charset_statsW(struct enum_font_dataW *efd,
1670                               int *ansi_charset, int *symbol_charset,
1671                               int *russian_charset)
1672 {
1673     int i;
1674
1675     *ansi_charset = 0;
1676     *symbol_charset = 0;
1677     *russian_charset = 0;
1678
1679     for (i = 0; i < efd->total; i++)
1680     {
1681         switch (efd->lf[i].lfCharSet)
1682         {
1683         case ANSI_CHARSET:
1684             (*ansi_charset)++;
1685             break;
1686         case SYMBOL_CHARSET:
1687             (*symbol_charset)++;
1688             break;
1689         case RUSSIAN_CHARSET:
1690             (*russian_charset)++;
1691             break;
1692         }
1693     }
1694 }
1695
1696 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1697 {
1698     struct enum_font_data efd;
1699     struct enum_font_dataW efdw;
1700     LOGFONT lf;
1701     HDC hdc;
1702     int i, ret, ansi_charset, symbol_charset, russian_charset;
1703
1704     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1705
1706     if (*font_name && !is_truetype_font_installed(font_name))
1707     {
1708         skip("%s is not installed\n", font_name);
1709         return;
1710     }
1711
1712     hdc = GetDC(0);
1713
1714     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1715      * while EnumFontFamiliesEx doesn't.
1716      */
1717     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1718     {
1719         /*
1720          * Use EnumFontFamiliesW since win98 crashes when the
1721          *    second parameter is NULL using EnumFontFamilies
1722          */
1723         efdw.total = 0;
1724         SetLastError(0xdeadbeef);
1725         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1726         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1727         if(ret)
1728         {
1729             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1730             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1731                   ansi_charset, symbol_charset, russian_charset);
1732             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1733             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1734             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1735             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1736         }
1737
1738         efdw.total = 0;
1739         SetLastError(0xdeadbeef);
1740         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1741         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1742         if(ret)
1743         {
1744             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1745             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1746                   ansi_charset, symbol_charset, russian_charset);
1747             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1748             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1749             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1750             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1751         }
1752     }
1753
1754     efd.total = 0;
1755     SetLastError(0xdeadbeef);
1756     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1757     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1758     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1759     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1760           ansi_charset, symbol_charset, russian_charset,
1761           *font_name ? font_name : "<empty>");
1762     if (*font_name)
1763         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1764     else
1765         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1766     for (i = 0; i < efd.total; i++)
1767     {
1768 /* FIXME: remove completely once Wine is fixed */
1769 if (efd.lf[i].lfCharSet != font_charset)
1770 {
1771 todo_wine
1772     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1773 }
1774 else
1775         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1776         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1777            font_name, efd.lf[i].lfFaceName);
1778     }
1779
1780     memset(&lf, 0, sizeof(lf));
1781     lf.lfCharSet = ANSI_CHARSET;
1782     lstrcpy(lf.lfFaceName, font_name);
1783     efd.total = 0;
1784     SetLastError(0xdeadbeef);
1785     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1786     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1787     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1788     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1789           ansi_charset, symbol_charset, russian_charset,
1790           *font_name ? font_name : "<empty>");
1791     if (font_charset == SYMBOL_CHARSET)
1792     {
1793         if (*font_name)
1794             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1795         else
1796             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1797     }
1798     else
1799     {
1800         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1801         for (i = 0; i < efd.total; i++)
1802         {
1803             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1804             if (*font_name)
1805                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1806                    font_name, efd.lf[i].lfFaceName);
1807         }
1808     }
1809
1810     /* DEFAULT_CHARSET should enumerate all available charsets */
1811     memset(&lf, 0, sizeof(lf));
1812     lf.lfCharSet = DEFAULT_CHARSET;
1813     lstrcpy(lf.lfFaceName, font_name);
1814     efd.total = 0;
1815     SetLastError(0xdeadbeef);
1816     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1817     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1818     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1819     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1820           ansi_charset, symbol_charset, russian_charset,
1821           *font_name ? font_name : "<empty>");
1822     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1823     for (i = 0; i < efd.total; i++)
1824     {
1825         if (*font_name)
1826             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1827                font_name, efd.lf[i].lfFaceName);
1828     }
1829     if (*font_name)
1830     {
1831         switch (font_charset)
1832         {
1833         case ANSI_CHARSET:
1834             ok(ansi_charset > 0,
1835                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1836             ok(!symbol_charset,
1837                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1838             ok(russian_charset > 0,
1839                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1840             break;
1841         case SYMBOL_CHARSET:
1842             ok(!ansi_charset,
1843                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1844             ok(symbol_charset,
1845                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1846             ok(!russian_charset,
1847                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1848             break;
1849         case DEFAULT_CHARSET:
1850             ok(ansi_charset > 0,
1851                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1852             ok(symbol_charset > 0,
1853                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1854             ok(russian_charset > 0,
1855                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1856             break;
1857         }
1858     }
1859     else
1860     {
1861         ok(ansi_charset > 0,
1862            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1863         ok(symbol_charset > 0,
1864            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1865         ok(russian_charset > 0,
1866            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1867     }
1868
1869     memset(&lf, 0, sizeof(lf));
1870     lf.lfCharSet = SYMBOL_CHARSET;
1871     lstrcpy(lf.lfFaceName, font_name);
1872     efd.total = 0;
1873     SetLastError(0xdeadbeef);
1874     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1875     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1876     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1877     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1878           ansi_charset, symbol_charset, russian_charset,
1879           *font_name ? font_name : "<empty>");
1880     if (*font_name && font_charset == ANSI_CHARSET)
1881         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1882     else
1883     {
1884         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1885         for (i = 0; i < efd.total; i++)
1886         {
1887             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1888             if (*font_name)
1889                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1890                    font_name, efd.lf[i].lfFaceName);
1891         }
1892
1893         ok(!ansi_charset,
1894            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1895         ok(symbol_charset > 0,
1896            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1897         ok(!russian_charset,
1898            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1899     }
1900
1901     ReleaseDC(0, hdc);
1902 }
1903
1904 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1905 {
1906     HFONT hfont, hfont_prev;
1907     DWORD ret;
1908     GLYPHMETRICS gm1, gm2;
1909     LOGFONTA lf2 = *lf;
1910     WORD idx;
1911     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1912
1913     if(!pGetGlyphIndicesA)
1914     {
1915         skip("GetGlyphIndicesA is unavailable\n");
1916         return;
1917     }
1918
1919     /* negative widths are handled just as positive ones */
1920     lf2.lfWidth = -lf->lfWidth;
1921
1922     SetLastError(0xdeadbeef);
1923     hfont = CreateFontIndirectA(lf);
1924     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1925     check_font("original", lf, hfont);
1926
1927     hfont_prev = SelectObject(hdc, hfont);
1928
1929     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1930     if (ret == GDI_ERROR || idx == 0xffff)
1931     {
1932         SelectObject(hdc, hfont_prev);
1933         DeleteObject(hfont);
1934         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1935         return;
1936     }
1937
1938     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1939     memset(&gm1, 0xab, sizeof(gm1));
1940     SetLastError(0xdeadbeef);
1941     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1942     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1943
1944     SelectObject(hdc, hfont_prev);
1945     DeleteObject(hfont);
1946
1947     SetLastError(0xdeadbeef);
1948     hfont = CreateFontIndirectA(&lf2);
1949     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1950     check_font("negative width", &lf2, hfont);
1951
1952     hfont_prev = SelectObject(hdc, hfont);
1953
1954     memset(&gm2, 0xbb, sizeof(gm2));
1955     SetLastError(0xdeadbeef);
1956     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
1957     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1958
1959     SelectObject(hdc, hfont_prev);
1960     DeleteObject(hfont);
1961
1962     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
1963        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
1964        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
1965        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
1966        gm1.gmCellIncX == gm2.gmCellIncX &&
1967        gm1.gmCellIncY == gm2.gmCellIncY,
1968        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
1969        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
1970        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
1971        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
1972        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
1973 }
1974
1975 /* PANOSE is 10 bytes in size, need to pack the structure properly */
1976 #include "pshpack2.h"
1977 typedef struct
1978 {
1979     USHORT version;
1980     SHORT xAvgCharWidth;
1981     USHORT usWeightClass;
1982     USHORT usWidthClass;
1983     SHORT fsType;
1984     SHORT ySubscriptXSize;
1985     SHORT ySubscriptYSize;
1986     SHORT ySubscriptXOffset;
1987     SHORT ySubscriptYOffset;
1988     SHORT ySuperscriptXSize;
1989     SHORT ySuperscriptYSize;
1990     SHORT ySuperscriptXOffset;
1991     SHORT ySuperscriptYOffset;
1992     SHORT yStrikeoutSize;
1993     SHORT yStrikeoutPosition;
1994     SHORT sFamilyClass;
1995     PANOSE panose;
1996     ULONG ulUnicodeRange1;
1997     ULONG ulUnicodeRange2;
1998     ULONG ulUnicodeRange3;
1999     ULONG ulUnicodeRange4;
2000     CHAR achVendID[4];
2001     USHORT fsSelection;
2002     USHORT usFirstCharIndex;
2003     USHORT usLastCharIndex;
2004     /* According to the Apple spec, original version didn't have the below fields,
2005      * version numbers were taked from the OpenType spec.
2006      */
2007     /* version 0 (TrueType 1.5) */
2008     USHORT sTypoAscender;
2009     USHORT sTypoDescender;
2010     USHORT sTypoLineGap;
2011     USHORT usWinAscent;
2012     USHORT usWinDescent;
2013     /* version 1 (TrueType 1.66) */
2014     ULONG ulCodePageRange1;
2015     ULONG ulCodePageRange2;
2016     /* version 2 (OpenType 1.2) */
2017     SHORT sxHeight;
2018     SHORT sCapHeight;
2019     USHORT usDefaultChar;
2020     USHORT usBreakChar;
2021     USHORT usMaxContext;
2022 } TT_OS2_V2;
2023 #include "poppack.h"
2024
2025 #ifdef WORDS_BIGENDIAN
2026 #define GET_BE_WORD(x) (x)
2027 #define GET_BE_DWORD(x) (x)
2028 #else
2029 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2030 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2031 #endif
2032
2033 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2034                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2035                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2036 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2037 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2038
2039 typedef struct
2040 {
2041     USHORT version;
2042     USHORT num_tables;
2043 } cmap_header;
2044
2045 typedef struct
2046 {
2047     USHORT plat_id;
2048     USHORT enc_id;
2049     ULONG offset;
2050 } cmap_encoding_record;
2051
2052 typedef struct
2053 {
2054     USHORT format;
2055     USHORT length;
2056     USHORT language;
2057
2058     BYTE glyph_ids[256];
2059 } cmap_format_0;
2060
2061 typedef struct
2062 {
2063     USHORT format;
2064     USHORT length;
2065     USHORT language;
2066
2067     USHORT seg_countx2;
2068     USHORT search_range;
2069     USHORT entry_selector;
2070     USHORT range_shift;
2071
2072     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2073 /* Then follows:
2074     USHORT pad;
2075     USHORT start_count[seg_countx2 / 2];
2076     USHORT id_delta[seg_countx2 / 2];
2077     USHORT id_range_offset[seg_countx2 / 2];
2078     USHORT glyph_ids[];
2079 */
2080 } cmap_format_4;
2081
2082 typedef struct
2083 {
2084     USHORT end_count;
2085     USHORT start_count;
2086     USHORT id_delta;
2087     USHORT id_range_offset;
2088 } cmap_format_4_seg;
2089
2090 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2091 {
2092     ok((tmA->tmPitchAndFamily & 0xf0) == family, "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2093        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2094        os2->panose.bWeight, os2->panose.bProportion);
2095 }
2096
2097 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2098 {
2099     int i;
2100     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2101
2102     *first = 256;
2103
2104     for(i = 0; i < 256; i++)
2105     {
2106         if(cmap->glyph_ids[i] == 0) continue;
2107         *last = i;
2108         if(*first == 256) *first = i;
2109     }
2110     if(*first == 256) return FALSE;
2111     return TRUE;
2112 }
2113
2114 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2115 {
2116     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2117     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2118     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2119     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2120     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2121 }
2122
2123 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last)
2124 {
2125     int i;
2126     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2127     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2128     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2129
2130     *first = 0x10000;
2131
2132     for(i = 0; i < seg_count; i++)
2133     {
2134         DWORD code, index;
2135         cmap_format_4_seg seg;
2136
2137         get_seg4(cmap, i, &seg);
2138         for(code = seg.start_count; code <= seg.end_count; code++)
2139         {
2140             if(seg.id_range_offset == 0)
2141                 index = (seg.id_delta + code) & 0xffff;
2142             else
2143             {
2144                 index = seg.id_range_offset / 2
2145                     + code - seg.start_count
2146                     + i - seg_count;
2147
2148                 index = GET_BE_WORD(glyph_ids[index]);
2149                 if(index) index += seg.id_delta;
2150             }
2151             if(*first == 0x10000)
2152                 *last = *first = code;
2153             else if(index)
2154                 *last = code;
2155         }
2156     }
2157
2158     if(*first == 0x10000) return FALSE;
2159     return TRUE;
2160 }
2161
2162 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2163 {
2164     USHORT i;
2165     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2166
2167     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2168     {
2169         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2170             return (BYTE *)header + GET_BE_DWORD(record->offset);
2171         record++;
2172     }
2173     return NULL;
2174 }
2175
2176 typedef enum
2177 {
2178     cmap_none,
2179     cmap_ms_unicode,
2180     cmap_ms_symbol
2181 } cmap_type;
2182
2183 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2184 {
2185     LONG size, ret;
2186     cmap_header *header;
2187     void *cmap;
2188     BOOL r = FALSE;
2189     WORD format;
2190
2191     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2192     ok(size != GDI_ERROR, "no cmap table found\n");
2193     if(size == GDI_ERROR) return FALSE;
2194
2195     header = HeapAlloc(GetProcessHeap(), 0, size);
2196     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2197     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2198     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2199
2200     cmap = get_cmap(header, 3, 1);
2201     if(cmap)
2202         *cmap_type = cmap_ms_unicode;
2203     else
2204     {
2205         cmap = get_cmap(header, 3, 0);
2206         if(cmap) *cmap_type = cmap_ms_symbol;
2207     }
2208     if(!cmap)
2209     {
2210         *cmap_type = cmap_none;
2211         goto end;
2212     }
2213
2214     format = GET_BE_WORD(*(WORD *)cmap);
2215     switch(format)
2216     {
2217     case 0:
2218         r = get_first_last_from_cmap0(cmap, first, last);
2219         break;
2220     case 4:
2221         r = get_first_last_from_cmap4(cmap, first, last);
2222         break;
2223     default:
2224         trace("unhandled cmap format %d\n", format);
2225         break;
2226     }
2227
2228 end:
2229     HeapFree(GetProcessHeap(), 0, header);
2230     return r;
2231 }
2232
2233 static void test_text_metrics(const LOGFONTA *lf)
2234 {
2235     HDC hdc;
2236     HFONT hfont, hfont_old;
2237     TEXTMETRICA tmA;
2238     TT_OS2_V2 tt_os2;
2239     LONG size, ret;
2240     const char *font_name = lf->lfFaceName;
2241     DWORD cmap_first = 0, cmap_last = 0;
2242     cmap_type cmap_type;
2243
2244     hdc = GetDC(0);
2245
2246     SetLastError(0xdeadbeef);
2247     hfont = CreateFontIndirectA(lf);
2248     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2249
2250     hfont_old = SelectObject(hdc, hfont);
2251
2252     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2253     if (size == GDI_ERROR)
2254     {
2255         trace("OS/2 chunk was not found\n");
2256         goto end_of_test;
2257     }
2258     if (size > sizeof(tt_os2))
2259     {
2260         trace("got too large OS/2 chunk of size %u\n", size);
2261         size = sizeof(tt_os2);
2262     }
2263
2264     memset(&tt_os2, 0, sizeof(tt_os2));
2265     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2266     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2267
2268     SetLastError(0xdeadbeef);
2269     ret = GetTextMetricsA(hdc, &tmA);
2270     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2271
2272     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2273     {
2274         skip("Unable to retrieve first and last glyphs from cmap\n");
2275     }
2276     else
2277     {
2278         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2279         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2280         UINT os2_first_char, os2_last_char, default_char, break_char;
2281         USHORT version;
2282         TEXTMETRICW tmW;
2283
2284         version = GET_BE_WORD(tt_os2.version);
2285
2286         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2287         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2288         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2289         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2290
2291         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2292               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2293               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2294
2295         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2296         {
2297             expect_first_W    = 0;
2298             switch(GetACP())
2299             {
2300             case 1257:  /* Baltic */
2301                 expect_last_W = 0xf8fd;
2302                 break;
2303             default:
2304                 expect_last_W = 0xf0ff;
2305             }
2306             expect_break_W    = 0x20;
2307             expect_default_W  = expect_break_W - 1;
2308             expect_first_A    = 0x1e;
2309             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2310         }
2311         else
2312         {
2313             expect_first_W    = cmap_first;
2314             expect_last_W     = min(cmap_last, os2_last_char);
2315             if(os2_first_char <= 1)
2316                 expect_break_W = os2_first_char + 2;
2317             else if(os2_first_char > 0xff)
2318                 expect_break_W = 0x20;
2319             else
2320                 expect_break_W = os2_first_char;
2321             expect_default_W  = expect_break_W - 1;
2322             expect_first_A    = expect_default_W - 1;
2323             expect_last_A     = min(expect_last_W, 0xff);
2324         }
2325         expect_break_A    = expect_break_W;
2326         expect_default_A  = expect_default_W;
2327
2328         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2329         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2330             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2331                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2332                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2333         else
2334             ok(tmA.tmFirstChar == expect_first_A ||
2335                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2336                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2337         ok(tmA.tmLastChar == expect_last_A ||
2338            tmA.tmLastChar == 0xff /* win9x */,
2339            "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2340         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2341            font_name, tmA.tmBreakChar, expect_break_A);
2342         ok(tmA.tmDefaultChar == expect_default_A, "A: tmDefaultChar for %s got %02x expected %02x\n",
2343            font_name, tmA.tmDefaultChar, expect_default_A);
2344
2345
2346         SetLastError(0xdeadbeef);
2347         ret = GetTextMetricsW(hdc, &tmW);
2348         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2349            "GetTextMetricsW error %u\n", GetLastError());
2350         if (ret)
2351         {
2352             /* Wine uses the os2 first char */
2353             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2354                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2355                              font_name, tmW.tmFirstChar, expect_first_W);
2356             else
2357                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2358                    font_name, tmW.tmFirstChar, expect_first_W);
2359
2360             /* Wine uses the os2 last char */
2361             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2362                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2363                              font_name, tmW.tmLastChar, expect_last_W);
2364             else
2365                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2366                    font_name, tmW.tmLastChar, expect_last_W);
2367             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2368                font_name, tmW.tmBreakChar, expect_break_W);
2369             ok(tmW.tmDefaultChar == expect_default_W, "W: tmDefaultChar for %s got %02x expected %02x\n",
2370                font_name, tmW.tmDefaultChar, expect_default_W);
2371
2372             /* Test the aspect ratio while we have tmW */
2373             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2374             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2375                tmW.tmDigitizedAspectX, ret);
2376             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2377             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2378                tmW.tmDigitizedAspectX, ret);
2379         }
2380     }
2381
2382     /* test FF_ values */
2383     switch(tt_os2.panose.bFamilyType)
2384     {
2385     case PAN_ANY:
2386     case PAN_NO_FIT:
2387     case PAN_FAMILY_TEXT_DISPLAY:
2388     case PAN_FAMILY_PICTORIAL:
2389     default:
2390         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2391            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2392         {
2393             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2394             break;
2395         }
2396         switch(tt_os2.panose.bSerifStyle)
2397         {
2398         case PAN_ANY:
2399         case PAN_NO_FIT:
2400         default:
2401             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2402             break;
2403
2404         case PAN_SERIF_COVE:
2405         case PAN_SERIF_OBTUSE_COVE:
2406         case PAN_SERIF_SQUARE_COVE:
2407         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2408         case PAN_SERIF_SQUARE:
2409         case PAN_SERIF_THIN:
2410         case PAN_SERIF_BONE:
2411         case PAN_SERIF_EXAGGERATED:
2412         case PAN_SERIF_TRIANGLE:
2413             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2414             break;
2415
2416         case PAN_SERIF_NORMAL_SANS:
2417         case PAN_SERIF_OBTUSE_SANS:
2418         case PAN_SERIF_PERP_SANS:
2419         case PAN_SERIF_FLARED:
2420         case PAN_SERIF_ROUNDED:
2421             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2422             break;
2423         }
2424         break;
2425
2426     case PAN_FAMILY_SCRIPT:
2427         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2428         break;
2429
2430     case PAN_FAMILY_DECORATIVE:
2431         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2432         break;
2433     }
2434
2435     test_negative_width(hdc, lf);
2436
2437 end_of_test:
2438     SelectObject(hdc, hfont_old);
2439     DeleteObject(hfont);
2440
2441     ReleaseDC(0, hdc);
2442 }
2443
2444 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2445 {
2446     INT *enumed = (INT *)lParam;
2447
2448     if (type == TRUETYPE_FONTTYPE)
2449     {
2450         (*enumed)++;
2451         test_text_metrics(lf);
2452     }
2453     return 1;
2454 }
2455
2456 static void test_GetTextMetrics(void)
2457 {
2458     LOGFONTA lf;
2459     HDC hdc;
2460     INT enumed;
2461
2462     hdc = GetDC(0);
2463
2464     memset(&lf, 0, sizeof(lf));
2465     lf.lfCharSet = DEFAULT_CHARSET;
2466     enumed = 0;
2467     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2468     trace("Tested metrics of %d truetype fonts\n", enumed);
2469
2470     ReleaseDC(0, hdc);
2471 }
2472
2473 static void test_nonexistent_font(void)
2474 {
2475     static const struct
2476     {
2477         const char *name;
2478         int charset;
2479     } font_subst[] =
2480     {
2481         { "Times New Roman Baltic", 186 },
2482         { "Times New Roman CE", 238 },
2483         { "Times New Roman CYR", 204 },
2484         { "Times New Roman Greek", 161 },
2485         { "Times New Roman TUR", 162 }
2486     };
2487     LOGFONTA lf;
2488     HDC hdc;
2489     HFONT hfont;
2490     CHARSETINFO csi;
2491     INT cs, expected_cs, i;
2492     char buf[LF_FACESIZE];
2493
2494     if (!is_truetype_font_installed("Arial") ||
2495         !is_truetype_font_installed("Times New Roman"))
2496     {
2497         skip("Arial or Times New Roman not installed\n");
2498         return;
2499     }
2500
2501     expected_cs = GetACP();
2502     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2503     {
2504         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2505         return;
2506     }
2507     expected_cs = csi.ciCharset;
2508     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2509
2510     hdc = GetDC(0);
2511
2512     memset(&lf, 0, sizeof(lf));
2513     lf.lfHeight = 100;
2514     lf.lfWeight = FW_REGULAR;
2515     lf.lfCharSet = ANSI_CHARSET;
2516     lf.lfPitchAndFamily = FF_SWISS;
2517     strcpy(lf.lfFaceName, "Nonexistent font");
2518     hfont = CreateFontIndirectA(&lf);
2519     hfont = SelectObject(hdc, hfont);
2520     GetTextFaceA(hdc, sizeof(buf), buf);
2521     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2522     cs = GetTextCharset(hdc);
2523     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2524     DeleteObject(SelectObject(hdc, hfont));
2525
2526     memset(&lf, 0, sizeof(lf));
2527     lf.lfHeight = -13;
2528     lf.lfWeight = FW_DONTCARE;
2529     strcpy(lf.lfFaceName, "Nonexistent font");
2530     hfont = CreateFontIndirectA(&lf);
2531     hfont = SelectObject(hdc, hfont);
2532     GetTextFaceA(hdc, sizeof(buf), buf);
2533 todo_wine /* Wine uses Arial for all substitutions */
2534     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2535        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2536        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2537        "Got %s\n", buf);
2538     cs = GetTextCharset(hdc);
2539     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2540     DeleteObject(SelectObject(hdc, hfont));
2541
2542     memset(&lf, 0, sizeof(lf));
2543     lf.lfHeight = -13;
2544     lf.lfWeight = FW_REGULAR;
2545     strcpy(lf.lfFaceName, "Nonexistent font");
2546     hfont = CreateFontIndirectA(&lf);
2547     hfont = SelectObject(hdc, hfont);
2548     GetTextFaceA(hdc, sizeof(buf), buf);
2549     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2550        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2551     cs = GetTextCharset(hdc);
2552     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2553     DeleteObject(SelectObject(hdc, hfont));
2554
2555     memset(&lf, 0, sizeof(lf));
2556     lf.lfHeight = -13;
2557     lf.lfWeight = FW_DONTCARE;
2558     strcpy(lf.lfFaceName, "Times New Roman");
2559     hfont = CreateFontIndirectA(&lf);
2560     hfont = SelectObject(hdc, hfont);
2561     GetTextFaceA(hdc, sizeof(buf), buf);
2562     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2563     cs = GetTextCharset(hdc);
2564     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2565     DeleteObject(SelectObject(hdc, hfont));
2566
2567     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2568     {
2569         memset(&lf, 0, sizeof(lf));
2570         lf.lfHeight = -13;
2571         lf.lfWeight = FW_REGULAR;
2572         strcpy(lf.lfFaceName, font_subst[i].name);
2573         hfont = CreateFontIndirectA(&lf);
2574         hfont = SelectObject(hdc, hfont);
2575         cs = GetTextCharset(hdc);
2576         if (font_subst[i].charset == expected_cs)
2577         {
2578             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2579             GetTextFaceA(hdc, sizeof(buf), buf);
2580             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2581         }
2582         else
2583         {
2584             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2585             GetTextFaceA(hdc, sizeof(buf), buf);
2586             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2587                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2588         }
2589         DeleteObject(SelectObject(hdc, hfont));
2590
2591         memset(&lf, 0, sizeof(lf));
2592         lf.lfHeight = -13;
2593         lf.lfWeight = FW_DONTCARE;
2594         strcpy(lf.lfFaceName, font_subst[i].name);
2595         hfont = CreateFontIndirectA(&lf);
2596         hfont = SelectObject(hdc, hfont);
2597         GetTextFaceA(hdc, sizeof(buf), buf);
2598         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2599            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2600            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2601            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2602            "got %s for font %s\n", buf, font_subst[i].name);
2603         cs = GetTextCharset(hdc);
2604         ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2605         DeleteObject(SelectObject(hdc, hfont));
2606     }
2607
2608     ReleaseDC(0, hdc);
2609 }
2610
2611 static void test_GdiRealizationInfo(void)
2612 {
2613     HDC hdc;
2614     DWORD info[4];
2615     BOOL r;
2616     HFONT hfont, hfont_old;
2617     LOGFONTA lf;
2618
2619     if(!pGdiRealizationInfo)
2620     {
2621         skip("GdiRealizationInfo not available\n");
2622         return;
2623     }
2624
2625     hdc = GetDC(0);
2626
2627     memset(info, 0xcc, sizeof(info));
2628     r = pGdiRealizationInfo(hdc, info);
2629     ok(r != 0, "ret 0\n");
2630     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2631     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2632
2633     if (!is_truetype_font_installed("Arial"))
2634     {
2635         skip("skipping GdiRealizationInfo with truetype font\n");
2636         goto end;
2637     }
2638
2639     memset(&lf, 0, sizeof(lf));
2640     strcpy(lf.lfFaceName, "Arial");
2641     lf.lfHeight = 20;
2642     lf.lfWeight = FW_NORMAL;
2643     hfont = CreateFontIndirectA(&lf);
2644     hfont_old = SelectObject(hdc, hfont);
2645
2646     memset(info, 0xcc, sizeof(info));
2647     r = pGdiRealizationInfo(hdc, info);
2648     ok(r != 0, "ret 0\n");
2649     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2650     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2651
2652     DeleteObject(SelectObject(hdc, hfont_old));
2653
2654  end:
2655     ReleaseDC(0, hdc);
2656 }
2657
2658 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2659    the nul in the count of characters copied when the face name buffer is not
2660    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2661    always includes it.  */
2662 static void test_GetTextFace(void)
2663 {
2664     static const char faceA[] = "Tahoma";
2665     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2666     LOGFONTA fA = {0};
2667     LOGFONTW fW = {0};
2668     char bufA[LF_FACESIZE];
2669     WCHAR bufW[LF_FACESIZE];
2670     HFONT f, g;
2671     HDC dc;
2672     int n;
2673
2674     if(!is_font_installed("Tahoma"))
2675     {
2676         skip("Tahoma is not installed so skipping this test\n");
2677         return;
2678     }
2679
2680     /* 'A' case.  */
2681     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2682     f = CreateFontIndirectA(&fA);
2683     ok(f != NULL, "CreateFontIndirectA failed\n");
2684
2685     dc = GetDC(NULL);
2686     g = SelectObject(dc, f);
2687     n = GetTextFaceA(dc, sizeof bufA, bufA);
2688     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2689     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2690
2691     /* Play with the count arg.  */
2692     bufA[0] = 'x';
2693     n = GetTextFaceA(dc, 0, bufA);
2694     ok(n == 0, "GetTextFaceA returned %d\n", n);
2695     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2696
2697     bufA[0] = 'x';
2698     n = GetTextFaceA(dc, 1, bufA);
2699     ok(n == 0, "GetTextFaceA returned %d\n", n);
2700     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2701
2702     bufA[0] = 'x'; bufA[1] = 'y';
2703     n = GetTextFaceA(dc, 2, bufA);
2704     ok(n == 1, "GetTextFaceA returned %d\n", n);
2705     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2706
2707     n = GetTextFaceA(dc, 0, NULL);
2708     ok(n == sizeof faceA ||
2709        broken(n == 0), /* win98, winMe */
2710        "GetTextFaceA returned %d\n", n);
2711
2712     DeleteObject(SelectObject(dc, g));
2713     ReleaseDC(NULL, dc);
2714
2715     /* 'W' case.  */
2716     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2717     SetLastError(0xdeadbeef);
2718     f = CreateFontIndirectW(&fW);
2719     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2720     {
2721         win_skip("CreateFontIndirectW is not implemented\n");
2722         return;
2723     }
2724     ok(f != NULL, "CreateFontIndirectW failed\n");
2725
2726     dc = GetDC(NULL);
2727     g = SelectObject(dc, f);
2728     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2729     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2730     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2731
2732     /* Play with the count arg.  */
2733     bufW[0] = 'x';
2734     n = GetTextFaceW(dc, 0, bufW);
2735     ok(n == 0, "GetTextFaceW returned %d\n", n);
2736     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2737
2738     bufW[0] = 'x';
2739     n = GetTextFaceW(dc, 1, bufW);
2740     ok(n == 1, "GetTextFaceW returned %d\n", n);
2741     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2742
2743     bufW[0] = 'x'; bufW[1] = 'y';
2744     n = GetTextFaceW(dc, 2, bufW);
2745     ok(n == 2, "GetTextFaceW returned %d\n", n);
2746     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2747
2748     n = GetTextFaceW(dc, 0, NULL);
2749     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2750
2751     DeleteObject(SelectObject(dc, g));
2752     ReleaseDC(NULL, dc);
2753 }
2754
2755 static void test_orientation(void)
2756 {
2757     static const char test_str[11] = "Test String";
2758     HDC hdc;
2759     LOGFONTA lf;
2760     HFONT hfont, old_hfont;
2761     SIZE size;
2762
2763     if (!is_truetype_font_installed("Arial"))
2764     {
2765         skip("Arial is not installed\n");
2766         return;
2767     }
2768
2769     hdc = CreateCompatibleDC(0);
2770     memset(&lf, 0, sizeof(lf));
2771     lstrcpyA(lf.lfFaceName, "Arial");
2772     lf.lfHeight = 72;
2773     lf.lfOrientation = lf.lfEscapement = 900;
2774     hfont = create_font("orientation", &lf);
2775     old_hfont = SelectObject(hdc, hfont);
2776     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2777     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2778     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2779     SelectObject(hdc, old_hfont);
2780     DeleteObject(hfont);
2781     DeleteDC(hdc);
2782 }
2783
2784 static void test_GetGlyphOutline(void)
2785 {
2786     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2787     HDC hdc;
2788     GLYPHMETRICS gm;
2789     LOGFONTA lf;
2790     HFONT hfont, old_hfont;
2791     INT ret;
2792
2793     if (!is_truetype_font_installed("Tahoma"))
2794     {
2795         skip("Tahoma is not installed\n");
2796         return;
2797     }
2798
2799     hdc = CreateCompatibleDC(0);
2800     memset(&lf, 0, sizeof(lf));
2801     lf.lfHeight = 72;
2802     lstrcpyA(lf.lfFaceName, "Tahoma");
2803     SetLastError(0xdeadbeef);
2804     hfont = CreateFontIndirectA(&lf);
2805     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2806     old_hfont = SelectObject(hdc, hfont);
2807
2808     memset(&gm, 0, sizeof(gm));
2809     SetLastError(0xdeadbeef);
2810     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2811     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
2812
2813     memset(&gm, 0, sizeof(gm));
2814     SetLastError(0xdeadbeef);
2815     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2816     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
2817     ok(GetLastError() == 0xdeadbeef ||
2818        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
2819        "expected 0xdeadbeef, got %u\n", GetLastError());
2820
2821     memset(&gm, 0, sizeof(gm));
2822     SetLastError(0xdeadbeef);
2823     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2824     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2825         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
2826
2827     memset(&gm, 0, sizeof(gm));
2828     SetLastError(0xdeadbeef);
2829     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2830     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2831     {
2832        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
2833        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2834     }
2835
2836     SelectObject(hdc, old_hfont);
2837     DeleteObject(hfont);
2838     DeleteDC(hdc);
2839 }
2840
2841 START_TEST(font)
2842 {
2843     init();
2844
2845     test_logfont();
2846     test_bitmap_font();
2847     test_outline_font();
2848     test_bitmap_font_metrics();
2849     test_GdiGetCharDimensions();
2850     test_GetCharABCWidths();
2851     test_text_extents();
2852     test_GetGlyphIndices();
2853     test_GetKerningPairs();
2854     test_GetOutlineTextMetrics();
2855     test_SetTextJustification();
2856     test_font_charset();
2857     test_GetFontUnicodeRanges();
2858     test_nonexistent_font();
2859     test_orientation();
2860
2861     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
2862      * I'd like to avoid them in this test.
2863      */
2864     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
2865     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
2866     if (is_truetype_font_installed("Arial Black") &&
2867         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
2868     {
2869         test_EnumFontFamilies("", ANSI_CHARSET);
2870         test_EnumFontFamilies("", SYMBOL_CHARSET);
2871         test_EnumFontFamilies("", DEFAULT_CHARSET);
2872     }
2873     else
2874         skip("Arial Black or Symbol/Wingdings is not installed\n");
2875     test_GetTextMetrics();
2876     test_GdiRealizationInfo();
2877     test_GetTextFace();
2878     test_GetGlyphOutline();
2879 }