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