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