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