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