gdi32/tests: Fix an uninitialized pointer check for Win64.
[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     LPSTR unset_ptr;
1189
1190     if (!is_font_installed("Arial"))
1191     {
1192         skip("Arial is not installed\n");
1193         return;
1194     }
1195
1196     hdc = GetDC(0);
1197
1198     memset(&lf, 0, sizeof(lf));
1199     strcpy(lf.lfFaceName, "Arial");
1200     lf.lfHeight = -13;
1201     lf.lfWeight = FW_NORMAL;
1202     lf.lfPitchAndFamily = DEFAULT_PITCH;
1203     lf.lfQuality = PROOF_QUALITY;
1204     hfont = CreateFontIndirect(&lf);
1205     assert(hfont != 0);
1206
1207     hfont_old = SelectObject(hdc, hfont);
1208     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1209     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1210
1211     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1212
1213     memset(otm, 0xAA, otm_size);
1214     SetLastError(0xdeadbeef);
1215     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1216     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1217     ok(ret == 1 /* Win9x */ ||
1218        ret == otm->otmSize /* XP*/,
1219        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1220     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1221     {
1222         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1223         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1224         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1225         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1226     }
1227
1228     memset(otm, 0xAA, otm_size);
1229     SetLastError(0xdeadbeef);
1230     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1231     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1232     ok(ret == 1 /* Win9x */ ||
1233        ret == otm->otmSize /* XP*/,
1234        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1235     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1236     {
1237         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1238         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1239         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1240         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1241     }
1242
1243     /* ask about truncated data */
1244     memset(otm, 0xAA, otm_size);
1245     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1246     SetLastError(0xdeadbeef);
1247     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1248     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1249     ok(ret == 1 /* Win9x */ ||
1250        ret == otm->otmSize /* XP*/,
1251        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1252     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1253     {
1254         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1255         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1256         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1257     }
1258     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1259
1260     HeapFree(GetProcessHeap(), 0, otm);
1261
1262     SelectObject(hdc, hfont_old);
1263     DeleteObject(hfont);
1264
1265     ReleaseDC(0, hdc);
1266 }
1267
1268 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1269 {
1270     INT         x, y,
1271                 breakCount,
1272                 outputWidth = 0,    /* to test TabbedTextOut() */
1273                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1274                 areaWidth = clientArea->right - clientArea->left,
1275                 nErrors = 0, e;
1276     BOOL        lastExtent = FALSE;
1277     PSTR        pFirstChar, pLastChar;
1278     SIZE        size;
1279     TEXTMETRICA tm;
1280     struct err
1281     {
1282         char extent[100];
1283         int  GetTextExtentExPointWWidth;
1284         int  TabbedTextOutWidth;
1285     } error[10];
1286
1287     GetTextMetricsA(hdc, &tm);
1288     y = clientArea->top;
1289     do {
1290         breakCount = 0;
1291         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1292         pFirstChar = str;
1293
1294         do {
1295             pLastChar = str;
1296
1297             /* if not at the end of the string, ... */
1298             if (*str == '\0') break;
1299             /* ... add the next word to the current extent */
1300             while (*str != '\0' && *str++ != tm.tmBreakChar);
1301             breakCount++;
1302             SetTextJustification(hdc, 0, 0);
1303             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1304         } while ((int) size.cx < areaWidth);
1305
1306         /* ignore trailing break chars */
1307         breakCount--;
1308         while (*(pLastChar - 1) == tm.tmBreakChar)
1309         {
1310             pLastChar--;
1311             breakCount--;
1312         }
1313
1314         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1315
1316         SetTextJustification(hdc, 0, 0);
1317         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1318
1319         /* do not justify the last extent */
1320         if (*str != '\0' && breakCount > 0)
1321         {
1322             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1323             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1324             justifiedWidth = size.cx;
1325         }
1326         else lastExtent = TRUE;
1327
1328         x = clientArea->left;
1329
1330         outputWidth = LOWORD(TabbedTextOut(
1331                              hdc, x, y, pFirstChar, pLastChar - pFirstChar,
1332                              0, NULL, 0));
1333         /* catch errors and report them */
1334         if (!lastExtent && ((outputWidth != areaWidth) || (justifiedWidth != areaWidth)))
1335         {
1336             memset(error[nErrors].extent, 0, 100);
1337             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1338             error[nErrors].TabbedTextOutWidth = outputWidth;
1339             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1340             nErrors++;
1341         }
1342
1343         y += size.cy;
1344         str = pLastChar;
1345     } while (*str && y < clientArea->bottom);
1346
1347     for (e = 0; e < nErrors; e++)
1348     {
1349         ok(near_match(error[e].TabbedTextOutWidth, areaWidth),
1350             "The output text (\"%s\") width should be %d, not %d.\n",
1351             error[e].extent, areaWidth, error[e].TabbedTextOutWidth);
1352         /* The width returned by GetTextExtentPoint32() is exactly the same
1353            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1354         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1355             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1356             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1357     }
1358 }
1359
1360 static void test_SetTextJustification(void)
1361 {
1362     HDC hdc;
1363     RECT clientArea;
1364     LOGFONTA lf;
1365     HFONT hfont;
1366     HWND hwnd;
1367     static char testText[] =
1368             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1369             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1370             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1371             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1372             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1373             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1374             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1375
1376     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1377     GetClientRect( hwnd, &clientArea );
1378     hdc = GetDC( hwnd );
1379
1380     memset(&lf, 0, sizeof lf);
1381     lf.lfCharSet = ANSI_CHARSET;
1382     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1383     lf.lfWeight = FW_DONTCARE;
1384     lf.lfHeight = 20;
1385     lf.lfQuality = DEFAULT_QUALITY;
1386     lstrcpyA(lf.lfFaceName, "Times New Roman");
1387     hfont = create_font("Times New Roman", &lf);
1388     SelectObject(hdc, hfont);
1389
1390     testJustification(hdc, testText, &clientArea);
1391
1392     DeleteObject(hfont);
1393     ReleaseDC(hwnd, hdc);
1394     DestroyWindow(hwnd);
1395 }
1396
1397 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1398 {
1399     HDC hdc;
1400     LOGFONTA lf;
1401     HFONT hfont, hfont_old;
1402     CHARSETINFO csi;
1403     FONTSIGNATURE fs;
1404     INT cs;
1405     DWORD i, ret;
1406     char name[64];
1407
1408     assert(count <= 128);
1409
1410     memset(&lf, 0, sizeof(lf));
1411
1412     lf.lfCharSet = charset;
1413     lf.lfHeight = 10;
1414     lstrcpyA(lf.lfFaceName, "Arial");
1415     SetLastError(0xdeadbeef);
1416     hfont = CreateFontIndirectA(&lf);
1417     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1418
1419     hdc = GetDC(0);
1420     hfont_old = SelectObject(hdc, hfont);
1421
1422     cs = GetTextCharsetInfo(hdc, &fs, 0);
1423     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1424
1425     SetLastError(0xdeadbeef);
1426     ret = GetTextFaceA(hdc, sizeof(name), name);
1427     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1428
1429     if (charset == SYMBOL_CHARSET)
1430     {
1431         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1432         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1433     }
1434     else
1435     {
1436         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1437         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1438     }
1439
1440     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1441     {
1442         trace("Can't find codepage for charset %d\n", cs);
1443         ReleaseDC(0, hdc);
1444         return FALSE;
1445     }
1446     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1447
1448     if (unicode)
1449     {
1450         char ansi_buf[128];
1451         WCHAR unicode_buf[128];
1452
1453         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1454
1455         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1456
1457         SetLastError(0xdeadbeef);
1458         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1459         ok(ret == count, "GetGlyphIndicesW error %u\n", GetLastError());
1460     }
1461     else
1462     {
1463         char ansi_buf[128];
1464
1465         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1466
1467         SetLastError(0xdeadbeef);
1468         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1469         ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
1470     }
1471
1472     SelectObject(hdc, hfont_old);
1473     DeleteObject(hfont);
1474
1475     ReleaseDC(0, hdc);
1476
1477     return TRUE;
1478 }
1479
1480 static void test_font_charset(void)
1481 {
1482     static struct charset_data
1483     {
1484         INT charset;
1485         UINT code_page;
1486         WORD font_idxA[128], font_idxW[128];
1487     } cd[] =
1488     {
1489         { ANSI_CHARSET, 1252 },
1490         { RUSSIAN_CHARSET, 1251 },
1491         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1492     };
1493     int i;
1494
1495     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1496     {
1497         skip("Skipping the font charset test on a Win9x platform\n");
1498         return;
1499     }
1500
1501     if (!is_font_installed("Arial"))
1502     {
1503         skip("Arial is not installed\n");
1504         return;
1505     }
1506
1507     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1508     {
1509         if (cd[i].charset == SYMBOL_CHARSET)
1510         {
1511             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1512             {
1513                 skip("Symbol or Wingdings is not installed\n");
1514                 break;
1515             }
1516         }
1517         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
1518         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
1519         ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1520     }
1521
1522     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1523     if (i > 2)
1524     {
1525         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1526         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1527     }
1528     else
1529         skip("Symbol or Wingdings is not installed\n");
1530 }
1531
1532 static void test_GetFontUnicodeRanges(void)
1533 {
1534     LOGFONTA lf;
1535     HDC hdc;
1536     HFONT hfont, hfont_old;
1537     DWORD size;
1538     GLYPHSET *gs;
1539
1540     if (!pGetFontUnicodeRanges)
1541     {
1542         skip("GetFontUnicodeRanges not available before W2K\n");
1543         return;
1544     }
1545
1546     memset(&lf, 0, sizeof(lf));
1547     lstrcpyA(lf.lfFaceName, "Arial");
1548     hfont = create_font("Arial", &lf);
1549
1550     hdc = GetDC(0);
1551     hfont_old = SelectObject(hdc, hfont);
1552
1553     size = pGetFontUnicodeRanges(NULL, NULL);
1554     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1555
1556     size = pGetFontUnicodeRanges(hdc, NULL);
1557     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1558
1559     gs = HeapAlloc(GetProcessHeap(), 0, size);
1560
1561     size = pGetFontUnicodeRanges(hdc, gs);
1562     ok(size, "GetFontUnicodeRanges failed\n");
1563 #if 0
1564     for (i = 0; i < gs->cRanges; i++)
1565         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1566 #endif
1567     trace("found %u ranges\n", gs->cRanges);
1568
1569     HeapFree(GetProcessHeap(), 0, gs);
1570
1571     SelectObject(hdc, hfont_old);
1572     DeleteObject(hfont);
1573     ReleaseDC(NULL, hdc);
1574 }
1575
1576 #define MAX_ENUM_FONTS 4096
1577
1578 struct enum_font_data
1579 {
1580     int total;
1581     LOGFONT lf[MAX_ENUM_FONTS];
1582 };
1583
1584 struct enum_font_dataW
1585 {
1586     int total;
1587     LOGFONTW lf[MAX_ENUM_FONTS];
1588 };
1589
1590 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1591 {
1592     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1593
1594     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1595
1596     if (type != TRUETYPE_FONTTYPE) return 1;
1597 #if 0
1598     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1599           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1600 #endif
1601     if (efd->total < MAX_ENUM_FONTS)
1602         efd->lf[efd->total++] = *lf;
1603     else
1604         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1605
1606     return 1;
1607 }
1608
1609 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1610 {
1611     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1612
1613     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1614
1615     if (type != TRUETYPE_FONTTYPE) return 1;
1616 #if 0
1617     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1618           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1619 #endif
1620     if (efd->total < MAX_ENUM_FONTS)
1621         efd->lf[efd->total++] = *lf;
1622     else
1623         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1624
1625     return 1;
1626 }
1627
1628 static void get_charset_stats(struct enum_font_data *efd,
1629                               int *ansi_charset, int *symbol_charset,
1630                               int *russian_charset)
1631 {
1632     int i;
1633
1634     *ansi_charset = 0;
1635     *symbol_charset = 0;
1636     *russian_charset = 0;
1637
1638     for (i = 0; i < efd->total; i++)
1639     {
1640         switch (efd->lf[i].lfCharSet)
1641         {
1642         case ANSI_CHARSET:
1643             (*ansi_charset)++;
1644             break;
1645         case SYMBOL_CHARSET:
1646             (*symbol_charset)++;
1647             break;
1648         case RUSSIAN_CHARSET:
1649             (*russian_charset)++;
1650             break;
1651         }
1652     }
1653 }
1654
1655 static void get_charset_statsW(struct enum_font_dataW *efd,
1656                               int *ansi_charset, int *symbol_charset,
1657                               int *russian_charset)
1658 {
1659     int i;
1660
1661     *ansi_charset = 0;
1662     *symbol_charset = 0;
1663     *russian_charset = 0;
1664
1665     for (i = 0; i < efd->total; i++)
1666     {
1667         switch (efd->lf[i].lfCharSet)
1668         {
1669         case ANSI_CHARSET:
1670             (*ansi_charset)++;
1671             break;
1672         case SYMBOL_CHARSET:
1673             (*symbol_charset)++;
1674             break;
1675         case RUSSIAN_CHARSET:
1676             (*russian_charset)++;
1677             break;
1678         }
1679     }
1680 }
1681
1682 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1683 {
1684     struct enum_font_data efd;
1685     struct enum_font_dataW efdw;
1686     LOGFONT lf;
1687     HDC hdc;
1688     int i, ret, ansi_charset, symbol_charset, russian_charset;
1689
1690     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1691
1692     if (*font_name && !is_truetype_font_installed(font_name))
1693     {
1694         skip("%s is not installed\n", font_name);
1695         return;
1696     }
1697
1698     hdc = GetDC(0);
1699
1700     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1701      * while EnumFontFamiliesEx doesn't.
1702      */
1703     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1704     {
1705         /*
1706          * Use EnumFontFamiliesW since win98 crashes when the
1707          *    second parameter is NULL using EnumFontFamilies
1708          */
1709         efdw.total = 0;
1710         SetLastError(0xdeadbeef);
1711         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1712         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1713         if(ret)
1714         {
1715             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1716             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1717                   ansi_charset, symbol_charset, russian_charset);
1718             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1719             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1720             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1721             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1722         }
1723
1724         efdw.total = 0;
1725         SetLastError(0xdeadbeef);
1726         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1727         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1728         if(ret)
1729         {
1730             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1731             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1732                   ansi_charset, symbol_charset, russian_charset);
1733             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1734             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1735             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1736             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1737         }
1738     }
1739
1740     efd.total = 0;
1741     SetLastError(0xdeadbeef);
1742     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1743     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1744     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1745     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1746           ansi_charset, symbol_charset, russian_charset,
1747           *font_name ? font_name : "<empty>");
1748     if (*font_name)
1749         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1750     else
1751         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1752     for (i = 0; i < efd.total; i++)
1753     {
1754 /* FIXME: remove completely once Wine is fixed */
1755 if (efd.lf[i].lfCharSet != font_charset)
1756 {
1757 todo_wine
1758     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1759 }
1760 else
1761         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1762         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1763            font_name, efd.lf[i].lfFaceName);
1764     }
1765
1766     memset(&lf, 0, sizeof(lf));
1767     lf.lfCharSet = ANSI_CHARSET;
1768     lstrcpy(lf.lfFaceName, font_name);
1769     efd.total = 0;
1770     SetLastError(0xdeadbeef);
1771     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1772     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1773     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1774     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1775           ansi_charset, symbol_charset, russian_charset,
1776           *font_name ? font_name : "<empty>");
1777     if (font_charset == SYMBOL_CHARSET)
1778     {
1779         if (*font_name)
1780             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1781         else
1782             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1783     }
1784     else
1785     {
1786         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1787         for (i = 0; i < efd.total; i++)
1788         {
1789             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1790             if (*font_name)
1791                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1792                    font_name, efd.lf[i].lfFaceName);
1793         }
1794     }
1795
1796     /* DEFAULT_CHARSET should enumerate all available charsets */
1797     memset(&lf, 0, sizeof(lf));
1798     lf.lfCharSet = DEFAULT_CHARSET;
1799     lstrcpy(lf.lfFaceName, font_name);
1800     efd.total = 0;
1801     SetLastError(0xdeadbeef);
1802     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1803     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1804     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1805     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1806           ansi_charset, symbol_charset, russian_charset,
1807           *font_name ? font_name : "<empty>");
1808     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1809     for (i = 0; i < efd.total; i++)
1810     {
1811         if (*font_name)
1812             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1813                font_name, efd.lf[i].lfFaceName);
1814     }
1815     if (*font_name)
1816     {
1817         switch (font_charset)
1818         {
1819         case ANSI_CHARSET:
1820             ok(ansi_charset > 0,
1821                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1822             ok(!symbol_charset,
1823                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1824             ok(russian_charset > 0,
1825                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1826             break;
1827         case SYMBOL_CHARSET:
1828             ok(!ansi_charset,
1829                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1830             ok(symbol_charset,
1831                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1832             ok(!russian_charset,
1833                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1834             break;
1835         case DEFAULT_CHARSET:
1836             ok(ansi_charset > 0,
1837                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1838             ok(symbol_charset > 0,
1839                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1840             ok(russian_charset > 0,
1841                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1842             break;
1843         }
1844     }
1845     else
1846     {
1847         ok(ansi_charset > 0,
1848            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1849         ok(symbol_charset > 0,
1850            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1851         ok(russian_charset > 0,
1852            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1853     }
1854
1855     memset(&lf, 0, sizeof(lf));
1856     lf.lfCharSet = SYMBOL_CHARSET;
1857     lstrcpy(lf.lfFaceName, font_name);
1858     efd.total = 0;
1859     SetLastError(0xdeadbeef);
1860     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1861     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1862     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1863     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1864           ansi_charset, symbol_charset, russian_charset,
1865           *font_name ? font_name : "<empty>");
1866     if (*font_name && font_charset == ANSI_CHARSET)
1867         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1868     else
1869     {
1870         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1871         for (i = 0; i < efd.total; i++)
1872         {
1873             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1874             if (*font_name)
1875                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1876                    font_name, efd.lf[i].lfFaceName);
1877         }
1878
1879         ok(!ansi_charset,
1880            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1881         ok(symbol_charset > 0,
1882            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1883         ok(!russian_charset,
1884            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1885     }
1886
1887     ReleaseDC(0, hdc);
1888 }
1889
1890 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1891 {
1892     HFONT hfont, hfont_prev;
1893     DWORD ret;
1894     GLYPHMETRICS gm1, gm2;
1895     LOGFONTA lf2 = *lf;
1896     WORD idx;
1897     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1898
1899     if(!pGetGlyphIndicesA)
1900     {
1901         skip("GetGlyphIndicesA is unavailable\n");
1902         return;
1903     }
1904
1905     /* negative widths are handled just as positive ones */
1906     lf2.lfWidth = -lf->lfWidth;
1907
1908     SetLastError(0xdeadbeef);
1909     hfont = CreateFontIndirectA(lf);
1910     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1911     check_font("original", lf, hfont);
1912
1913     hfont_prev = SelectObject(hdc, hfont);
1914
1915     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1916     if (ret == GDI_ERROR || idx == 0xffff)
1917     {
1918         SelectObject(hdc, hfont_prev);
1919         DeleteObject(hfont);
1920         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1921         return;
1922     }
1923
1924     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1925     memset(&gm1, 0xab, sizeof(gm1));
1926     SetLastError(0xdeadbeef);
1927     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1928     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1929
1930     SelectObject(hdc, hfont_prev);
1931     DeleteObject(hfont);
1932
1933     SetLastError(0xdeadbeef);
1934     hfont = CreateFontIndirectA(&lf2);
1935     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1936     check_font("negative width", &lf2, hfont);
1937
1938     hfont_prev = SelectObject(hdc, hfont);
1939
1940     memset(&gm2, 0xbb, sizeof(gm2));
1941     SetLastError(0xdeadbeef);
1942     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
1943     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1944
1945     SelectObject(hdc, hfont_prev);
1946     DeleteObject(hfont);
1947
1948     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
1949        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
1950        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
1951        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
1952        gm1.gmCellIncX == gm2.gmCellIncX &&
1953        gm1.gmCellIncY == gm2.gmCellIncY,
1954        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
1955        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
1956        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
1957        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
1958        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
1959 }
1960
1961 /* PANOSE is 10 bytes in size, need to pack the structure properly */
1962 #include "pshpack2.h"
1963 typedef struct
1964 {
1965     USHORT version;
1966     SHORT xAvgCharWidth;
1967     USHORT usWeightClass;
1968     USHORT usWidthClass;
1969     SHORT fsType;
1970     SHORT ySubscriptXSize;
1971     SHORT ySubscriptYSize;
1972     SHORT ySubscriptXOffset;
1973     SHORT ySubscriptYOffset;
1974     SHORT ySuperscriptXSize;
1975     SHORT ySuperscriptYSize;
1976     SHORT ySuperscriptXOffset;
1977     SHORT ySuperscriptYOffset;
1978     SHORT yStrikeoutSize;
1979     SHORT yStrikeoutPosition;
1980     SHORT sFamilyClass;
1981     PANOSE panose;
1982     ULONG ulUnicodeRange1;
1983     ULONG ulUnicodeRange2;
1984     ULONG ulUnicodeRange3;
1985     ULONG ulUnicodeRange4;
1986     CHAR achVendID[4];
1987     USHORT fsSelection;
1988     USHORT usFirstCharIndex;
1989     USHORT usLastCharIndex;
1990     /* According to the Apple spec, original version didn't have the below fields,
1991      * version numbers were taked from the OpenType spec.
1992      */
1993     /* version 0 (TrueType 1.5) */
1994     USHORT sTypoAscender;
1995     USHORT sTypoDescender;
1996     USHORT sTypoLineGap;
1997     USHORT usWinAscent;
1998     USHORT usWinDescent;
1999     /* version 1 (TrueType 1.66) */
2000     ULONG ulCodePageRange1;
2001     ULONG ulCodePageRange2;
2002     /* version 2 (OpenType 1.2) */
2003     SHORT sxHeight;
2004     SHORT sCapHeight;
2005     USHORT usDefaultChar;
2006     USHORT usBreakChar;
2007     USHORT usMaxContext;
2008 } TT_OS2_V2;
2009 #include "poppack.h"
2010
2011 #ifdef WORDS_BIGENDIAN
2012 #define GET_BE_WORD(x) (x)
2013 #else
2014 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2015 #endif
2016
2017 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2018                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2019                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2020 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2021
2022 static void test_text_metrics(const LOGFONTA *lf)
2023 {
2024     HDC hdc;
2025     HFONT hfont, hfont_old;
2026     TEXTMETRICA tmA;
2027     TEXTMETRICW tmW;
2028     UINT first_unicode_char, last_unicode_char, default_char, break_char;
2029     INT test_char;
2030     TT_OS2_V2 tt_os2;
2031     USHORT version;
2032     LONG size, ret;
2033     const char *font_name = lf->lfFaceName;
2034
2035     hdc = GetDC(0);
2036
2037     SetLastError(0xdeadbeef);
2038     hfont = CreateFontIndirectA(lf);
2039     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2040
2041     hfont_old = SelectObject(hdc, hfont);
2042
2043     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2044     if (size == GDI_ERROR)
2045     {
2046         trace("OS/2 chunk was not found\n");
2047         goto end_of_test;
2048     }
2049     if (size > sizeof(tt_os2))
2050     {
2051         trace("got too large OS/2 chunk of size %u\n", size);
2052         size = sizeof(tt_os2);
2053     }
2054
2055     memset(&tt_os2, 0, sizeof(tt_os2));
2056     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2057     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2058
2059     version = GET_BE_WORD(tt_os2.version);
2060
2061     first_unicode_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2062     last_unicode_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2063     default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2064     break_char = GET_BE_WORD(tt_os2.usBreakChar);
2065
2066     trace("font %s charset %u: %x-%x default %x break %x OS/2 version %u vendor %4.4s\n",
2067           font_name, lf->lfCharSet, first_unicode_char, last_unicode_char, default_char, break_char,
2068           version, (LPCSTR)&tt_os2.achVendID);
2069
2070     SetLastError(0xdeadbeef);
2071     ret = GetTextMetricsA(hdc, &tmA);
2072     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2073
2074 #if 0 /* FIXME: This doesn't appear to be what Windows does */
2075     test_char = min(first_unicode_char - 1, 255);
2076     ok(tmA.tmFirstChar == test_char, "A: tmFirstChar for %s %02x != %02x\n",
2077        font_name, tmA.tmFirstChar, test_char);
2078 #endif
2079     if (lf->lfCharSet == SYMBOL_CHARSET)
2080     {
2081         test_char = min(last_unicode_char - 0xf000, 255);
2082         ok(tmA.tmLastChar == test_char, "A: tmLastChar for %s %02x != %02x\n",
2083            font_name, tmA.tmLastChar, test_char);
2084     }
2085     else
2086     {
2087         test_char = min(last_unicode_char, 255);
2088         ok(tmA.tmLastChar == test_char, "A: tmLastChar for %s %02x != %02x\n",
2089            font_name, tmA.tmLastChar, test_char);
2090     }
2091
2092     SetLastError(0xdeadbeef);
2093     ret = GetTextMetricsW(hdc, &tmW);
2094     ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2095        "GetTextMetricsW error %u\n", GetLastError());
2096     if (ret)
2097     {
2098         trace("%04x-%04x (%02x-%02x) default %x (%x) break %x (%x)\n",
2099               tmW.tmFirstChar, tmW.tmLastChar, tmA.tmFirstChar, tmA.tmLastChar,
2100               tmW.tmDefaultChar, tmA.tmDefaultChar, tmW.tmBreakChar, tmA.tmBreakChar);
2101
2102         if (lf->lfCharSet == SYMBOL_CHARSET)
2103         {
2104             /* It appears that for fonts with SYMBOL_CHARSET Windows always
2105              * sets symbol range to 0 - f0ff
2106              */
2107             ok(tmW.tmFirstChar == 0, "W: tmFirstChar for %s %02x != 0\n",
2108                font_name, tmW.tmFirstChar);
2109             /* FIXME: Windows returns f0ff here, while Wine f0xx */
2110             ok(tmW.tmLastChar >= 0xf000, "W: tmLastChar for %s %02x < 0xf000\n",
2111                font_name, tmW.tmLastChar);
2112
2113             ok(tmW.tmDefaultChar == 0x1f, "W: tmDefaultChar for %s %02x != 0x1f\n",
2114                font_name, tmW.tmDefaultChar);
2115             ok(tmW.tmBreakChar == 0x20, "W: tmBreakChar for %s %02x != 0x20\n",
2116                font_name, tmW.tmBreakChar);
2117         }
2118         else
2119         {
2120             ok(tmW.tmFirstChar == first_unicode_char, "W: tmFirstChar for %s %02x != %02x\n",
2121                font_name, tmW.tmFirstChar, first_unicode_char);
2122             ok(tmW.tmLastChar == last_unicode_char, "W: tmLastChar for %s %02x != %02x\n",
2123                font_name, tmW.tmLastChar, last_unicode_char);
2124         }
2125         ret = GetDeviceCaps(hdc, LOGPIXELSX);
2126         ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2127            tmW.tmDigitizedAspectX, ret);
2128         ret = GetDeviceCaps(hdc, LOGPIXELSY);
2129         ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2130            tmW.tmDigitizedAspectX, ret);
2131     }
2132
2133     test_negative_width(hdc, lf);
2134
2135 end_of_test:
2136     SelectObject(hdc, hfont_old);
2137     DeleteObject(hfont);
2138
2139     ReleaseDC(0, hdc);
2140 }
2141
2142 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2143 {
2144     INT *enumed = (INT *)lParam;
2145
2146     if (type == TRUETYPE_FONTTYPE)
2147     {
2148         (*enumed)++;
2149         test_text_metrics(lf);
2150     }
2151     return 1;
2152 }
2153
2154 static void test_GetTextMetrics(void)
2155 {
2156     LOGFONTA lf;
2157     HDC hdc;
2158     INT enumed;
2159
2160     hdc = GetDC(0);
2161
2162     memset(&lf, 0, sizeof(lf));
2163     lf.lfCharSet = DEFAULT_CHARSET;
2164     enumed = 0;
2165     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2166     trace("Tested metrics of %d truetype fonts\n", enumed);
2167
2168     ReleaseDC(0, hdc);
2169 }
2170
2171 static void test_nonexistent_font(void)
2172 {
2173     static const struct
2174     {
2175         const char *name;
2176         int charset;
2177     } font_subst[] =
2178     {
2179         { "Times New Roman Baltic", 186 },
2180         { "Times New Roman CE", 238 },
2181         { "Times New Roman CYR", 204 },
2182         { "Times New Roman Greek", 161 },
2183         { "Times New Roman TUR", 162 }
2184     };
2185     LOGFONTA lf;
2186     HDC hdc;
2187     HFONT hfont;
2188     CHARSETINFO csi;
2189     INT cs, expected_cs, i;
2190     char buf[LF_FACESIZE];
2191
2192     if (!is_truetype_font_installed("Arial") ||
2193         !is_truetype_font_installed("Times New Roman"))
2194     {
2195         skip("Arial or Times New Roman not installed\n");
2196         return;
2197     }
2198
2199     expected_cs = GetACP();
2200     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2201     {
2202         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2203         return;
2204     }
2205     expected_cs = csi.ciCharset;
2206     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2207
2208     hdc = GetDC(0);
2209
2210     memset(&lf, 0, sizeof(lf));
2211     lf.lfHeight = 100;
2212     lf.lfWeight = FW_REGULAR;
2213     lf.lfCharSet = ANSI_CHARSET;
2214     lf.lfPitchAndFamily = FF_SWISS;
2215     strcpy(lf.lfFaceName, "Nonexistent font");
2216     hfont = CreateFontIndirectA(&lf);
2217     hfont = SelectObject(hdc, hfont);
2218     GetTextFaceA(hdc, sizeof(buf), buf);
2219     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2220     cs = GetTextCharset(hdc);
2221     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2222     DeleteObject(SelectObject(hdc, hfont));
2223
2224     memset(&lf, 0, sizeof(lf));
2225     lf.lfHeight = -13;
2226     lf.lfWeight = FW_DONTCARE;
2227     strcpy(lf.lfFaceName, "Nonexistent font");
2228     hfont = CreateFontIndirectA(&lf);
2229     hfont = SelectObject(hdc, hfont);
2230     GetTextFaceA(hdc, sizeof(buf), buf);
2231 todo_wine /* Wine uses Arial for all substitutions */
2232     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2233        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2234        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2235        "Got %s\n", buf);
2236     cs = GetTextCharset(hdc);
2237     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2238     DeleteObject(SelectObject(hdc, hfont));
2239
2240     memset(&lf, 0, sizeof(lf));
2241     lf.lfHeight = -13;
2242     lf.lfWeight = FW_REGULAR;
2243     strcpy(lf.lfFaceName, "Nonexistent font");
2244     hfont = CreateFontIndirectA(&lf);
2245     hfont = SelectObject(hdc, hfont);
2246     GetTextFaceA(hdc, sizeof(buf), buf);
2247     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2248        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2249     cs = GetTextCharset(hdc);
2250     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2251     DeleteObject(SelectObject(hdc, hfont));
2252
2253     memset(&lf, 0, sizeof(lf));
2254     lf.lfHeight = -13;
2255     lf.lfWeight = FW_DONTCARE;
2256     strcpy(lf.lfFaceName, "Times New Roman");
2257     hfont = CreateFontIndirectA(&lf);
2258     hfont = SelectObject(hdc, hfont);
2259     GetTextFaceA(hdc, sizeof(buf), buf);
2260     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2261     cs = GetTextCharset(hdc);
2262     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2263     DeleteObject(SelectObject(hdc, hfont));
2264
2265     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2266     {
2267         memset(&lf, 0, sizeof(lf));
2268         lf.lfHeight = -13;
2269         lf.lfWeight = FW_REGULAR;
2270         strcpy(lf.lfFaceName, font_subst[i].name);
2271         hfont = CreateFontIndirectA(&lf);
2272         hfont = SelectObject(hdc, hfont);
2273         cs = GetTextCharset(hdc);
2274         if (font_subst[i].charset == expected_cs)
2275         {
2276             ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2277             GetTextFaceA(hdc, sizeof(buf), buf);
2278             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2279         }
2280         else
2281         {
2282             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2283             GetTextFaceA(hdc, sizeof(buf), buf);
2284             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2285                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s\n", buf);
2286         }
2287         DeleteObject(SelectObject(hdc, hfont));
2288
2289         memset(&lf, 0, sizeof(lf));
2290         lf.lfHeight = -13;
2291         lf.lfWeight = FW_DONTCARE;
2292         strcpy(lf.lfFaceName, font_subst[i].name);
2293         hfont = CreateFontIndirectA(&lf);
2294         hfont = SelectObject(hdc, hfont);
2295         GetTextFaceA(hdc, sizeof(buf), buf);
2296         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2297            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2298            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2299            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2300            "got %s\n", buf);
2301         cs = GetTextCharset(hdc);
2302         ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2303         DeleteObject(SelectObject(hdc, hfont));
2304     }
2305
2306     ReleaseDC(0, hdc);
2307 }
2308
2309 static void test_GdiRealizationInfo(void)
2310 {
2311     HDC hdc;
2312     DWORD info[4];
2313     BOOL r;
2314     HFONT hfont, hfont_old;
2315     LOGFONTA lf;
2316
2317     if(!pGdiRealizationInfo)
2318     {
2319         skip("GdiRealizationInfo not available\n");
2320         return;
2321     }
2322
2323     hdc = GetDC(0);
2324
2325     memset(info, 0xcc, sizeof(info));
2326     r = pGdiRealizationInfo(hdc, info);
2327     ok(r != 0, "ret 0\n");
2328     ok(info[0] == 1, "info[0] = %x for the system font\n", info[0]);
2329     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2330
2331     if (!is_truetype_font_installed("Arial"))
2332     {
2333         skip("skipping GdiRealizationInfo with truetype font\n");
2334         goto end;
2335     }
2336
2337     memset(&lf, 0, sizeof(lf));
2338     strcpy(lf.lfFaceName, "Arial");
2339     lf.lfHeight = 20;
2340     lf.lfWeight = FW_NORMAL;
2341     hfont = CreateFontIndirectA(&lf);
2342     hfont_old = SelectObject(hdc, hfont);
2343
2344     memset(info, 0xcc, sizeof(info));
2345     r = pGdiRealizationInfo(hdc, info);
2346     ok(r != 0, "ret 0\n");
2347     ok(info[0] == 3, "info[0] = %x for arial\n", info[0]);
2348     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2349
2350     DeleteObject(SelectObject(hdc, hfont_old));
2351
2352  end:
2353     ReleaseDC(0, hdc);
2354 }
2355
2356 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2357    the nul in the count of characters copied when the face name buffer is not
2358    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2359    always includes it.  */
2360 static void test_GetTextFace(void)
2361 {
2362     static const char faceA[] = "Tahoma";
2363     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2364     LOGFONTA fA = {0};
2365     LOGFONTW fW = {0};
2366     char bufA[LF_FACESIZE];
2367     WCHAR bufW[LF_FACESIZE];
2368     HFONT f, g;
2369     HDC dc;
2370     int n;
2371
2372     if(!is_font_installed("Tahoma"))
2373     {
2374         skip("Tahoma is not installed so skipping this test\n");
2375         return;
2376     }
2377
2378     /* 'A' case.  */
2379     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2380     f = CreateFontIndirectA(&fA);
2381     ok(f != NULL, "CreateFontIndirectA failed\n");
2382
2383     dc = GetDC(NULL);
2384     g = SelectObject(dc, f);
2385     n = GetTextFaceA(dc, sizeof bufA, bufA);
2386     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2387     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2388
2389     /* Play with the count arg.  */
2390     bufA[0] = 'x';
2391     n = GetTextFaceA(dc, 0, bufA);
2392     ok(n == 0, "GetTextFaceA returned %d\n", n);
2393     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2394
2395     bufA[0] = 'x';
2396     n = GetTextFaceA(dc, 1, bufA);
2397     ok(n == 0, "GetTextFaceA returned %d\n", n);
2398     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2399
2400     bufA[0] = 'x'; bufA[1] = 'y';
2401     n = GetTextFaceA(dc, 2, bufA);
2402     ok(n == 1, "GetTextFaceA returned %d\n", n);
2403     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2404
2405     n = GetTextFaceA(dc, 0, NULL);
2406     ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n);
2407
2408     DeleteObject(SelectObject(dc, g));
2409     ReleaseDC(NULL, dc);
2410
2411     /* 'W' case.  */
2412     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2413     SetLastError(0xdeadbeef);
2414     f = CreateFontIndirectW(&fW);
2415     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2416     {
2417         win_skip("CreateFontIndirectW is not implemented\n");
2418         return;
2419     }
2420     ok(f != NULL, "CreateFontIndirectW failed\n");
2421
2422     dc = GetDC(NULL);
2423     g = SelectObject(dc, f);
2424     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2425     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2426     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2427
2428     /* Play with the count arg.  */
2429     bufW[0] = 'x';
2430     n = GetTextFaceW(dc, 0, bufW);
2431     ok(n == 0, "GetTextFaceW returned %d\n", n);
2432     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2433
2434     bufW[0] = 'x';
2435     n = GetTextFaceW(dc, 1, bufW);
2436     ok(n == 1, "GetTextFaceW returned %d\n", n);
2437     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2438
2439     bufW[0] = 'x'; bufW[1] = 'y';
2440     n = GetTextFaceW(dc, 2, bufW);
2441     ok(n == 2, "GetTextFaceW returned %d\n", n);
2442     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2443
2444     n = GetTextFaceW(dc, 0, NULL);
2445     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2446
2447     DeleteObject(SelectObject(dc, g));
2448     ReleaseDC(NULL, dc);
2449 }
2450
2451 static void test_orientation(void)
2452 {
2453     static const char test_str[11] = "Test String";
2454     HDC hdc;
2455     LOGFONTA lf;
2456     HFONT hfont, old_hfont;
2457     SIZE size;
2458
2459     if (!is_truetype_font_installed("Arial"))
2460     {
2461         skip("Arial is not installed\n");
2462         return;
2463     }
2464
2465     hdc = CreateCompatibleDC(0);
2466     memset(&lf, 0, sizeof(lf));
2467     lstrcpyA(lf.lfFaceName, "Arial");
2468     lf.lfHeight = 72;
2469     lf.lfOrientation = lf.lfEscapement = 900;
2470     hfont = create_font("orientation", &lf);
2471     old_hfont = SelectObject(hdc, hfont);
2472     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2473     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2474     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2475     SelectObject(hdc, old_hfont);
2476     DeleteObject(hfont);
2477     DeleteDC(hdc);
2478 }
2479
2480 START_TEST(font)
2481 {
2482     init();
2483
2484     test_logfont();
2485     test_bitmap_font();
2486     test_outline_font();
2487     test_bitmap_font_metrics();
2488     test_GdiGetCharDimensions();
2489     test_GetCharABCWidths();
2490     test_text_extents();
2491     test_GetGlyphIndices();
2492     test_GetKerningPairs();
2493     test_GetOutlineTextMetrics();
2494     test_SetTextJustification();
2495     test_font_charset();
2496     test_GetFontUnicodeRanges();
2497     test_nonexistent_font();
2498     test_orientation();
2499
2500     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
2501      * I'd like to avoid them in this test.
2502      */
2503     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
2504     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
2505     if (is_truetype_font_installed("Arial Black") &&
2506         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
2507     {
2508         test_EnumFontFamilies("", ANSI_CHARSET);
2509         test_EnumFontFamilies("", SYMBOL_CHARSET);
2510         test_EnumFontFamilies("", DEFAULT_CHARSET);
2511     }
2512     else
2513         skip("Arial Black or Symbol/Wingdings is not installed\n");
2514     test_GetTextMetrics();
2515     test_GdiRealizationInfo();
2516     test_GetTextFace();
2517 }