gdiplus: Implement GdipGetEmHeight.
[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 struct enum_font_dataW
1536 {
1537     int total;
1538     LOGFONTW lf[MAX_ENUM_FONTS];
1539 };
1540
1541 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1542 {
1543     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1544
1545     if (type != TRUETYPE_FONTTYPE) return 1;
1546 #if 0
1547     trace("enumed font \"%s\", charset %d, weight %d, italic %d\n",
1548           lf->lfFaceName, lf->lfCharSet, lf->lfWeight, lf->lfItalic);
1549 #endif
1550     if (efd->total < MAX_ENUM_FONTS)
1551         efd->lf[efd->total++] = *lf;
1552
1553     return 1;
1554 }
1555
1556 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1557 {
1558     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1559
1560     if (type != TRUETYPE_FONTTYPE) return 1;
1561
1562     if (efd->total < MAX_ENUM_FONTS)
1563         efd->lf[efd->total++] = *lf;
1564
1565     return 1;
1566 }
1567
1568 static void get_charset_stats(struct enum_font_data *efd,
1569                               int *ansi_charset, int *symbol_charset,
1570                               int *russian_charset)
1571 {
1572     int i;
1573
1574     *ansi_charset = 0;
1575     *symbol_charset = 0;
1576     *russian_charset = 0;
1577
1578     for (i = 0; i < efd->total; i++)
1579     {
1580         switch (efd->lf[i].lfCharSet)
1581         {
1582         case ANSI_CHARSET:
1583             (*ansi_charset)++;
1584             break;
1585         case SYMBOL_CHARSET:
1586             (*symbol_charset)++;
1587             break;
1588         case RUSSIAN_CHARSET:
1589             (*russian_charset)++;
1590             break;
1591         }
1592     }
1593 }
1594
1595 static void get_charset_statsW(struct enum_font_dataW *efd,
1596                               int *ansi_charset, int *symbol_charset,
1597                               int *russian_charset)
1598 {
1599     int i;
1600
1601     *ansi_charset = 0;
1602     *symbol_charset = 0;
1603     *russian_charset = 0;
1604
1605     for (i = 0; i < efd->total; i++)
1606     {
1607         switch (efd->lf[i].lfCharSet)
1608         {
1609         case ANSI_CHARSET:
1610             (*ansi_charset)++;
1611             break;
1612         case SYMBOL_CHARSET:
1613             (*symbol_charset)++;
1614             break;
1615         case RUSSIAN_CHARSET:
1616             (*russian_charset)++;
1617             break;
1618         }
1619     }
1620 }
1621
1622 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1623 {
1624     struct enum_font_data efd;
1625     struct enum_font_dataW efdw;
1626     LOGFONT lf;
1627     HDC hdc;
1628     int i, ret, ansi_charset, symbol_charset, russian_charset;
1629
1630     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1631
1632     if (*font_name && !is_truetype_font_installed(font_name))
1633     {
1634         skip("%s is not installed\n", font_name);
1635         return;
1636     }
1637
1638     hdc = GetDC(0);
1639
1640     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1641      * while EnumFontFamiliesEx doesn't.
1642      */
1643     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1644     {
1645         /*
1646          * Use EnumFontFamiliesW since win98 crashes when the
1647          *    second parameter is NULL using EnumFontFamilies
1648          */
1649         efd.total = 0;
1650         SetLastError(0xdeadbeef);
1651         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1652         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1653         if(ret)
1654         {
1655             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1656             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1657                   ansi_charset, symbol_charset, russian_charset);
1658             ok(efd.total == 0, "fonts enumerated: NULL\n");
1659             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1660             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1661             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1662         }
1663
1664         efd.total = 0;
1665         SetLastError(0xdeadbeef);
1666         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1667         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1668         if(ret)
1669         {
1670             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1671             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1672                   ansi_charset, symbol_charset, russian_charset);
1673             ok(efd.total == 0, "fonts enumerated: NULL\n");
1674             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1675             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1676             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1677         }
1678     }
1679
1680     efd.total = 0;
1681     SetLastError(0xdeadbeef);
1682     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1683     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1684     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1685     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1686           ansi_charset, symbol_charset, russian_charset,
1687           *font_name ? font_name : "<empty>");
1688     if (*font_name)
1689         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1690     else
1691         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1692     for (i = 0; i < efd.total; i++)
1693     {
1694 /* FIXME: remove completely once Wine is fixed */
1695 if (efd.lf[i].lfCharSet != font_charset)
1696 {
1697 todo_wine
1698     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1699 }
1700 else
1701         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1702         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1703            font_name, efd.lf[i].lfFaceName);
1704     }
1705
1706     memset(&lf, 0, sizeof(lf));
1707     lf.lfCharSet = ANSI_CHARSET;
1708     lstrcpy(lf.lfFaceName, font_name);
1709     efd.total = 0;
1710     SetLastError(0xdeadbeef);
1711     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1712     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1713     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1714     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1715           ansi_charset, symbol_charset, russian_charset,
1716           *font_name ? font_name : "<empty>");
1717     if (font_charset == SYMBOL_CHARSET)
1718     {
1719         if (*font_name)
1720             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1721         else
1722             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1723     }
1724     else
1725     {
1726         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1727         for (i = 0; i < efd.total; i++)
1728         {
1729             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1730             if (*font_name)
1731                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1732                    font_name, efd.lf[i].lfFaceName);
1733         }
1734     }
1735
1736     /* DEFAULT_CHARSET should enumerate all available charsets */
1737     memset(&lf, 0, sizeof(lf));
1738     lf.lfCharSet = DEFAULT_CHARSET;
1739     lstrcpy(lf.lfFaceName, font_name);
1740     efd.total = 0;
1741     SetLastError(0xdeadbeef);
1742     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1743     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1744     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1745     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1746           ansi_charset, symbol_charset, russian_charset,
1747           *font_name ? font_name : "<empty>");
1748     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1749     for (i = 0; i < efd.total; i++)
1750     {
1751         if (*font_name)
1752             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1753                font_name, efd.lf[i].lfFaceName);
1754     }
1755     if (*font_name)
1756     {
1757         switch (font_charset)
1758         {
1759         case ANSI_CHARSET:
1760             ok(ansi_charset > 0,
1761                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1762             ok(!symbol_charset,
1763                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1764             ok(russian_charset > 0,
1765                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1766             break;
1767         case SYMBOL_CHARSET:
1768             ok(!ansi_charset,
1769                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1770             ok(symbol_charset,
1771                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1772             ok(!russian_charset,
1773                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1774             break;
1775         case DEFAULT_CHARSET:
1776             ok(ansi_charset > 0,
1777                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1778             ok(symbol_charset > 0,
1779                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1780             ok(russian_charset > 0,
1781                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1782             break;
1783         }
1784     }
1785     else
1786     {
1787         ok(ansi_charset > 0,
1788            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1789         ok(symbol_charset > 0,
1790            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1791         ok(russian_charset > 0,
1792            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1793     }
1794
1795     memset(&lf, 0, sizeof(lf));
1796     lf.lfCharSet = SYMBOL_CHARSET;
1797     lstrcpy(lf.lfFaceName, font_name);
1798     efd.total = 0;
1799     SetLastError(0xdeadbeef);
1800     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1801     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1802     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1803     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1804           ansi_charset, symbol_charset, russian_charset,
1805           *font_name ? font_name : "<empty>");
1806     if (*font_name && font_charset == ANSI_CHARSET)
1807         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1808     else
1809     {
1810         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1811         for (i = 0; i < efd.total; i++)
1812         {
1813             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1814             if (*font_name)
1815                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1816                    font_name, efd.lf[i].lfFaceName);
1817         }
1818
1819         ok(!ansi_charset,
1820            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1821         ok(symbol_charset > 0,
1822            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1823         ok(!russian_charset,
1824            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1825     }
1826
1827     ReleaseDC(0, hdc);
1828 }
1829
1830 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1831 {
1832     HFONT hfont, hfont_prev;
1833     DWORD ret;
1834     GLYPHMETRICS gm1, gm2;
1835     LOGFONTA lf2 = *lf;
1836     WORD idx;
1837     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1838
1839     if(!pGetGlyphIndicesA)
1840     {
1841         skip("GetGlyphIndicesA is unavailable\n");
1842         return;
1843     }
1844
1845     /* negative widths are handled just as positive ones */
1846     lf2.lfWidth = -lf->lfWidth;
1847
1848     SetLastError(0xdeadbeef);
1849     hfont = CreateFontIndirectA(lf);
1850     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1851     check_font("original", lf, hfont);
1852
1853     hfont_prev = SelectObject(hdc, hfont);
1854
1855     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1856     if (ret == GDI_ERROR || idx == 0xffff)
1857     {
1858         SelectObject(hdc, hfont_prev);
1859         DeleteObject(hfont);
1860         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1861         return;
1862     }
1863
1864     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1865     memset(&gm1, 0xab, sizeof(gm1));
1866     SetLastError(0xdeadbeef);
1867     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1868     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1869
1870     SelectObject(hdc, hfont_prev);
1871     DeleteObject(hfont);
1872
1873     SetLastError(0xdeadbeef);
1874     hfont = CreateFontIndirectA(&lf2);
1875     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1876     check_font("negative width", &lf2, hfont);
1877
1878     hfont_prev = SelectObject(hdc, hfont);
1879
1880     memset(&gm2, 0xbb, sizeof(gm2));
1881     SetLastError(0xdeadbeef);
1882     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
1883     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1884
1885     SelectObject(hdc, hfont_prev);
1886     DeleteObject(hfont);
1887
1888     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
1889        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
1890        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
1891        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
1892        gm1.gmCellIncX == gm2.gmCellIncX &&
1893        gm1.gmCellIncY == gm2.gmCellIncY,
1894        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
1895        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
1896        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
1897        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
1898        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
1899 }
1900
1901 /* PANOSE is 10 bytes in size, need to pack the structure properly */
1902 #include "pshpack2.h"
1903 typedef struct
1904 {
1905     USHORT version;
1906     SHORT xAvgCharWidth;
1907     USHORT usWeightClass;
1908     USHORT usWidthClass;
1909     SHORT fsType;
1910     SHORT ySubscriptXSize;
1911     SHORT ySubscriptYSize;
1912     SHORT ySubscriptXOffset;
1913     SHORT ySubscriptYOffset;
1914     SHORT ySuperscriptXSize;
1915     SHORT ySuperscriptYSize;
1916     SHORT ySuperscriptXOffset;
1917     SHORT ySuperscriptYOffset;
1918     SHORT yStrikeoutSize;
1919     SHORT yStrikeoutPosition;
1920     SHORT sFamilyClass;
1921     PANOSE panose;
1922     ULONG ulUnicodeRange1;
1923     ULONG ulUnicodeRange2;
1924     ULONG ulUnicodeRange3;
1925     ULONG ulUnicodeRange4;
1926     CHAR achVendID[4];
1927     USHORT fsSelection;
1928     USHORT usFirstCharIndex;
1929     USHORT usLastCharIndex;
1930     /* According to the Apple spec, original version didn't have the below fields,
1931      * version numbers were taked from the OpenType spec.
1932      */
1933     /* version 0 (TrueType 1.5) */
1934     USHORT sTypoAscender;
1935     USHORT sTypoDescender;
1936     USHORT sTypoLineGap;
1937     USHORT usWinAscent;
1938     USHORT usWinDescent;
1939     /* version 1 (TrueType 1.66) */
1940     ULONG ulCodePageRange1;
1941     ULONG ulCodePageRange2;
1942     /* version 2 (OpenType 1.2) */
1943     SHORT sxHeight;
1944     SHORT sCapHeight;
1945     USHORT usDefaultChar;
1946     USHORT usBreakChar;
1947     USHORT usMaxContext;
1948 } TT_OS2_V2;
1949 #include "poppack.h"
1950
1951 #ifdef WORDS_BIGENDIAN
1952 #define GET_BE_WORD(x) (x)
1953 #else
1954 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
1955 #endif
1956
1957 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
1958                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
1959                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
1960 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
1961
1962 static void test_text_metrics(const LOGFONTA *lf)
1963 {
1964     HDC hdc;
1965     HFONT hfont, hfont_old;
1966     TEXTMETRICA tmA;
1967     TEXTMETRICW tmW;
1968     UINT first_unicode_char, last_unicode_char, default_char, break_char;
1969     INT test_char;
1970     TT_OS2_V2 tt_os2;
1971     USHORT version;
1972     LONG size, ret;
1973     const char *font_name = lf->lfFaceName;
1974
1975     hdc = GetDC(0);
1976
1977     SetLastError(0xdeadbeef);
1978     hfont = CreateFontIndirectA(lf);
1979     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1980
1981     hfont_old = SelectObject(hdc, hfont);
1982
1983     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1984     if (size == GDI_ERROR)
1985     {
1986         trace("OS/2 chunk was not found\n");
1987         goto end_of_test;
1988     }
1989     if (size > sizeof(tt_os2))
1990     {
1991         trace("got too large OS/2 chunk of size %u\n", size);
1992         size = sizeof(tt_os2);
1993     }
1994
1995     memset(&tt_os2, 0, sizeof(tt_os2));
1996     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
1997     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
1998
1999     version = GET_BE_WORD(tt_os2.version);
2000
2001     first_unicode_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2002     last_unicode_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2003     default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2004     break_char = GET_BE_WORD(tt_os2.usBreakChar);
2005
2006     trace("font %s charset %u: %x-%x default %x break %x OS/2 version %u vendor %4.4s\n",
2007           font_name, lf->lfCharSet, first_unicode_char, last_unicode_char, default_char, break_char,
2008           version, (LPCSTR)&tt_os2.achVendID);
2009
2010     SetLastError(0xdeadbeef);
2011     ret = GetTextMetricsA(hdc, &tmA);
2012     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2013
2014 #if 0 /* FIXME: This doesn't appear to be what Windows does */
2015     test_char = min(first_unicode_char - 1, 255);
2016     ok(tmA.tmFirstChar == test_char, "A: tmFirstChar for %s %02x != %02x\n",
2017        font_name, tmA.tmFirstChar, test_char);
2018 #endif
2019     if (lf->lfCharSet == SYMBOL_CHARSET)
2020     {
2021         test_char = min(last_unicode_char - 0xf000, 255);
2022         ok(tmA.tmLastChar == test_char, "A: tmLastChar for %s %02x != %02x\n",
2023            font_name, tmA.tmLastChar, test_char);
2024     }
2025     else
2026     {
2027         test_char = min(last_unicode_char, 255);
2028         ok(tmA.tmLastChar == test_char, "A: tmLastChar for %s %02x != %02x\n",
2029            font_name, tmA.tmLastChar, test_char);
2030     }
2031
2032     SetLastError(0xdeadbeef);
2033     ret = GetTextMetricsW(hdc, &tmW);
2034     ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2035        "GetTextMetricsW error %u\n", GetLastError());
2036     if (ret)
2037     {
2038         trace("%04x-%04x (%02x-%02x) default %x (%x) break %x (%x)\n",
2039               tmW.tmFirstChar, tmW.tmLastChar, tmA.tmFirstChar, tmA.tmLastChar,
2040               tmW.tmDefaultChar, tmA.tmDefaultChar, tmW.tmBreakChar, tmA.tmBreakChar);
2041
2042         if (lf->lfCharSet == SYMBOL_CHARSET)
2043         {
2044             /* It appears that for fonts with SYMBOL_CHARSET Windows always
2045              * sets symbol range to 0 - f0ff
2046              */
2047             ok(tmW.tmFirstChar == 0, "W: tmFirstChar for %s %02x != 0\n",
2048                font_name, tmW.tmFirstChar);
2049             /* FIXME: Windows returns f0ff here, while Wine f0xx */
2050             ok(tmW.tmLastChar >= 0xf000, "W: tmLastChar for %s %02x < 0xf000\n",
2051                font_name, tmW.tmLastChar);
2052
2053             ok(tmW.tmDefaultChar == 0x1f, "W: tmDefaultChar for %s %02x != 0x1f\n",
2054                font_name, tmW.tmDefaultChar);
2055             ok(tmW.tmBreakChar == 0x20, "W: tmBreakChar for %s %02x != 0x20\n",
2056                font_name, tmW.tmBreakChar);
2057         }
2058         else
2059         {
2060             ok(tmW.tmFirstChar == first_unicode_char, "W: tmFirstChar for %s %02x != %02x\n",
2061                font_name, tmW.tmFirstChar, first_unicode_char);
2062             ok(tmW.tmLastChar == last_unicode_char, "W: tmLastChar for %s %02x != %02x\n",
2063                font_name, tmW.tmLastChar, last_unicode_char);
2064         }
2065         ret = GetDeviceCaps(hdc, LOGPIXELSX);
2066         ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2067            tmW.tmDigitizedAspectX, ret);
2068         ret = GetDeviceCaps(hdc, LOGPIXELSY);
2069         ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2070            tmW.tmDigitizedAspectX, ret);
2071     }
2072
2073     test_negative_width(hdc, lf);
2074
2075 end_of_test:
2076     SelectObject(hdc, hfont_old);
2077     DeleteObject(hfont);
2078
2079     ReleaseDC(0, hdc);
2080 }
2081
2082 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2083 {
2084     INT *enumed = (INT *)lParam;
2085
2086     if (type == TRUETYPE_FONTTYPE)
2087     {
2088         (*enumed)++;
2089         test_text_metrics(lf);
2090     }
2091     return 1;
2092 }
2093
2094 static void test_GetTextMetrics(void)
2095 {
2096     LOGFONTA lf;
2097     HDC hdc;
2098     INT enumed;
2099
2100     hdc = GetDC(0);
2101
2102     memset(&lf, 0, sizeof(lf));
2103     lf.lfCharSet = DEFAULT_CHARSET;
2104     enumed = 0;
2105     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2106     trace("Tested metrics of %d truetype fonts\n", enumed);
2107
2108     ReleaseDC(0, hdc);
2109 }
2110
2111 static void test_nonexistent_font(void)
2112 {
2113     static const struct
2114     {
2115         const char *name;
2116         int charset;
2117     } font_subst[] =
2118     {
2119         { "Times New Roman Baltic", 186 },
2120         { "Times New Roman CE", 238 },
2121         { "Times New Roman CYR", 204 },
2122         { "Times New Roman Greek", 161 },
2123         { "Times New Roman TUR", 162 }
2124     };
2125     LOGFONTA lf;
2126     HDC hdc;
2127     HFONT hfont;
2128     CHARSETINFO csi;
2129     INT cs, expected_cs, i;
2130     char buf[LF_FACESIZE];
2131
2132     if (!is_truetype_font_installed("Arial") ||
2133         !is_truetype_font_installed("Times New Roman"))
2134     {
2135         skip("Arial or Times New Roman not installed\n");
2136         return;
2137     }
2138
2139     expected_cs = GetACP();
2140     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2141     {
2142         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2143         return;
2144     }
2145     expected_cs = csi.ciCharset;
2146     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2147
2148     hdc = GetDC(0);
2149
2150     memset(&lf, 0, sizeof(lf));
2151     lf.lfHeight = 100;
2152     lf.lfWeight = FW_REGULAR;
2153     lf.lfCharSet = ANSI_CHARSET;
2154     lf.lfPitchAndFamily = FF_SWISS;
2155     strcpy(lf.lfFaceName, "Nonexistent font");
2156     hfont = CreateFontIndirectA(&lf);
2157     hfont = SelectObject(hdc, hfont);
2158     GetTextFaceA(hdc, sizeof(buf), buf);
2159     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2160     cs = GetTextCharset(hdc);
2161     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2162     DeleteObject(SelectObject(hdc, hfont));
2163
2164     memset(&lf, 0, sizeof(lf));
2165     lf.lfHeight = -13;
2166     lf.lfWeight = FW_DONTCARE;
2167     strcpy(lf.lfFaceName, "Nonexistent font");
2168     hfont = CreateFontIndirectA(&lf);
2169     hfont = SelectObject(hdc, hfont);
2170     GetTextFaceA(hdc, sizeof(buf), buf);
2171 todo_wine /* Wine uses Arial for all substitutions */
2172     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2173        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2174        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2175        "Got %s\n", buf);
2176     cs = GetTextCharset(hdc);
2177     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2178     DeleteObject(SelectObject(hdc, hfont));
2179
2180     memset(&lf, 0, sizeof(lf));
2181     lf.lfHeight = -13;
2182     lf.lfWeight = FW_REGULAR;
2183     strcpy(lf.lfFaceName, "Nonexistent font");
2184     hfont = CreateFontIndirectA(&lf);
2185     hfont = SelectObject(hdc, hfont);
2186     GetTextFaceA(hdc, sizeof(buf), buf);
2187     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2188        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2189     cs = GetTextCharset(hdc);
2190     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2191     DeleteObject(SelectObject(hdc, hfont));
2192
2193     memset(&lf, 0, sizeof(lf));
2194     lf.lfHeight = -13;
2195     lf.lfWeight = FW_DONTCARE;
2196     strcpy(lf.lfFaceName, "Times New Roman");
2197     hfont = CreateFontIndirectA(&lf);
2198     hfont = SelectObject(hdc, hfont);
2199     GetTextFaceA(hdc, sizeof(buf), buf);
2200     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2201     cs = GetTextCharset(hdc);
2202     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2203     DeleteObject(SelectObject(hdc, hfont));
2204
2205     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2206     {
2207         memset(&lf, 0, sizeof(lf));
2208         lf.lfHeight = -13;
2209         lf.lfWeight = FW_REGULAR;
2210         strcpy(lf.lfFaceName, font_subst[i].name);
2211         hfont = CreateFontIndirectA(&lf);
2212         hfont = SelectObject(hdc, hfont);
2213         cs = GetTextCharset(hdc);
2214         if (font_subst[i].charset == expected_cs)
2215         {
2216             ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2217             GetTextFaceA(hdc, sizeof(buf), buf);
2218             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2219         }
2220         else
2221         {
2222             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2223             GetTextFaceA(hdc, sizeof(buf), buf);
2224             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2225                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s\n", buf);
2226         }
2227         DeleteObject(SelectObject(hdc, hfont));
2228
2229         memset(&lf, 0, sizeof(lf));
2230         lf.lfHeight = -13;
2231         lf.lfWeight = FW_DONTCARE;
2232         strcpy(lf.lfFaceName, font_subst[i].name);
2233         hfont = CreateFontIndirectA(&lf);
2234         hfont = SelectObject(hdc, hfont);
2235         GetTextFaceA(hdc, sizeof(buf), buf);
2236         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2237            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2238            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2239            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2240            "got %s\n", buf);
2241         cs = GetTextCharset(hdc);
2242         ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2243         DeleteObject(SelectObject(hdc, hfont));
2244     }
2245
2246     ReleaseDC(0, hdc);
2247 }
2248
2249 static void test_GdiRealizationInfo(void)
2250 {
2251     HDC hdc;
2252     DWORD info[4];
2253     BOOL r;
2254     HFONT hfont, hfont_old;
2255     LOGFONTA lf;
2256
2257     if(!pGdiRealizationInfo)
2258     {
2259         skip("GdiRealizationInfo not available\n");
2260         return;
2261     }
2262
2263     hdc = GetDC(0);
2264
2265     memset(info, 0xcc, sizeof(info));
2266     r = pGdiRealizationInfo(hdc, info);
2267     ok(r != 0, "ret 0\n");
2268     ok(info[0] == 1, "info[0] = %x for the system font\n", info[0]);
2269     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2270
2271     if (!is_truetype_font_installed("Arial"))
2272     {
2273         skip("skipping GdiRealizationInfo with truetype font\n");
2274         goto end;
2275     }
2276
2277     memset(&lf, 0, sizeof(lf));
2278     strcpy(lf.lfFaceName, "Arial");
2279     lf.lfHeight = 20;
2280     lf.lfWeight = FW_NORMAL;
2281     hfont = CreateFontIndirectA(&lf);
2282     hfont_old = SelectObject(hdc, hfont);
2283
2284     memset(info, 0xcc, sizeof(info));
2285     r = pGdiRealizationInfo(hdc, info);
2286     ok(r != 0, "ret 0\n");
2287     ok(info[0] == 3, "info[0] = %x for arial\n", info[0]);
2288     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2289
2290     DeleteObject(SelectObject(hdc, hfont_old));
2291
2292  end:
2293     ReleaseDC(0, hdc);
2294 }
2295
2296 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2297    the nul in the count of characters copied when the face name buffer is not
2298    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2299    always includes it.  */
2300 static void test_GetTextFace(void)
2301 {
2302     static const char faceA[] = "Tahoma";
2303     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2304     LOGFONTA fA = {0};
2305     LOGFONTW fW = {0};
2306     char bufA[LF_FACESIZE];
2307     WCHAR bufW[LF_FACESIZE];
2308     HFONT f, g;
2309     HDC dc;
2310     int n;
2311
2312     /* 'A' case.  */
2313     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2314     f = CreateFontIndirectA(&fA);
2315     ok(f != NULL, "CreateFontIndirectA failed\n");
2316
2317     dc = GetDC(NULL);
2318     g = SelectObject(dc, f);
2319     n = GetTextFaceA(dc, sizeof bufA, bufA);
2320     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2321     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2322
2323     /* Play with the count arg.  */
2324     bufA[0] = 'x';
2325     n = GetTextFaceA(dc, 0, bufA);
2326     ok(n == 0, "GetTextFaceA returned %d\n", n);
2327     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2328
2329     bufA[0] = 'x';
2330     n = GetTextFaceA(dc, 1, bufA);
2331     ok(n == 0, "GetTextFaceA returned %d\n", n);
2332     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2333
2334     bufA[0] = 'x'; bufA[1] = 'y';
2335     n = GetTextFaceA(dc, 2, bufA);
2336     ok(n == 1, "GetTextFaceA returned %d\n", n);
2337     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2338
2339     n = GetTextFaceA(dc, 0, NULL);
2340     ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n);
2341
2342     DeleteObject(SelectObject(dc, g));
2343     ReleaseDC(NULL, dc);
2344
2345     /* 'W' case.  */
2346     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2347     f = CreateFontIndirectW(&fW);
2348     ok(f != NULL, "CreateFontIndirectW failed\n");
2349
2350     dc = GetDC(NULL);
2351     g = SelectObject(dc, f);
2352     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2353     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2354     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2355
2356     /* Play with the count arg.  */
2357     bufW[0] = 'x';
2358     n = GetTextFaceW(dc, 0, bufW);
2359     ok(n == 0, "GetTextFaceW returned %d\n", n);
2360     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2361
2362     bufW[0] = 'x';
2363     n = GetTextFaceW(dc, 1, bufW);
2364     ok(n == 1, "GetTextFaceW returned %d\n", n);
2365     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2366
2367     bufW[0] = 'x'; bufW[1] = 'y';
2368     n = GetTextFaceW(dc, 2, bufW);
2369     ok(n == 2, "GetTextFaceW returned %d\n", n);
2370     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2371
2372     n = GetTextFaceW(dc, 0, NULL);
2373     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2374
2375     DeleteObject(SelectObject(dc, g));
2376     ReleaseDC(NULL, dc);
2377 }
2378
2379 START_TEST(font)
2380 {
2381     init();
2382
2383     test_logfont();
2384     test_bitmap_font();
2385     test_outline_font();
2386     test_bitmap_font_metrics();
2387     test_GdiGetCharDimensions();
2388     test_GetCharABCWidths();
2389     test_text_extents();
2390     test_GetGlyphIndices();
2391     test_GetKerningPairs();
2392     test_GetOutlineTextMetrics();
2393     test_SetTextJustification();
2394     test_font_charset();
2395     test_GetFontUnicodeRanges();
2396     test_nonexistent_font();
2397
2398     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
2399      * I'd like to avoid them in this test.
2400      */
2401     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
2402     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
2403     if (is_truetype_font_installed("Arial Black") &&
2404         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
2405     {
2406         test_EnumFontFamilies("", ANSI_CHARSET);
2407         test_EnumFontFamilies("", SYMBOL_CHARSET);
2408         test_EnumFontFamilies("", DEFAULT_CHARSET);
2409     }
2410     else
2411         skip("Arial Black or Symbol/Wingdings is not installed\n");
2412     test_GetTextMetrics();
2413     test_GdiRealizationInfo();
2414     test_GetTextFace();
2415 }