gdi32/tests: Fix the trailing '\n' of a few ok() calls.
[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(lf->lfHeight == getobj_lf.lfHeight ||
110        broken((SHORT)lf->lfHeight == getobj_lf.lfHeight), /* win9x */
111        "lfHeight: expect %08x got %08x\n", lf->lfHeight, getobj_lf.lfHeight);
112     ok(lf->lfWidth == getobj_lf.lfWidth ||
113        broken((SHORT)lf->lfWidth == getobj_lf.lfWidth), /* win9x */
114        "lfWidth: expect %08x got %08x\n", lf->lfWidth, getobj_lf.lfWidth);
115     ok(lf->lfEscapement == getobj_lf.lfEscapement ||
116        broken((SHORT)lf->lfEscapement == getobj_lf.lfEscapement), /* win9x */
117        "lfEscapement: expect %08x got %08x\n", lf->lfEscapement, getobj_lf.lfEscapement);
118     ok(lf->lfOrientation == getobj_lf.lfOrientation ||
119        broken((SHORT)lf->lfOrientation == getobj_lf.lfOrientation), /* win9x */
120        "lfOrientation: expect %08x got %08x\n", lf->lfOrientation, getobj_lf.lfOrientation);
121     ok(lf->lfWeight == getobj_lf.lfWeight ||
122        broken((SHORT)lf->lfWeight == getobj_lf.lfWeight), /* win9x */
123        "lfWeight: expect %08x got %08x\n", lf->lfWeight, getobj_lf.lfWeight);
124     ok(lf->lfItalic == getobj_lf.lfItalic, "lfItalic: expect %02x got %02x\n", lf->lfItalic, getobj_lf.lfItalic);
125     ok(lf->lfUnderline == getobj_lf.lfUnderline, "lfUnderline: expect %02x got %02x\n", lf->lfUnderline, getobj_lf.lfUnderline);
126     ok(lf->lfStrikeOut == getobj_lf.lfStrikeOut, "lfStrikeOut: expect %02x got %02x\n", lf->lfStrikeOut, getobj_lf.lfStrikeOut);
127     ok(lf->lfCharSet == getobj_lf.lfCharSet, "lfCharSet: expect %02x got %02x\n", lf->lfCharSet, getobj_lf.lfCharSet);
128     ok(lf->lfOutPrecision == getobj_lf.lfOutPrecision, "lfOutPrecision: expect %02x got %02x\n", lf->lfOutPrecision, getobj_lf.lfOutPrecision);
129     ok(lf->lfClipPrecision == getobj_lf.lfClipPrecision, "lfClipPrecision: expect %02x got %02x\n", lf->lfClipPrecision, getobj_lf.lfClipPrecision);
130     ok(lf->lfQuality == getobj_lf.lfQuality, "lfQuality: expect %02x got %02x\n", lf->lfQuality, getobj_lf.lfQuality);
131     ok(lf->lfPitchAndFamily == getobj_lf.lfPitchAndFamily, "lfPitchAndFamily: expect %02x got %02x\n", lf->lfPitchAndFamily, getobj_lf.lfPitchAndFamily);
132     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName) ||
133        broken(!memcmp(lf->lfFaceName, getobj_lf.lfFaceName, LF_FACESIZE-1)), /* win9x doesn't ensure '\0' termination */
134        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
135 }
136
137 static HFONT create_font(const char* test, const LOGFONTA* lf)
138 {
139     HFONT hfont = CreateFontIndirectA(lf);
140     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
141     if (hfont)
142         check_font(test, lf, hfont);
143     return hfont;
144 }
145
146 static void test_logfont(void)
147 {
148     LOGFONTA lf;
149     HFONT hfont;
150
151     memset(&lf, 0, sizeof lf);
152
153     lf.lfCharSet = ANSI_CHARSET;
154     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
155     lf.lfWeight = FW_DONTCARE;
156     lf.lfHeight = 16;
157     lf.lfWidth = 16;
158     lf.lfQuality = DEFAULT_QUALITY;
159
160     lstrcpyA(lf.lfFaceName, "Arial");
161     hfont = create_font("Arial", &lf);
162     DeleteObject(hfont);
163
164     memset(&lf, 'A', sizeof(lf));
165     hfont = CreateFontIndirectA(&lf);
166     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
167     
168     lf.lfFaceName[LF_FACESIZE - 1] = 0;
169     check_font("AAA...", &lf, hfont);
170     DeleteObject(hfont);
171 }
172
173 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
174 {
175     if (type & RASTER_FONTTYPE)
176     {
177         LOGFONT *lf = (LOGFONT *)lParam;
178         *lf = *elf;
179         return 0; /* stop enumeration */
180     }
181
182     return 1; /* continue enumeration */
183 }
184
185 static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
186 {
187     ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight);
188     ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent);
189     ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent);
190     ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
191     ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
192     ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
193     ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
194     ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight);
195     ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang);
196     ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
197     ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
198     ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar);
199     ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar);
200     ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar);
201     ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar);
202     ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic);
203     ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined);
204     ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut);
205     ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
206     ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet);
207 }
208
209 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
210                               LONG lfWidth, const char *test_str,
211                               INT test_str_len, const TEXTMETRICA *tm_orig,
212                               const SIZE *size_orig, INT width_of_A_orig,
213                               INT scale_x, INT scale_y)
214 {
215     LOGFONTA lf;
216     OUTLINETEXTMETRIC otm;
217     TEXTMETRICA tm;
218     SIZE size;
219     INT width_of_A, cx, cy;
220     UINT ret;
221
222     if (!hfont)
223         return;
224
225     ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
226
227     GetObjectA(hfont, sizeof(lf), &lf);
228
229     if (GetOutlineTextMetricsA(hdc, 0, NULL))
230     {
231         otm.otmSize = sizeof(otm) / 2;
232         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
233         ok(ret == sizeof(otm)/2 /* XP */ ||
234            ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
235
236         memset(&otm, 0x1, sizeof(otm));
237         otm.otmSize = sizeof(otm);
238         ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
239         ok(ret == sizeof(otm) /* XP */ ||
240            ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
241
242         memset(&tm, 0x2, sizeof(tm));
243         ret = GetTextMetricsA(hdc, &tm);
244         ok(ret, "GetTextMetricsA failed\n");
245         /* the structure size is aligned */
246         if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1))
247         {
248             ok(0, "tm != otm\n");
249             compare_tm(&tm, &otm.otmTextMetrics);
250         }
251
252         tm = otm.otmTextMetrics;
253 if (0) /* these metrics are scaled too, but with rounding errors */
254 {
255         ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent);
256         ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent);
257 }
258         ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent);
259         ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
260         ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
261         ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
262         ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent);
263         ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare);
264     }
265     else
266     {
267         ret = GetTextMetricsA(hdc, &tm);
268         ok(ret, "GetTextMetricsA failed\n");
269     }
270
271     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
272     cy = tm.tmHeight / tm_orig->tmHeight;
273     ok(cx == scale_x && cy == scale_y, "height %d: expected scale_x %d, scale_y %d, got cx %d, cy %d\n",
274        lfHeight, scale_x, scale_y, cx, cy);
275     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
276     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
277     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
278     ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
279     ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
280
281     ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
282     if (lf.lfHeight)
283     {
284         if (lf.lfWidth)
285             ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth);
286     }
287     else
288         ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
289
290     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
291
292     ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x);
293     ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
294
295     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
296
297     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);
298 }
299
300 /* Test how GDI scales bitmap font metrics */
301 static void test_bitmap_font(void)
302 {
303     static const char test_str[11] = "Test String";
304     HDC hdc;
305     LOGFONTA bitmap_lf;
306     HFONT hfont, old_hfont;
307     TEXTMETRICA tm_orig;
308     SIZE size_orig;
309     INT ret, i, width_orig, height_orig, scale, lfWidth;
310
311     hdc = GetDC(0);
312
313     /* "System" has only 1 pixel size defined, otherwise the test breaks */
314     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
315     if (ret)
316     {
317         ReleaseDC(0, hdc);
318         trace("no bitmap fonts were found, skipping the test\n");
319         return;
320     }
321
322     trace("found bitmap font %s, height %d\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
323
324     height_orig = bitmap_lf.lfHeight;
325     lfWidth = bitmap_lf.lfWidth;
326
327     hfont = create_font("bitmap", &bitmap_lf);
328     old_hfont = SelectObject(hdc, hfont);
329     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
330     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
331     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
332     SelectObject(hdc, old_hfont);
333     DeleteObject(hfont);
334
335     bitmap_lf.lfHeight = 0;
336     bitmap_lf.lfWidth = 4;
337     hfont = create_font("bitmap", &bitmap_lf);
338     old_hfont = SelectObject(hdc, hfont);
339     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
340     SelectObject(hdc, old_hfont);
341     DeleteObject(hfont);
342
343     bitmap_lf.lfHeight = height_orig;
344     bitmap_lf.lfWidth = lfWidth;
345
346     /* test fractional scaling */
347     for (i = 1; i <= height_orig * 6; i++)
348     {
349         INT nearest_height;
350
351         bitmap_lf.lfHeight = i;
352         hfont = create_font("fractional", &bitmap_lf);
353         scale = (i + height_orig - 1) / height_orig;
354         nearest_height = scale * height_orig;
355         /* Only jump to the next height if the difference <= 25% original height */
356         if (scale > 2 && nearest_height - i > height_orig / 4) scale--;
357         /* The jump between unscaled and doubled is delayed by 1 in winnt+ but not in win9x,
358            so we'll not test this particular height. */
359         else if(scale == 2 && nearest_height - i == (height_orig / 4)) continue;
360         else if(scale == 2 && nearest_height - i > (height_orig / 4 - 1)) scale--;
361         old_hfont = SelectObject(hdc, hfont);
362         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale);
363         SelectObject(hdc, old_hfont);
364         DeleteObject(hfont);
365     }
366
367     /* test integer scaling 3x2 */
368     bitmap_lf.lfHeight = height_orig * 2;
369     bitmap_lf.lfWidth *= 3;
370     hfont = create_font("3x2", &bitmap_lf);
371     old_hfont = SelectObject(hdc, hfont);
372     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
373     SelectObject(hdc, old_hfont);
374     DeleteObject(hfont);
375
376     /* test integer scaling 3x3 */
377     bitmap_lf.lfHeight = height_orig * 3;
378     bitmap_lf.lfWidth = 0;
379     hfont = create_font("3x3", &bitmap_lf);
380     old_hfont = SelectObject(hdc, hfont);
381     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
382     SelectObject(hdc, old_hfont);
383     DeleteObject(hfont);
384
385     ReleaseDC(0, hdc);
386 }
387
388 /* Test how GDI scales outline font metrics */
389 static void test_outline_font(void)
390 {
391     static const char test_str[11] = "Test String";
392     HDC hdc, hdc_2;
393     LOGFONTA lf;
394     HFONT hfont, old_hfont, old_hfont_2;
395     OUTLINETEXTMETRICA otm;
396     SIZE size_orig;
397     INT width_orig, height_orig, lfWidth;
398     XFORM xform;
399     GLYPHMETRICS gm;
400     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
401     MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
402     POINT pt;
403     INT ret;
404
405     if (!is_truetype_font_installed("Arial"))
406     {
407         skip("Arial is not installed\n");
408         return;
409     }
410
411     hdc = CreateCompatibleDC(0);
412
413     memset(&lf, 0, sizeof(lf));
414     strcpy(lf.lfFaceName, "Arial");
415     lf.lfHeight = 72;
416     hfont = create_font("outline", &lf);
417     old_hfont = SelectObject(hdc, hfont);
418     otm.otmSize = sizeof(otm);
419     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
420     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
421     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
422
423     test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
424     SelectObject(hdc, old_hfont);
425     DeleteObject(hfont);
426
427     /* font of otmEMSquare height helps to avoid a lot of rounding errors */
428     lf.lfHeight = otm.otmEMSquare;
429     lf.lfHeight = -lf.lfHeight;
430     hfont = create_font("outline", &lf);
431     old_hfont = SelectObject(hdc, hfont);
432     otm.otmSize = sizeof(otm);
433     ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n");
434     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
435     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
436     SelectObject(hdc, old_hfont);
437     DeleteObject(hfont);
438
439     height_orig = otm.otmTextMetrics.tmHeight;
440     lfWidth = otm.otmTextMetrics.tmAveCharWidth;
441
442     /* test integer scaling 3x2 */
443     lf.lfHeight = height_orig * 2;
444     lf.lfWidth = lfWidth * 3;
445     hfont = create_font("3x2", &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, 3, 2);
448     SelectObject(hdc, old_hfont);
449     DeleteObject(hfont);
450
451     /* test integer scaling 3x3 */
452     lf.lfHeight = height_orig * 3;
453     lf.lfWidth = lfWidth * 3;
454     hfont = create_font("3x3", &lf);
455     old_hfont = SelectObject(hdc, hfont);
456     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
457     SelectObject(hdc, old_hfont);
458     DeleteObject(hfont);
459
460     /* test integer scaling 1x1 */
461     lf.lfHeight = height_orig * 1;
462     lf.lfWidth = lfWidth * 1;
463     hfont = create_font("1x1", &lf);
464     old_hfont = SelectObject(hdc, hfont);
465     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
466     SelectObject(hdc, old_hfont);
467     DeleteObject(hfont);
468
469     /* test integer scaling 1x1 */
470     lf.lfHeight = height_orig;
471     lf.lfWidth = 0;
472     hfont = create_font("1x1", &lf);
473     old_hfont = SelectObject(hdc, hfont);
474     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
475
476     /* with an identity matrix */
477     memset(&gm, 0, sizeof(gm));
478     SetLastError(0xdeadbeef);
479     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
480     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
481     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
482     ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig);
483     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
484     /* with a custom matrix */
485     memset(&gm, 0, sizeof(gm));
486     SetLastError(0xdeadbeef);
487     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
488     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
489     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
490     ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2);
491     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
492
493     /* Test that changing the DC transformation affects only the font
494      * selected on this DC and doesn't affect the same font selected on
495      * another DC.
496      */
497     hdc_2 = CreateCompatibleDC(0);
498     old_hfont_2 = SelectObject(hdc_2, hfont);
499     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
500
501     SetMapMode(hdc, MM_ANISOTROPIC);
502
503     /* font metrics on another DC should be unchanged */
504     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
505
506     /* test restrictions of compatibility mode GM_COMPATIBLE */
507     /*  part 1: rescaling only X should not change font scaling on screen.
508                 So compressing the X axis by 2 is not done, and this
509                 appears as X scaling of 2 that no one requested. */
510     SetWindowExtEx(hdc, 100, 100, NULL);
511     SetViewportExtEx(hdc, 50, 100, NULL);
512     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
513     /* font metrics on another DC should be unchanged */
514     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
515
516     /*  part 2: rescaling only Y should change font scaling.
517                 As also X is scaled by a factor of 2, but this is not
518                 requested by the DC transformation, we get a scaling factor
519                 of 2 in the X coordinate. */
520     SetViewportExtEx(hdc, 100, 200, NULL);
521     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
522     /* font metrics on another DC should be unchanged */
523     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
524
525     /* restore scaling */
526     SetMapMode(hdc, MM_TEXT);
527
528     /* font metrics on another DC should be unchanged */
529     test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
530
531     SelectObject(hdc_2, old_hfont_2);
532     DeleteDC(hdc_2);
533
534     if (!SetGraphicsMode(hdc, GM_ADVANCED))
535     {
536         SelectObject(hdc, old_hfont);
537         DeleteObject(hfont);
538         DeleteDC(hdc);
539         skip("GM_ADVANCED is not supported on this platform\n");
540         return;
541     }
542
543     xform.eM11 = 20.0f;
544     xform.eM12 = 0.0f;
545     xform.eM21 = 0.0f;
546     xform.eM22 = 20.0f;
547     xform.eDx = 0.0f;
548     xform.eDy = 0.0f;
549
550     SetLastError(0xdeadbeef);
551     ret = SetWorldTransform(hdc, &xform);
552     ok(ret, "SetWorldTransform error %u\n", GetLastError());
553
554     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
555
556     /* with an identity matrix */
557     memset(&gm, 0, sizeof(gm));
558     SetLastError(0xdeadbeef);
559     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
560     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
561     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
562     pt.x = width_orig; pt.y = 0;
563     LPtoDP(hdc, &pt, 1);
564     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
565     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
566     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
567     /* with a custom matrix */
568     memset(&gm, 0, sizeof(gm));
569     SetLastError(0xdeadbeef);
570     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
571     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
572     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
573     pt.x = width_orig; pt.y = 0;
574     LPtoDP(hdc, &pt, 1);
575     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
576     ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
577     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
578
579     SetLastError(0xdeadbeef);
580     ret = SetMapMode(hdc, MM_LOMETRIC);
581     ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError());
582
583     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
584
585     /* with an identity matrix */
586     memset(&gm, 0, sizeof(gm));
587     SetLastError(0xdeadbeef);
588     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
589     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
590     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
591     pt.x = width_orig; pt.y = 0;
592     LPtoDP(hdc, &pt, 1);
593     ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x);
594     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
595     /* with a custom matrix */
596     memset(&gm, 0, sizeof(gm));
597     SetLastError(0xdeadbeef);
598     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
599     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
600     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
601     pt.x = width_orig; pt.y = 0;
602     LPtoDP(hdc, &pt, 1);
603     ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2);
604     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
605
606     SetLastError(0xdeadbeef);
607     ret = SetMapMode(hdc, MM_TEXT);
608     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError());
609
610     test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
611
612     /* with an identity matrix */
613     memset(&gm, 0, sizeof(gm));
614     SetLastError(0xdeadbeef);
615     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
616     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
617     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
618     pt.x = width_orig; pt.y = 0;
619     LPtoDP(hdc, &pt, 1);
620     ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
621     ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig);
622     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
623     /* with a custom matrix */
624     memset(&gm, 0, sizeof(gm));
625     SetLastError(0xdeadbeef);
626     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
627     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
628     trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
629     pt.x = width_orig; pt.y = 0;
630     LPtoDP(hdc, &pt, 1);
631     ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
632     ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig);
633     ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
634
635     SelectObject(hdc, old_hfont);
636     DeleteObject(hfont);
637     DeleteDC(hdc);
638 }
639
640 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
641 {
642     LOGFONT *lf = (LOGFONT *)lParam;
643
644     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
645     {
646         *lf = *elf;
647         return 0; /* stop enumeration */
648     }
649     return 1; /* continue enumeration */
650 }
651
652 static void test_bitmap_font_metrics(void)
653 {
654     static const struct font_data
655     {
656         const char face_name[LF_FACESIZE];
657         int weight, height, ascent, descent, int_leading, ext_leading;
658         int ave_char_width, max_char_width, dpi;
659         DWORD ansi_bitfield;
660     } fd[] =
661     {
662         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
663         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
664         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16, 96, FS_LATIN1 | FS_CYRILLIC },
665         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 96, FS_LATIN2 },
666         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 19, 96, FS_LATIN1 },
667         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 24, 96, FS_LATIN2 },
668         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20, 96, FS_CYRILLIC },
669         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 96, FS_LATIN1 },
670         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 96, FS_LATIN2 },
671         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25, 96, FS_CYRILLIC },
672         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
673
674         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
675         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, FS_LATIN1 | FS_LATIN2 },
676         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 17, 120, FS_CYRILLIC },
677         { "MS Sans Serif", FW_NORMAL, 25, 20, 5, 5, 0, 10, 21, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
678         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 6, 0, 12, 24, 120, FS_LATIN1 | FS_LATIN2 },
679         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 24, 120, FS_CYRILLIC },
680         { "MS Sans Serif", FW_NORMAL, 36, 29, 7, 6, 0, 15, 30, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
681         { "MS Sans Serif", FW_NORMAL, 46, 37, 9, 6, 0, 20, 40, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
682
683         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, FS_LATIN1 | FS_LATIN2 },
684         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, FS_CYRILLIC },
685         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
686         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11, 96, FS_LATIN1 },
687         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12, 96, FS_LATIN2 | FS_CYRILLIC },
688         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 96, FS_LATIN1 | FS_LATIN2 },
689         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16, 96, FS_CYRILLIC },
690         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 18, 96, FS_LATIN1 | FS_LATIN2 },
691         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19, 96, FS_CYRILLIC },
692         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 17, 96, FS_LATIN1 },
693         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 22, 96, FS_LATIN2 },
694         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23, 96, FS_CYRILLIC },
695         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 23, 96, FS_LATIN1 },
696         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 26, 96, FS_LATIN2 },
697         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27, 96, FS_CYRILLIC },
698         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 33, 96, FS_LATIN1 | FS_LATIN2 },
699         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34, 96, FS_CYRILLIC },
700
701         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 14, 120, FS_LATIN1 | FS_CYRILLIC },
702         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 13, 120, FS_LATIN2 },
703         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 18, 120, FS_LATIN1 | FS_CYRILLIC },
704         { "MS Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 15, 120, FS_LATIN2 },
705         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 21, 120, FS_LATIN1 | FS_CYRILLIC },
706         { "MS Serif", FW_NORMAL, 23, 18, 5, 3, 0, 10, 19, 120, FS_LATIN2 },
707         { "MS Serif", FW_NORMAL, 27, 21, 6, 4, 0, 12, 23, 120, FS_LATIN1 | FS_LATIN2 },
708         { "MS Serif", FW_MEDIUM, 27, 22, 5, 2, 0, 12, 30, 120, FS_CYRILLIC },
709         { "MS Serif", FW_NORMAL, 33, 26, 7, 3, 0, 14, 30, 120, FS_LATIN1 | FS_LATIN2 },
710         { "MS Serif", FW_MEDIUM, 32, 25, 7, 2, 0, 14, 32, 120, FS_CYRILLIC },
711         { "MS Serif", FW_NORMAL, 43, 34, 9, 3, 0, 19, 39, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
712
713         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
714         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
715         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
716
717         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
718         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
719         { "Courier", FW_NORMAL, 25, 20, 5, 0, 0, 15, 15, 120, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
720
721         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 14, 96, FS_LATIN1 },
722         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15, 96, FS_LATIN2 | FS_CYRILLIC },
723 /*
724  * TODO:  the system for CP932 should be NORMAL, not BOLD.  However that would
725  *        require a new system.sfd for that font
726  */
727         { "System", FW_BOLD, 18, 16, 2, 0, 2, 8, 16, 96, FS_JISJAPAN },
728
729         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 14, 120, FS_LATIN1 },
730         { "System", FW_BOLD, 20, 16, 4, 4, 0, 9, 17, 120, FS_LATIN2 | FS_CYRILLIC },
731
732         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 96, FS_LATIN1 },
733         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 96, FS_LATIN2 | FS_CYRILLIC },
734         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 2, 4, 96, FS_JISJAPAN },
735         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4, 96, FS_LATIN1 },
736         { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 2, 8, 96, FS_LATIN2 | FS_CYRILLIC },
737         { "Small Fonts", FW_NORMAL, 5, 4, 1, 0, 0, 3, 6, 96, FS_JISJAPAN },
738         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13, 96, FS_LATIN1 },
739         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 96, FS_LATIN2 | FS_CYRILLIC },
740         { "Small Fonts", FW_NORMAL, 6, 5, 1, 0, 0, 4, 8, 96, FS_JISJAPAN },
741         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 96, FS_LATIN1 },
742         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 96, FS_LATIN2 | FS_CYRILLIC },
743         { "Small Fonts", FW_NORMAL, 8, 7, 1, 0, 0, 5, 10, 96, FS_JISJAPAN },
744         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8, 96, FS_LATIN1 | FS_LATIN2 },
745         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 96, FS_CYRILLIC },
746         { "Small Fonts", FW_NORMAL, 10, 8, 2, 0, 0, 6, 12, 96, FS_JISJAPAN },
747         { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC },
748         { "Small Fonts", FW_NORMAL, 11, 9, 2, 0, 0, 7, 14, 96, FS_JISJAPAN },
749
750         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2, 120, FS_LATIN1 | FS_JISJAPAN },
751         { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 8, 120, FS_LATIN2 | FS_CYRILLIC },
752         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 5, 120, FS_LATIN1 | FS_JISJAPAN },
753         { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 8, 120, FS_LATIN2 | FS_CYRILLIC },
754         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7, 120, FS_LATIN1 | FS_JISJAPAN },
755         { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 8, 120, FS_LATIN2 | FS_CYRILLIC },
756         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 9, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
757         { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8, 120, FS_CYRILLIC },
758         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 5, 10, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
759         { "Small Fonts", FW_NORMAL, 12, 10, 2, 2, 0, 6, 10, 120, FS_CYRILLIC },
760         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 12, 120, FS_LATIN1 | FS_LATIN2 | FS_JISJAPAN },
761         { "Small Fonts", FW_NORMAL, 13, 11, 2, 2, 0, 6, 11, 120, FS_CYRILLIC },
762
763         { "Fixedsys", FW_NORMAL, 15, 12, 3, 3, 0, 8, 8, 96, FS_LATIN1 | FS_LATIN2 },
764         { "Fixedsys", FW_NORMAL, 16, 12, 4, 3, 0, 8, 8, 96, FS_CYRILLIC },
765         { "FixedSys", FW_NORMAL, 18, 16, 2, 0, 0, 8, 16, 96, FS_JISJAPAN },
766
767         /* The 120dpi version still has its dpi marked as 96 */
768         { "Fixedsys", FW_NORMAL, 20, 16, 4, 2, 0, 10, 10, 96, FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC }
769
770         /* FIXME: add "Terminal" */
771     };
772     HDC hdc;
773     LOGFONT lf;
774     HFONT hfont, old_hfont;
775     TEXTMETRIC tm;
776     INT ret, i;
777
778     hdc = CreateCompatibleDC(0);
779     assert(hdc);
780
781     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
782     {
783         int bit;
784
785         memset(&lf, 0, sizeof(lf));
786
787         lf.lfHeight = fd[i].height;
788         strcpy(lf.lfFaceName, fd[i].face_name);
789
790         for(bit = 0; bit < 32; bit++)
791         {
792             DWORD fs[2];
793             CHARSETINFO csi;
794
795             fs[0] = 1L << bit;
796             fs[1] = 0;
797             if((fd[i].ansi_bitfield & fs[0]) == 0) continue;
798             if(!TranslateCharsetInfo( fs, &csi, TCI_SRCFONTSIG )) continue;
799
800             lf.lfCharSet = csi.ciCharset;
801             ret = EnumFontFamiliesEx(hdc, &lf, find_font_proc, (LPARAM)&lf, 0);
802             if (ret) continue;
803
804             hfont = create_font(lf.lfFaceName, &lf);
805             old_hfont = SelectObject(hdc, hfont);
806             ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %d\n", GetLastError());
807             if(fd[i].dpi == tm.tmDigitizedAspectX)
808             {
809                 trace("found font %s, height %d charset %x dpi %d\n", lf.lfFaceName, lf.lfHeight, lf.lfCharSet, fd[i].dpi);
810                 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);
811                 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);
812                 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);
813                 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);
814                 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);
815                 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);
816                 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);
817
818                 /* Don't run the max char width test on System/ANSI_CHARSET.  We have extra characters in our font
819                    that make the max width bigger */
820                 if(strcmp(lf.lfFaceName, "System") || lf.lfCharSet != ANSI_CHARSET)
821                     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);
822             }
823             SelectObject(hdc, old_hfont);
824             DeleteObject(hfont);
825         }
826     }
827
828     DeleteDC(hdc);
829 }
830
831 static void test_GdiGetCharDimensions(void)
832 {
833     HDC hdc;
834     TEXTMETRICW tm;
835     LONG ret;
836     SIZE size;
837     LONG avgwidth, height;
838     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
839
840     if (!pGdiGetCharDimensions)
841     {
842         win_skip("GdiGetCharDimensions not available on this platform\n");
843         return;
844     }
845
846     hdc = CreateCompatibleDC(NULL);
847
848     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
849     avgwidth = ((size.cx / 26) + 1) / 2;
850
851     ret = pGdiGetCharDimensions(hdc, &tm, &height);
852     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
853     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %d instead of %d\n", tm.tmHeight, height);
854
855     ret = pGdiGetCharDimensions(hdc, &tm, NULL);
856     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
857
858     ret = pGdiGetCharDimensions(hdc, NULL, NULL);
859     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
860
861     height = 0;
862     ret = pGdiGetCharDimensions(hdc, NULL, &height);
863     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %d instead of %d\n", avgwidth, ret);
864     ok(height == size.cy, "GdiGetCharDimensions should have set height to %d instead of %d\n", size.cy, height);
865
866     DeleteDC(hdc);
867 }
868
869 static void test_GetCharABCWidths(void)
870 {
871     static const WCHAR str[] = {'a',0};
872     BOOL ret;
873     HDC hdc;
874     LOGFONTA lf;
875     HFONT hfont;
876     ABC abc[1];
877     WORD glyphs[1];
878     DWORD nb;
879
880     if (!pGetCharABCWidthsW || !pGetCharABCWidthsI)
881     {
882         win_skip("GetCharABCWidthsW/I not available on this platform\n");
883         return;
884     }
885
886     memset(&lf, 0, sizeof(lf));
887     strcpy(lf.lfFaceName, "System");
888     lf.lfHeight = 20;
889
890     hfont = CreateFontIndirectA(&lf);
891     hdc = GetDC(0);
892     hfont = SelectObject(hdc, hfont);
893
894     nb = pGetGlyphIndicesW(hdc, str, 1, glyphs, 0);
895     ok(nb == 1, "GetGlyphIndicesW should have returned 1\n");
896
897     ret = pGetCharABCWidthsI(NULL, 0, 1, glyphs, abc);
898     ok(!ret, "GetCharABCWidthsI should have failed\n");
899
900     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, NULL);
901     ok(!ret, "GetCharABCWidthsI should have failed\n");
902
903     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
904     ok(ret, "GetCharABCWidthsI should have succeeded\n");
905
906     ret = pGetCharABCWidthsW(NULL, 'a', 'a', abc);
907     ok(!ret, "GetCharABCWidthsW should have failed\n");
908
909     ret = pGetCharABCWidthsW(hdc, 'a', 'a', NULL);
910     ok(!ret, "GetCharABCWidthsW should have failed\n");
911
912     ret = pGetCharABCWidthsW(hdc, 'a', 'a', abc);
913     ok(!ret, "GetCharABCWidthsW should have failed\n");
914
915     hfont = SelectObject(hdc, hfont);
916     DeleteObject(hfont);
917     ReleaseDC(NULL, hdc);
918 }
919
920 static void test_text_extents(void)
921 {
922     static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
923     LPINT extents;
924     INT i, len, fit1, fit2;
925     LOGFONTA lf;
926     TEXTMETRICA tm;
927     HDC hdc;
928     HFONT hfont;
929     SIZE sz;
930     SIZE sz1, sz2;
931
932     memset(&lf, 0, sizeof(lf));
933     strcpy(lf.lfFaceName, "Arial");
934     lf.lfHeight = 20;
935
936     hfont = CreateFontIndirectA(&lf);
937     hdc = GetDC(0);
938     hfont = SelectObject(hdc, hfont);
939     GetTextMetricsA(hdc, &tm);
940     GetTextExtentPointA(hdc, "o", 1, &sz);
941     ok(sz.cy == tm.tmHeight, "cy %d tmHeight %d\n", sz.cy, tm.tmHeight);
942
943     SetLastError(0xdeadbeef);
944     GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
945     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
946     {
947         win_skip("Skipping remainder of text extents test on a Win9x platform\n");
948         hfont = SelectObject(hdc, hfont);
949         DeleteObject(hfont);
950         ReleaseDC(0, hdc);
951         return;
952     }
953
954     len = lstrlenW(wt);
955     extents = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof extents[0]);
956     extents[0] = 1;         /* So that the increasing sequence test will fail
957                                if the extents array is untouched.  */
958     GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
959     GetTextExtentPointW(hdc, wt, len, &sz2);
960     ok(sz1.cy == sz2.cy,
961        "cy from GetTextExtentExPointW (%d) and GetTextExtentPointW (%d) differ\n", sz1.cy, sz2.cy);
962     /* Because of the '\n' in the string GetTextExtentExPoint and
963        GetTextExtentPoint return different widths under Win2k, but
964        under WinXP they return the same width.  So we don't test that
965        here. */
966
967     for (i = 1; i < len; ++i)
968         ok(extents[i-1] <= extents[i],
969            "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
970            i);
971     ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
972     ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
973     ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
974     GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
975     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
976     ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
977     GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
978     ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
979     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
980     ok(extents[0] == extents[2] && extents[1] == extents[3],
981        "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
982     GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
983     ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
984        "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
985     HeapFree(GetProcessHeap(), 0, extents);
986
987     hfont = SelectObject(hdc, hfont);
988     DeleteObject(hfont);
989     ReleaseDC(NULL, hdc);
990 }
991
992 static void test_GetGlyphIndices(void)
993 {
994     HDC      hdc;
995     HFONT    hfont;
996     DWORD    charcount;
997     LOGFONTA lf;
998     DWORD    flags = 0;
999     WCHAR    testtext[] = {'T','e','s','t',0xffff,0};
1000     WORD     glyphs[(sizeof(testtext)/2)-1];
1001     TEXTMETRIC textm;
1002     HFONT hOldFont;
1003
1004     if (!pGetGlyphIndicesW) {
1005         win_skip("GetGlyphIndicesW not available on platform\n");
1006         return;
1007     }
1008
1009     hdc = GetDC(0);
1010
1011     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1012     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1013     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1014     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1015     ok((glyphs[4] == 0x001f || glyphs[4] == 0xffff /* Vista */), "GetGlyphIndicesW should have returned a nonexistent char not %04x\n", glyphs[4]);
1016     flags = 0;
1017     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1018     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1019     ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndicesW should have returned a %04x not %04x\n",
1020                     textm.tmDefaultChar, glyphs[4]);
1021
1022     if(!is_font_installed("Tahoma"))
1023     {
1024         skip("Tahoma is not installed so skipping this test\n");
1025         return;
1026     }
1027     memset(&lf, 0, sizeof(lf));
1028     strcpy(lf.lfFaceName, "Tahoma");
1029     lf.lfHeight = 20;
1030
1031     hfont = CreateFontIndirectA(&lf);
1032     hOldFont = SelectObject(hdc, hfont);
1033     ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
1034     flags |= GGI_MARK_NONEXISTING_GLYPHS;
1035     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1036     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1037     ok(glyphs[4] == 0xffff, "GetGlyphIndicesW should have returned 0xffff char not %04x\n", glyphs[4]);
1038     flags = 0;
1039     testtext[0] = textm.tmDefaultChar;
1040     charcount = pGetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
1041     ok(charcount == 5, "GetGlyphIndicesW count of glyphs should = 5 not %d\n", charcount);
1042     ok(glyphs[0] == 0, "GetGlyphIndicesW for tmDefaultChar should be 0 not %04x\n", glyphs[0]);
1043     ok(glyphs[4] == 0, "GetGlyphIndicesW should have returned 0 not %04x\n", glyphs[4]);
1044     DeleteObject(SelectObject(hdc, hOldFont));
1045 }
1046
1047 static void test_GetKerningPairs(void)
1048 {
1049     static const struct kerning_data
1050     {
1051         const char face_name[LF_FACESIZE];
1052         LONG height;
1053         /* some interesting fields from OUTLINETEXTMETRIC */
1054         LONG tmHeight, tmAscent, tmDescent;
1055         UINT otmEMSquare;
1056         INT  otmAscent;
1057         INT  otmDescent;
1058         UINT otmLineGap;
1059         UINT otmsCapEmHeight;
1060         UINT otmsXHeight;
1061         INT  otmMacAscent;
1062         INT  otmMacDescent;
1063         UINT otmMacLineGap;
1064         UINT otmusMinimumPPEM;
1065         /* small subset of kerning pairs to test */
1066         DWORD total_kern_pairs;
1067         const KERNINGPAIR kern_pair[26];
1068     } kd[] =
1069     {
1070         {"Arial", 12, 12, 9, 3,
1071                   2048, 7, -2, 1, 5, 2, 8, -2, 0, 9,
1072                   26,
1073             {
1074                 {' ','A',-1},{' ','T',0},{' ','Y',0},{'1','1',-1},
1075                 {'A',' ',-1},{'A','T',-1},{'A','V',-1},{'A','W',0},
1076                 {'A','Y',-1},{'A','v',0},{'A','w',0},{'A','y',0},
1077                 {'F',',',-1},{'F','.',-1},{'F','A',-1},{'L',' ',0},
1078                 {'L','T',-1},{'L','V',-1},{'L','W',-1},{'L','Y',-1},
1079                 {915,912,+1},{915,913,-1},{910,912,+1},{910,913,-1},
1080                 {933,970,+1},{933,972,-1}
1081                 }
1082         },
1083         {"Arial", -34, 39, 32, 7,
1084                   2048, 25, -7, 5, 17, 9, 31, -7, 1, 9,
1085                   26,
1086             {
1087                 {' ','A',-2},{' ','T',-1},{' ','Y',-1},{'1','1',-3},
1088                 {'A',' ',-2},{'A','T',-3},{'A','V',-3},{'A','W',-1},
1089                 {'A','Y',-3},{'A','v',-1},{'A','w',-1},{'A','y',-1},
1090                 {'F',',',-4},{'F','.',-4},{'F','A',-2},{'L',' ',-1},
1091                 {'L','T',-3},{'L','V',-3},{'L','W',-3},{'L','Y',-3},
1092                 {915,912,+3},{915,913,-3},{910,912,+3},{910,913,-3},
1093                 {933,970,+2},{933,972,-3}
1094             }
1095         },
1096         { "Arial", 120, 120, 97, 23,
1097                    2048, 79, -23, 16, 54, 27, 98, -23, 4, 9,
1098                    26,
1099             {
1100                 {' ','A',-6},{' ','T',-2},{' ','Y',-2},{'1','1',-8},
1101                 {'A',' ',-6},{'A','T',-8},{'A','V',-8},{'A','W',-4},
1102                 {'A','Y',-8},{'A','v',-2},{'A','w',-2},{'A','y',-2},
1103                 {'F',',',-12},{'F','.',-12},{'F','A',-6},{'L',' ',-4},
1104                 {'L','T',-8},{'L','V',-8},{'L','W',-8},{'L','Y',-8},
1105                 {915,912,+9},{915,913,-10},{910,912,+9},{910,913,-8},
1106                 {933,970,+6},{933,972,-10}
1107             }
1108         },
1109 #if 0 /* this set fails due to +1/-1 errors (rounding bug?), needs investigation. */
1110         { "Arial", 1024 /* usually 1/2 of EM Square */, 1024, 830, 194,
1111                    2048, 668, -193, 137, 459, 229, 830, -194, 30, 9,
1112                    26,
1113             {
1114                 {' ','A',-51},{' ','T',-17},{' ','Y',-17},{'1','1',-68},
1115                 {'A',' ',-51},{'A','T',-68},{'A','V',-68},{'A','W',-34},
1116                 {'A','Y',-68},{'A','v',-17},{'A','w',-17},{'A','y',-17},
1117                 {'F',',',-102},{'F','.',-102},{'F','A',-51},{'L',' ',-34},
1118                 {'L','T',-68},{'L','V',-68},{'L','W',-68},{'L','Y',-68},
1119                 {915,912,+73},{915,913,-84},{910,912,+76},{910,913,-68},
1120                 {933,970,+54},{933,972,-83}
1121             }
1122         }
1123 #endif
1124     };
1125     LOGFONT lf;
1126     HFONT hfont, hfont_old;
1127     KERNINGPAIR *kern_pair;
1128     HDC hdc;
1129     DWORD total_kern_pairs, ret, i, n, matches;
1130
1131     hdc = GetDC(0);
1132
1133     /* GetKerningPairsA maps unicode set of kerning pairs to current code page
1134      * which may render this test unusable, so we're trying to avoid that.
1135      */
1136     SetLastError(0xdeadbeef);
1137     GetKerningPairsW(hdc, 0, NULL);
1138     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1139     {
1140         win_skip("Skipping the GetKerningPairs test on a Win9x platform\n");
1141         ReleaseDC(0, hdc);
1142         return;
1143     }
1144
1145     for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
1146     {
1147         OUTLINETEXTMETRICW otm;
1148
1149         if (!is_font_installed(kd[i].face_name))
1150         {
1151             trace("%s is not installed so skipping this test\n", kd[i].face_name);
1152             continue;
1153         }
1154
1155         trace("testing font %s, height %d\n", kd[i].face_name, kd[i].height);
1156
1157         memset(&lf, 0, sizeof(lf));
1158         strcpy(lf.lfFaceName, kd[i].face_name);
1159         lf.lfHeight = kd[i].height;
1160         hfont = CreateFontIndirect(&lf);
1161         assert(hfont != 0);
1162
1163         hfont_old = SelectObject(hdc, hfont);
1164
1165         SetLastError(0xdeadbeef);
1166         otm.otmSize = sizeof(otm); /* just in case for Win9x compatibility */
1167         ok(GetOutlineTextMetricsW(hdc, sizeof(otm), &otm) == sizeof(otm), "GetOutlineTextMetricsW error %d\n", GetLastError());
1168
1169         ok(kd[i].tmHeight == otm.otmTextMetrics.tmHeight, "expected %d, got %d\n",
1170            kd[i].tmHeight, otm.otmTextMetrics.tmHeight);
1171         ok(kd[i].tmAscent == otm.otmTextMetrics.tmAscent, "expected %d, got %d\n",
1172            kd[i].tmAscent, otm.otmTextMetrics.tmAscent);
1173         ok(kd[i].tmDescent == otm.otmTextMetrics.tmDescent, "expected %d, got %d\n",
1174            kd[i].tmDescent, otm.otmTextMetrics.tmDescent);
1175
1176         ok(kd[i].otmEMSquare == otm.otmEMSquare, "expected %u, got %u\n",
1177            kd[i].otmEMSquare, otm.otmEMSquare);
1178         ok(kd[i].otmAscent == otm.otmAscent, "expected %d, got %d\n",
1179            kd[i].otmAscent, otm.otmAscent);
1180         ok(kd[i].otmDescent == otm.otmDescent, "expected %d, got %d\n",
1181            kd[i].otmDescent, otm.otmDescent);
1182         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
1183            kd[i].otmLineGap, otm.otmLineGap);
1184         ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n",
1185            kd[i].otmMacDescent, otm.otmMacDescent);
1186 todo_wine {
1187         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
1188            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
1189         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
1190            kd[i].otmsXHeight, otm.otmsXHeight);
1191         ok(kd[i].otmMacAscent == otm.otmMacAscent, "expected %d, got %d\n",
1192            kd[i].otmMacAscent, otm.otmMacAscent);
1193         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
1194         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
1195            kd[i].otmMacLineGap, otm.otmMacLineGap);
1196         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
1197            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
1198 }
1199
1200         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
1201         trace("total_kern_pairs %u\n", total_kern_pairs);
1202         kern_pair = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pair));
1203
1204 #if 0 /* Win98 (GetKerningPairsA) and XP behave differently here, the test passes on XP */
1205         SetLastError(0xdeadbeef);
1206         ret = GetKerningPairsW(hdc, 0, kern_pair);
1207         ok(GetLastError() == ERROR_INVALID_PARAMETER,
1208            "got error %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
1209         ok(ret == 0, "got %lu, expected 0\n", ret);
1210 #endif
1211
1212         ret = GetKerningPairsW(hdc, 100, NULL);
1213         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1214
1215         ret = GetKerningPairsW(hdc, total_kern_pairs/2, kern_pair);
1216         ok(ret == total_kern_pairs/2, "got %u, expected %u\n", ret, total_kern_pairs/2);
1217
1218         ret = GetKerningPairsW(hdc, total_kern_pairs, kern_pair);
1219         ok(ret == total_kern_pairs, "got %u, expected %u\n", ret, total_kern_pairs);
1220
1221         matches = 0;
1222
1223         for (n = 0; n < ret; n++)
1224         {
1225             DWORD j;
1226 #if 0
1227             if (kern_pair[n].wFirst < 127 && kern_pair[n].wSecond < 127)
1228                 trace("{'%c','%c',%d},\n",
1229                       kern_pair[n].wFirst, kern_pair[n].wSecond, kern_pair[n].iKernAmount);
1230 #endif
1231             for (j = 0; j < kd[i].total_kern_pairs; j++)
1232             {
1233                 if (kern_pair[n].wFirst == kd[i].kern_pair[j].wFirst &&
1234                     kern_pair[n].wSecond == kd[i].kern_pair[j].wSecond)
1235                 {
1236                     ok(kern_pair[n].iKernAmount == kd[i].kern_pair[j].iKernAmount,
1237                        "pair %d:%d got %d, expected %d\n",
1238                        kern_pair[n].wFirst, kern_pair[n].wSecond,
1239                        kern_pair[n].iKernAmount, kd[i].kern_pair[j].iKernAmount);
1240                     matches++;
1241                 }
1242             }
1243         }
1244
1245         ok(matches == kd[i].total_kern_pairs, "got matches %u, expected %u\n",
1246            matches, kd[i].total_kern_pairs);
1247
1248         HeapFree(GetProcessHeap(), 0, kern_pair);
1249
1250         SelectObject(hdc, hfont_old);
1251         DeleteObject(hfont);
1252     }
1253
1254     ReleaseDC(0, hdc);
1255 }
1256
1257 static void test_GetOutlineTextMetrics(void)
1258 {
1259     OUTLINETEXTMETRIC *otm;
1260     LOGFONT lf;
1261     HFONT hfont, hfont_old;
1262     HDC hdc;
1263     DWORD ret, otm_size;
1264     LPSTR unset_ptr;
1265
1266     if (!is_font_installed("Arial"))
1267     {
1268         skip("Arial is not installed\n");
1269         return;
1270     }
1271
1272     hdc = GetDC(0);
1273
1274     memset(&lf, 0, sizeof(lf));
1275     strcpy(lf.lfFaceName, "Arial");
1276     lf.lfHeight = -13;
1277     lf.lfWeight = FW_NORMAL;
1278     lf.lfPitchAndFamily = DEFAULT_PITCH;
1279     lf.lfQuality = PROOF_QUALITY;
1280     hfont = CreateFontIndirect(&lf);
1281     assert(hfont != 0);
1282
1283     hfont_old = SelectObject(hdc, hfont);
1284     otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
1285     trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
1286
1287     otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
1288
1289     memset(otm, 0xAA, otm_size);
1290     SetLastError(0xdeadbeef);
1291     otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
1292     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1293     ok(ret == 1 /* Win9x */ ||
1294        ret == otm->otmSize /* XP*/,
1295        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1296     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1297     {
1298         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1299         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1300         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1301         ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
1302     }
1303
1304     memset(otm, 0xAA, otm_size);
1305     SetLastError(0xdeadbeef);
1306     otm->otmSize = otm_size; /* just in case for Win9x compatibility */
1307     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1308     ok(ret == 1 /* Win9x */ ||
1309        ret == otm->otmSize /* XP*/,
1310        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1311     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1312     {
1313         ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
1314         ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
1315         ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
1316         ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
1317     }
1318
1319     /* ask about truncated data */
1320     memset(otm, 0xAA, otm_size);
1321     memset(&unset_ptr, 0xAA, sizeof(unset_ptr));
1322     SetLastError(0xdeadbeef);
1323     otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
1324     ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
1325     ok(ret == 1 /* Win9x */ ||
1326        ret == otm->otmSize /* XP*/,
1327        "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
1328     if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
1329     {
1330         ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
1331         ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
1332         ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
1333     }
1334     ok(otm->otmpFullName == unset_ptr, "expected %p got %p\n", unset_ptr, otm->otmpFullName);
1335
1336     HeapFree(GetProcessHeap(), 0, otm);
1337
1338     SelectObject(hdc, hfont_old);
1339     DeleteObject(hfont);
1340
1341     ReleaseDC(0, hdc);
1342 }
1343
1344 static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
1345 {
1346     INT         x, y,
1347                 breakCount,
1348                 justifiedWidth = 0, /* to test GetTextExtentExPointW() */
1349                 areaWidth = clientArea->right - clientArea->left,
1350                 nErrors = 0, e;
1351     BOOL        lastExtent = FALSE;
1352     PSTR        pFirstChar, pLastChar;
1353     SIZE        size;
1354     TEXTMETRICA tm;
1355     struct err
1356     {
1357         char extent[100];
1358         int  GetTextExtentExPointWWidth;
1359     } error[10];
1360
1361     GetTextMetricsA(hdc, &tm);
1362     y = clientArea->top;
1363     do {
1364         breakCount = 0;
1365         while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
1366         pFirstChar = str;
1367
1368         do {
1369             pLastChar = str;
1370
1371             /* if not at the end of the string, ... */
1372             if (*str == '\0') break;
1373             /* ... add the next word to the current extent */
1374             while (*str != '\0' && *str++ != tm.tmBreakChar);
1375             breakCount++;
1376             SetTextJustification(hdc, 0, 0);
1377             GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
1378         } while ((int) size.cx < areaWidth);
1379
1380         /* ignore trailing break chars */
1381         breakCount--;
1382         while (*(pLastChar - 1) == tm.tmBreakChar)
1383         {
1384             pLastChar--;
1385             breakCount--;
1386         }
1387
1388         if (*str == '\0' || breakCount <= 0) pLastChar = str;
1389
1390         SetTextJustification(hdc, 0, 0);
1391         GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1392
1393         /* do not justify the last extent */
1394         if (*str != '\0' && breakCount > 0)
1395         {
1396             SetTextJustification(hdc, areaWidth - size.cx, breakCount);
1397             GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
1398             justifiedWidth = size.cx;
1399         }
1400         else lastExtent = TRUE;
1401
1402         x = clientArea->left;
1403
1404         /* catch errors and report them */
1405         if (!lastExtent && (justifiedWidth != areaWidth))
1406         {
1407             memset(error[nErrors].extent, 0, 100);
1408             memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
1409             error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
1410             nErrors++;
1411         }
1412
1413         y += size.cy;
1414         str = pLastChar;
1415     } while (*str && y < clientArea->bottom);
1416
1417     for (e = 0; e < nErrors; e++)
1418     {
1419         /* The width returned by GetTextExtentPoint32() is exactly the same
1420            returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
1421         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
1422             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
1423             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
1424     }
1425 }
1426
1427 static void test_SetTextJustification(void)
1428 {
1429     HDC hdc;
1430     RECT clientArea;
1431     LOGFONTA lf;
1432     HFONT hfont;
1433     HWND hwnd;
1434     static char testText[] =
1435             "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
1436             "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
1437             "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
1438             "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
1439             "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
1440             "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
1441             "sunt in culpa qui officia deserunt mollit anim id est laborum.";
1442
1443     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0, 400,400, 0, 0, 0, NULL);
1444     GetClientRect( hwnd, &clientArea );
1445     hdc = GetDC( hwnd );
1446
1447     memset(&lf, 0, sizeof lf);
1448     lf.lfCharSet = ANSI_CHARSET;
1449     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1450     lf.lfWeight = FW_DONTCARE;
1451     lf.lfHeight = 20;
1452     lf.lfQuality = DEFAULT_QUALITY;
1453     lstrcpyA(lf.lfFaceName, "Times New Roman");
1454     hfont = create_font("Times New Roman", &lf);
1455     SelectObject(hdc, hfont);
1456
1457     testJustification(hdc, testText, &clientArea);
1458
1459     DeleteObject(hfont);
1460     ReleaseDC(hwnd, hdc);
1461     DestroyWindow(hwnd);
1462 }
1463
1464 static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
1465 {
1466     HDC hdc;
1467     LOGFONTA lf;
1468     HFONT hfont, hfont_old;
1469     CHARSETINFO csi;
1470     FONTSIGNATURE fs;
1471     INT cs;
1472     DWORD i, ret;
1473     char name[64];
1474
1475     assert(count <= 128);
1476
1477     memset(&lf, 0, sizeof(lf));
1478
1479     lf.lfCharSet = charset;
1480     lf.lfHeight = 10;
1481     lstrcpyA(lf.lfFaceName, "Arial");
1482     SetLastError(0xdeadbeef);
1483     hfont = CreateFontIndirectA(&lf);
1484     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
1485
1486     hdc = GetDC(0);
1487     hfont_old = SelectObject(hdc, hfont);
1488
1489     cs = GetTextCharsetInfo(hdc, &fs, 0);
1490     ok(cs == charset, "expected %d, got %d\n", charset, cs);
1491
1492     SetLastError(0xdeadbeef);
1493     ret = GetTextFaceA(hdc, sizeof(name), name);
1494     ok(ret, "GetTextFaceA error %u\n", GetLastError());
1495
1496     if (charset == SYMBOL_CHARSET)
1497     {
1498         ok(strcmp("Arial", name), "face name should NOT be Arial\n");
1499         ok(fs.fsCsb[0] & (1 << 31), "symbol encoding should be available\n");
1500     }
1501     else
1502     {
1503         ok(!strcmp("Arial", name), "face name should be Arial, not %s\n", name);
1504         ok(!(fs.fsCsb[0] & (1 << 31)), "symbol encoding should NOT be available\n");
1505     }
1506
1507     if (!TranslateCharsetInfo((DWORD *)(INT_PTR)cs, &csi, TCI_SRCCHARSET))
1508     {
1509         trace("Can't find codepage for charset %d\n", cs);
1510         ReleaseDC(0, hdc);
1511         return FALSE;
1512     }
1513     ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
1514
1515     if (unicode)
1516     {
1517         char ansi_buf[128];
1518         WCHAR unicode_buf[128];
1519
1520         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1521
1522         MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
1523
1524         SetLastError(0xdeadbeef);
1525         ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
1526         ok(ret == count, "GetGlyphIndicesW error %u\n", GetLastError());
1527     }
1528     else
1529     {
1530         char ansi_buf[128];
1531
1532         for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
1533
1534         SetLastError(0xdeadbeef);
1535         ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
1536         ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
1537     }
1538
1539     SelectObject(hdc, hfont_old);
1540     DeleteObject(hfont);
1541
1542     ReleaseDC(0, hdc);
1543
1544     return TRUE;
1545 }
1546
1547 static void test_font_charset(void)
1548 {
1549     static struct charset_data
1550     {
1551         INT charset;
1552         UINT code_page;
1553         WORD font_idxA[128], font_idxW[128];
1554     } cd[] =
1555     {
1556         { ANSI_CHARSET, 1252 },
1557         { RUSSIAN_CHARSET, 1251 },
1558         { SYMBOL_CHARSET, CP_SYMBOL } /* keep it as the last one */
1559     };
1560     int i;
1561
1562     if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
1563     {
1564         win_skip("Skipping the font charset test on a Win9x platform\n");
1565         return;
1566     }
1567
1568     if (!is_font_installed("Arial"))
1569     {
1570         skip("Arial is not installed\n");
1571         return;
1572     }
1573
1574     for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
1575     {
1576         if (cd[i].charset == SYMBOL_CHARSET)
1577         {
1578             if (!is_font_installed("Symbol") && !is_font_installed("Wingdings"))
1579             {
1580                 skip("Symbol or Wingdings is not installed\n");
1581                 break;
1582             }
1583         }
1584         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
1585         get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
1586         ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128*sizeof(WORD)), "%d: indices don't match\n", i);
1587     }
1588
1589     ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
1590     if (i > 2)
1591     {
1592         ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
1593         ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
1594     }
1595     else
1596         skip("Symbol or Wingdings is not installed\n");
1597 }
1598
1599 static void test_GetFontUnicodeRanges(void)
1600 {
1601     LOGFONTA lf;
1602     HDC hdc;
1603     HFONT hfont, hfont_old;
1604     DWORD size;
1605     GLYPHSET *gs;
1606
1607     if (!pGetFontUnicodeRanges)
1608     {
1609         win_skip("GetFontUnicodeRanges not available before W2K\n");
1610         return;
1611     }
1612
1613     memset(&lf, 0, sizeof(lf));
1614     lstrcpyA(lf.lfFaceName, "Arial");
1615     hfont = create_font("Arial", &lf);
1616
1617     hdc = GetDC(0);
1618     hfont_old = SelectObject(hdc, hfont);
1619
1620     size = pGetFontUnicodeRanges(NULL, NULL);
1621     ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
1622
1623     size = pGetFontUnicodeRanges(hdc, NULL);
1624     ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
1625
1626     gs = HeapAlloc(GetProcessHeap(), 0, size);
1627
1628     size = pGetFontUnicodeRanges(hdc, gs);
1629     ok(size, "GetFontUnicodeRanges failed\n");
1630 #if 0
1631     for (i = 0; i < gs->cRanges; i++)
1632         trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
1633 #endif
1634     trace("found %u ranges\n", gs->cRanges);
1635
1636     HeapFree(GetProcessHeap(), 0, gs);
1637
1638     SelectObject(hdc, hfont_old);
1639     DeleteObject(hfont);
1640     ReleaseDC(NULL, hdc);
1641 }
1642
1643 #define MAX_ENUM_FONTS 4096
1644
1645 struct enum_font_data
1646 {
1647     int total;
1648     LOGFONT lf[MAX_ENUM_FONTS];
1649 };
1650
1651 struct enum_font_dataW
1652 {
1653     int total;
1654     LOGFONTW lf[MAX_ENUM_FONTS];
1655 };
1656
1657 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
1658 {
1659     struct enum_font_data *efd = (struct enum_font_data *)lParam;
1660
1661     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1662
1663     if (type != TRUETYPE_FONTTYPE) return 1;
1664 #if 0
1665     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1666           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1667 #endif
1668     if (efd->total < MAX_ENUM_FONTS)
1669         efd->lf[efd->total++] = *lf;
1670     else
1671         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1672
1673     return 1;
1674 }
1675
1676 static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1677 {
1678     struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
1679
1680     ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
1681
1682     if (type != TRUETYPE_FONTTYPE) return 1;
1683 #if 0
1684     trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
1685           lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
1686 #endif
1687     if (efd->total < MAX_ENUM_FONTS)
1688         efd->lf[efd->total++] = *lf;
1689     else
1690         trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
1691
1692     return 1;
1693 }
1694
1695 static void get_charset_stats(struct enum_font_data *efd,
1696                               int *ansi_charset, int *symbol_charset,
1697                               int *russian_charset)
1698 {
1699     int i;
1700
1701     *ansi_charset = 0;
1702     *symbol_charset = 0;
1703     *russian_charset = 0;
1704
1705     for (i = 0; i < efd->total; i++)
1706     {
1707         switch (efd->lf[i].lfCharSet)
1708         {
1709         case ANSI_CHARSET:
1710             (*ansi_charset)++;
1711             break;
1712         case SYMBOL_CHARSET:
1713             (*symbol_charset)++;
1714             break;
1715         case RUSSIAN_CHARSET:
1716             (*russian_charset)++;
1717             break;
1718         }
1719     }
1720 }
1721
1722 static void get_charset_statsW(struct enum_font_dataW *efd,
1723                               int *ansi_charset, int *symbol_charset,
1724                               int *russian_charset)
1725 {
1726     int i;
1727
1728     *ansi_charset = 0;
1729     *symbol_charset = 0;
1730     *russian_charset = 0;
1731
1732     for (i = 0; i < efd->total; i++)
1733     {
1734         switch (efd->lf[i].lfCharSet)
1735         {
1736         case ANSI_CHARSET:
1737             (*ansi_charset)++;
1738             break;
1739         case SYMBOL_CHARSET:
1740             (*symbol_charset)++;
1741             break;
1742         case RUSSIAN_CHARSET:
1743             (*russian_charset)++;
1744             break;
1745         }
1746     }
1747 }
1748
1749 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
1750 {
1751     struct enum_font_data efd;
1752     struct enum_font_dataW efdw;
1753     LOGFONT lf;
1754     HDC hdc;
1755     int i, ret, ansi_charset, symbol_charset, russian_charset;
1756
1757     trace("Testing font %s, charset %d\n", *font_name ? font_name : "<empty>", font_charset);
1758
1759     if (*font_name && !is_truetype_font_installed(font_name))
1760     {
1761         skip("%s is not installed\n", font_name);
1762         return;
1763     }
1764
1765     hdc = GetDC(0);
1766
1767     /* Observed behaviour: EnumFontFamilies enumerates aliases like "Arial Cyr"
1768      * while EnumFontFamiliesEx doesn't.
1769      */
1770     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
1771     {
1772         /*
1773          * Use EnumFontFamiliesW since win98 crashes when the
1774          *    second parameter is NULL using EnumFontFamilies
1775          */
1776         efdw.total = 0;
1777         SetLastError(0xdeadbeef);
1778         ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
1779         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError());
1780         if(ret)
1781         {
1782             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1783             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1784                   ansi_charset, symbol_charset, russian_charset);
1785             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1786             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1787             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1788             ok(russian_charset > 0 ||
1789                broken(russian_charset == 0), /* NT4 */
1790                "NULL family should enumerate RUSSIAN_CHARSET\n");
1791         }
1792
1793         efdw.total = 0;
1794         SetLastError(0xdeadbeef);
1795         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1796         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1797         if(ret)
1798         {
1799             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1800             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1801                   ansi_charset, symbol_charset, russian_charset);
1802             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1803             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1804             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1805             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1806         }
1807     }
1808
1809     efd.total = 0;
1810     SetLastError(0xdeadbeef);
1811     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1812     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1813     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1814     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1815           ansi_charset, symbol_charset, russian_charset,
1816           *font_name ? font_name : "<empty>");
1817     if (*font_name)
1818         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1819     else
1820         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1821     for (i = 0; i < efd.total; i++)
1822     {
1823 /* FIXME: remove completely once Wine is fixed */
1824 if (efd.lf[i].lfCharSet != font_charset)
1825 {
1826 todo_wine
1827     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1828 }
1829 else
1830         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1831         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1832            font_name, efd.lf[i].lfFaceName);
1833     }
1834
1835     memset(&lf, 0, sizeof(lf));
1836     lf.lfCharSet = ANSI_CHARSET;
1837     lstrcpy(lf.lfFaceName, font_name);
1838     efd.total = 0;
1839     SetLastError(0xdeadbeef);
1840     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1841     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1842     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1843     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1844           ansi_charset, symbol_charset, russian_charset,
1845           *font_name ? font_name : "<empty>");
1846     if (font_charset == SYMBOL_CHARSET)
1847     {
1848         if (*font_name)
1849             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1850         else
1851             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1852     }
1853     else
1854     {
1855         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1856         for (i = 0; i < efd.total; i++)
1857         {
1858             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1859             if (*font_name)
1860                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1861                    font_name, efd.lf[i].lfFaceName);
1862         }
1863     }
1864
1865     /* DEFAULT_CHARSET should enumerate all available charsets */
1866     memset(&lf, 0, sizeof(lf));
1867     lf.lfCharSet = DEFAULT_CHARSET;
1868     lstrcpy(lf.lfFaceName, font_name);
1869     efd.total = 0;
1870     SetLastError(0xdeadbeef);
1871     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1872     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1873     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1874     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1875           ansi_charset, symbol_charset, russian_charset,
1876           *font_name ? font_name : "<empty>");
1877     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1878     for (i = 0; i < efd.total; i++)
1879     {
1880         if (*font_name)
1881             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1882                font_name, efd.lf[i].lfFaceName);
1883     }
1884     if (*font_name)
1885     {
1886         switch (font_charset)
1887         {
1888         case ANSI_CHARSET:
1889             ok(ansi_charset > 0,
1890                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1891             ok(!symbol_charset,
1892                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1893             ok(russian_charset > 0,
1894                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1895             break;
1896         case SYMBOL_CHARSET:
1897             ok(!ansi_charset,
1898                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1899             ok(symbol_charset,
1900                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1901             ok(!russian_charset,
1902                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1903             break;
1904         case DEFAULT_CHARSET:
1905             ok(ansi_charset > 0,
1906                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1907             ok(symbol_charset > 0,
1908                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1909             ok(russian_charset > 0,
1910                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1911             break;
1912         }
1913     }
1914     else
1915     {
1916         ok(ansi_charset > 0,
1917            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1918         ok(symbol_charset > 0,
1919            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1920         ok(russian_charset > 0,
1921            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1922     }
1923
1924     memset(&lf, 0, sizeof(lf));
1925     lf.lfCharSet = SYMBOL_CHARSET;
1926     lstrcpy(lf.lfFaceName, font_name);
1927     efd.total = 0;
1928     SetLastError(0xdeadbeef);
1929     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1930     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1931     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1932     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1933           ansi_charset, symbol_charset, russian_charset,
1934           *font_name ? font_name : "<empty>");
1935     if (*font_name && font_charset == ANSI_CHARSET)
1936         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1937     else
1938     {
1939         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1940         for (i = 0; i < efd.total; i++)
1941         {
1942             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1943             if (*font_name)
1944                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1945                    font_name, efd.lf[i].lfFaceName);
1946         }
1947
1948         ok(!ansi_charset,
1949            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1950         ok(symbol_charset > 0,
1951            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1952         ok(!russian_charset,
1953            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1954     }
1955
1956     ReleaseDC(0, hdc);
1957 }
1958
1959 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1960 {
1961     HFONT hfont, hfont_prev;
1962     DWORD ret;
1963     GLYPHMETRICS gm1, gm2;
1964     LOGFONTA lf2 = *lf;
1965     WORD idx;
1966     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1967
1968     if(!pGetGlyphIndicesA)
1969         return;
1970
1971     /* negative widths are handled just as positive ones */
1972     lf2.lfWidth = -lf->lfWidth;
1973
1974     SetLastError(0xdeadbeef);
1975     hfont = CreateFontIndirectA(lf);
1976     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1977     check_font("original", lf, hfont);
1978
1979     hfont_prev = SelectObject(hdc, hfont);
1980
1981     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1982     if (ret == GDI_ERROR || idx == 0xffff)
1983     {
1984         SelectObject(hdc, hfont_prev);
1985         DeleteObject(hfont);
1986         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1987         return;
1988     }
1989
1990     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1991     memset(&gm1, 0xab, sizeof(gm1));
1992     SetLastError(0xdeadbeef);
1993     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1994     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1995
1996     SelectObject(hdc, hfont_prev);
1997     DeleteObject(hfont);
1998
1999     SetLastError(0xdeadbeef);
2000     hfont = CreateFontIndirectA(&lf2);
2001     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2002     check_font("negative width", &lf2, hfont);
2003
2004     hfont_prev = SelectObject(hdc, hfont);
2005
2006     memset(&gm2, 0xbb, sizeof(gm2));
2007     SetLastError(0xdeadbeef);
2008     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2009     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2010
2011     SelectObject(hdc, hfont_prev);
2012     DeleteObject(hfont);
2013
2014     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2015        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2016        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2017        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2018        gm1.gmCellIncX == gm2.gmCellIncX &&
2019        gm1.gmCellIncY == gm2.gmCellIncY,
2020        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2021        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2022        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2023        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2024        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2025 }
2026
2027 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2028 #include "pshpack2.h"
2029 typedef struct
2030 {
2031     USHORT version;
2032     SHORT xAvgCharWidth;
2033     USHORT usWeightClass;
2034     USHORT usWidthClass;
2035     SHORT fsType;
2036     SHORT ySubscriptXSize;
2037     SHORT ySubscriptYSize;
2038     SHORT ySubscriptXOffset;
2039     SHORT ySubscriptYOffset;
2040     SHORT ySuperscriptXSize;
2041     SHORT ySuperscriptYSize;
2042     SHORT ySuperscriptXOffset;
2043     SHORT ySuperscriptYOffset;
2044     SHORT yStrikeoutSize;
2045     SHORT yStrikeoutPosition;
2046     SHORT sFamilyClass;
2047     PANOSE panose;
2048     ULONG ulUnicodeRange1;
2049     ULONG ulUnicodeRange2;
2050     ULONG ulUnicodeRange3;
2051     ULONG ulUnicodeRange4;
2052     CHAR achVendID[4];
2053     USHORT fsSelection;
2054     USHORT usFirstCharIndex;
2055     USHORT usLastCharIndex;
2056     /* According to the Apple spec, original version didn't have the below fields,
2057      * version numbers were taked from the OpenType spec.
2058      */
2059     /* version 0 (TrueType 1.5) */
2060     USHORT sTypoAscender;
2061     USHORT sTypoDescender;
2062     USHORT sTypoLineGap;
2063     USHORT usWinAscent;
2064     USHORT usWinDescent;
2065     /* version 1 (TrueType 1.66) */
2066     ULONG ulCodePageRange1;
2067     ULONG ulCodePageRange2;
2068     /* version 2 (OpenType 1.2) */
2069     SHORT sxHeight;
2070     SHORT sCapHeight;
2071     USHORT usDefaultChar;
2072     USHORT usBreakChar;
2073     USHORT usMaxContext;
2074 } TT_OS2_V2;
2075 #include "poppack.h"
2076
2077 #ifdef WORDS_BIGENDIAN
2078 #define GET_BE_WORD(x) (x)
2079 #define GET_BE_DWORD(x) (x)
2080 #else
2081 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2082 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2083 #endif
2084
2085 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2086                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2087                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2088 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2089 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2090
2091 typedef struct
2092 {
2093     USHORT version;
2094     USHORT num_tables;
2095 } cmap_header;
2096
2097 typedef struct
2098 {
2099     USHORT plat_id;
2100     USHORT enc_id;
2101     ULONG offset;
2102 } cmap_encoding_record;
2103
2104 typedef struct
2105 {
2106     USHORT format;
2107     USHORT length;
2108     USHORT language;
2109
2110     BYTE glyph_ids[256];
2111 } cmap_format_0;
2112
2113 typedef struct
2114 {
2115     USHORT format;
2116     USHORT length;
2117     USHORT language;
2118
2119     USHORT seg_countx2;
2120     USHORT search_range;
2121     USHORT entry_selector;
2122     USHORT range_shift;
2123
2124     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2125 /* Then follows:
2126     USHORT pad;
2127     USHORT start_count[seg_countx2 / 2];
2128     USHORT id_delta[seg_countx2 / 2];
2129     USHORT id_range_offset[seg_countx2 / 2];
2130     USHORT glyph_ids[];
2131 */
2132 } cmap_format_4;
2133
2134 typedef struct
2135 {
2136     USHORT end_count;
2137     USHORT start_count;
2138     USHORT id_delta;
2139     USHORT id_range_offset;
2140 } cmap_format_4_seg;
2141
2142 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2143 {
2144     ok((tmA->tmPitchAndFamily & 0xf0) == family, "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2145        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2146        os2->panose.bWeight, os2->panose.bProportion);
2147 }
2148
2149 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2150 {
2151     int i;
2152     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2153
2154     *first = 256;
2155
2156     for(i = 0; i < 256; i++)
2157     {
2158         if(cmap->glyph_ids[i] == 0) continue;
2159         *last = i;
2160         if(*first == 256) *first = i;
2161     }
2162     if(*first == 256) return FALSE;
2163     return TRUE;
2164 }
2165
2166 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2167 {
2168     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2169     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2170     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2171     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2172     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2173 }
2174
2175 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last)
2176 {
2177     int i;
2178     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2179     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2180     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2181
2182     *first = 0x10000;
2183
2184     for(i = 0; i < seg_count; i++)
2185     {
2186         DWORD code, index;
2187         cmap_format_4_seg seg;
2188
2189         get_seg4(cmap, i, &seg);
2190         for(code = seg.start_count; code <= seg.end_count; code++)
2191         {
2192             if(seg.id_range_offset == 0)
2193                 index = (seg.id_delta + code) & 0xffff;
2194             else
2195             {
2196                 index = seg.id_range_offset / 2
2197                     + code - seg.start_count
2198                     + i - seg_count;
2199
2200                 index = GET_BE_WORD(glyph_ids[index]);
2201                 if(index) index += seg.id_delta;
2202             }
2203             if(*first == 0x10000)
2204                 *last = *first = code;
2205             else if(index)
2206                 *last = code;
2207         }
2208     }
2209
2210     if(*first == 0x10000) return FALSE;
2211     return TRUE;
2212 }
2213
2214 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2215 {
2216     USHORT i;
2217     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2218
2219     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2220     {
2221         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2222             return (BYTE *)header + GET_BE_DWORD(record->offset);
2223         record++;
2224     }
2225     return NULL;
2226 }
2227
2228 typedef enum
2229 {
2230     cmap_none,
2231     cmap_ms_unicode,
2232     cmap_ms_symbol
2233 } cmap_type;
2234
2235 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2236 {
2237     LONG size, ret;
2238     cmap_header *header;
2239     void *cmap;
2240     BOOL r = FALSE;
2241     WORD format;
2242
2243     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2244     ok(size != GDI_ERROR, "no cmap table found\n");
2245     if(size == GDI_ERROR) return FALSE;
2246
2247     header = HeapAlloc(GetProcessHeap(), 0, size);
2248     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2249     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2250     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2251
2252     cmap = get_cmap(header, 3, 1);
2253     if(cmap)
2254         *cmap_type = cmap_ms_unicode;
2255     else
2256     {
2257         cmap = get_cmap(header, 3, 0);
2258         if(cmap) *cmap_type = cmap_ms_symbol;
2259     }
2260     if(!cmap)
2261     {
2262         *cmap_type = cmap_none;
2263         goto end;
2264     }
2265
2266     format = GET_BE_WORD(*(WORD *)cmap);
2267     switch(format)
2268     {
2269     case 0:
2270         r = get_first_last_from_cmap0(cmap, first, last);
2271         break;
2272     case 4:
2273         r = get_first_last_from_cmap4(cmap, first, last);
2274         break;
2275     default:
2276         trace("unhandled cmap format %d\n", format);
2277         break;
2278     }
2279
2280 end:
2281     HeapFree(GetProcessHeap(), 0, header);
2282     return r;
2283 }
2284
2285 static void test_text_metrics(const LOGFONTA *lf)
2286 {
2287     HDC hdc;
2288     HFONT hfont, hfont_old;
2289     TEXTMETRICA tmA;
2290     TT_OS2_V2 tt_os2;
2291     LONG size, ret;
2292     const char *font_name = lf->lfFaceName;
2293     DWORD cmap_first = 0, cmap_last = 0;
2294     cmap_type cmap_type;
2295
2296     hdc = GetDC(0);
2297
2298     SetLastError(0xdeadbeef);
2299     hfont = CreateFontIndirectA(lf);
2300     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2301
2302     hfont_old = SelectObject(hdc, hfont);
2303
2304     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2305     if (size == GDI_ERROR)
2306     {
2307         trace("OS/2 chunk was not found\n");
2308         goto end_of_test;
2309     }
2310     if (size > sizeof(tt_os2))
2311     {
2312         trace("got too large OS/2 chunk of size %u\n", size);
2313         size = sizeof(tt_os2);
2314     }
2315
2316     memset(&tt_os2, 0, sizeof(tt_os2));
2317     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2318     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2319
2320     SetLastError(0xdeadbeef);
2321     ret = GetTextMetricsA(hdc, &tmA);
2322     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2323
2324     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2325     {
2326         skip("Unable to retrieve first and last glyphs from cmap\n");
2327     }
2328     else
2329     {
2330         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2331         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2332         UINT os2_first_char, os2_last_char, default_char, break_char;
2333         USHORT version;
2334         TEXTMETRICW tmW;
2335
2336         version = GET_BE_WORD(tt_os2.version);
2337
2338         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2339         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2340         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2341         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2342
2343         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2344               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2345               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2346
2347         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2348         {
2349             expect_first_W    = 0;
2350             switch(GetACP())
2351             {
2352             case 1257:  /* Baltic */
2353                 expect_last_W = 0xf8fd;
2354                 break;
2355             default:
2356                 expect_last_W = 0xf0ff;
2357             }
2358             expect_break_W    = 0x20;
2359             expect_default_W  = expect_break_W - 1;
2360             expect_first_A    = 0x1e;
2361             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2362         }
2363         else
2364         {
2365             expect_first_W    = cmap_first;
2366             expect_last_W     = min(cmap_last, os2_last_char);
2367             if(os2_first_char <= 1)
2368                 expect_break_W = os2_first_char + 2;
2369             else if(os2_first_char > 0xff)
2370                 expect_break_W = 0x20;
2371             else
2372                 expect_break_W = os2_first_char;
2373             expect_default_W  = expect_break_W - 1;
2374             expect_first_A    = expect_default_W - 1;
2375             expect_last_A     = min(expect_last_W, 0xff);
2376         }
2377         expect_break_A    = expect_break_W;
2378         expect_default_A  = expect_default_W;
2379
2380         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2381         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2382             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2383                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2384                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2385         else
2386             ok(tmA.tmFirstChar == expect_first_A ||
2387                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2388                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2389         ok(tmA.tmLastChar == expect_last_A ||
2390            tmA.tmLastChar == 0xff /* win9x */,
2391            "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2392         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2393            font_name, tmA.tmBreakChar, expect_break_A);
2394         ok(tmA.tmDefaultChar == expect_default_A, "A: tmDefaultChar for %s got %02x expected %02x\n",
2395            font_name, tmA.tmDefaultChar, expect_default_A);
2396
2397
2398         SetLastError(0xdeadbeef);
2399         ret = GetTextMetricsW(hdc, &tmW);
2400         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2401            "GetTextMetricsW error %u\n", GetLastError());
2402         if (ret)
2403         {
2404             /* Wine uses the os2 first char */
2405             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2406                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2407                              font_name, tmW.tmFirstChar, expect_first_W);
2408             else
2409                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2410                    font_name, tmW.tmFirstChar, expect_first_W);
2411
2412             /* Wine uses the os2 last char */
2413             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2414                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2415                              font_name, tmW.tmLastChar, expect_last_W);
2416             else
2417                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2418                    font_name, tmW.tmLastChar, expect_last_W);
2419             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2420                font_name, tmW.tmBreakChar, expect_break_W);
2421             ok(tmW.tmDefaultChar == expect_default_W, "W: tmDefaultChar for %s got %02x expected %02x\n",
2422                font_name, tmW.tmDefaultChar, expect_default_W);
2423
2424             /* Test the aspect ratio while we have tmW */
2425             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2426             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2427                tmW.tmDigitizedAspectX, ret);
2428             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2429             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2430                tmW.tmDigitizedAspectX, ret);
2431         }
2432     }
2433
2434     /* test FF_ values */
2435     switch(tt_os2.panose.bFamilyType)
2436     {
2437     case PAN_ANY:
2438     case PAN_NO_FIT:
2439     case PAN_FAMILY_TEXT_DISPLAY:
2440     case PAN_FAMILY_PICTORIAL:
2441     default:
2442         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2443            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2444         {
2445             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2446             break;
2447         }
2448         switch(tt_os2.panose.bSerifStyle)
2449         {
2450         case PAN_ANY:
2451         case PAN_NO_FIT:
2452         default:
2453             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2454             break;
2455
2456         case PAN_SERIF_COVE:
2457         case PAN_SERIF_OBTUSE_COVE:
2458         case PAN_SERIF_SQUARE_COVE:
2459         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2460         case PAN_SERIF_SQUARE:
2461         case PAN_SERIF_THIN:
2462         case PAN_SERIF_BONE:
2463         case PAN_SERIF_EXAGGERATED:
2464         case PAN_SERIF_TRIANGLE:
2465             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2466             break;
2467
2468         case PAN_SERIF_NORMAL_SANS:
2469         case PAN_SERIF_OBTUSE_SANS:
2470         case PAN_SERIF_PERP_SANS:
2471         case PAN_SERIF_FLARED:
2472         case PAN_SERIF_ROUNDED:
2473             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2474             break;
2475         }
2476         break;
2477
2478     case PAN_FAMILY_SCRIPT:
2479         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2480         break;
2481
2482     case PAN_FAMILY_DECORATIVE:
2483         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2484         break;
2485     }
2486
2487     test_negative_width(hdc, lf);
2488
2489 end_of_test:
2490     SelectObject(hdc, hfont_old);
2491     DeleteObject(hfont);
2492
2493     ReleaseDC(0, hdc);
2494 }
2495
2496 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2497 {
2498     INT *enumed = (INT *)lParam;
2499
2500     if (type == TRUETYPE_FONTTYPE)
2501     {
2502         (*enumed)++;
2503         test_text_metrics(lf);
2504     }
2505     return 1;
2506 }
2507
2508 static void test_GetTextMetrics(void)
2509 {
2510     LOGFONTA lf;
2511     HDC hdc;
2512     INT enumed;
2513
2514     /* Report only once */
2515     if(!pGetGlyphIndicesA)
2516         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2517
2518     hdc = GetDC(0);
2519
2520     memset(&lf, 0, sizeof(lf));
2521     lf.lfCharSet = DEFAULT_CHARSET;
2522     enumed = 0;
2523     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2524     trace("Tested metrics of %d truetype fonts\n", enumed);
2525
2526     ReleaseDC(0, hdc);
2527 }
2528
2529 static void test_nonexistent_font(void)
2530 {
2531     static const struct
2532     {
2533         const char *name;
2534         int charset;
2535     } font_subst[] =
2536     {
2537         { "Times New Roman Baltic", 186 },
2538         { "Times New Roman CE", 238 },
2539         { "Times New Roman CYR", 204 },
2540         { "Times New Roman Greek", 161 },
2541         { "Times New Roman TUR", 162 }
2542     };
2543     LOGFONTA lf;
2544     HDC hdc;
2545     HFONT hfont;
2546     CHARSETINFO csi;
2547     INT cs, expected_cs, i;
2548     char buf[LF_FACESIZE];
2549
2550     if (!is_truetype_font_installed("Arial") ||
2551         !is_truetype_font_installed("Times New Roman"))
2552     {
2553         skip("Arial or Times New Roman not installed\n");
2554         return;
2555     }
2556
2557     expected_cs = GetACP();
2558     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2559     {
2560         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2561         return;
2562     }
2563     expected_cs = csi.ciCharset;
2564     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2565
2566     hdc = GetDC(0);
2567
2568     memset(&lf, 0, sizeof(lf));
2569     lf.lfHeight = 100;
2570     lf.lfWeight = FW_REGULAR;
2571     lf.lfCharSet = ANSI_CHARSET;
2572     lf.lfPitchAndFamily = FF_SWISS;
2573     strcpy(lf.lfFaceName, "Nonexistent font");
2574     hfont = CreateFontIndirectA(&lf);
2575     hfont = SelectObject(hdc, hfont);
2576     GetTextFaceA(hdc, sizeof(buf), buf);
2577     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2578     cs = GetTextCharset(hdc);
2579     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2580     DeleteObject(SelectObject(hdc, hfont));
2581
2582     memset(&lf, 0, sizeof(lf));
2583     lf.lfHeight = -13;
2584     lf.lfWeight = FW_DONTCARE;
2585     strcpy(lf.lfFaceName, "Nonexistent font");
2586     hfont = CreateFontIndirectA(&lf);
2587     hfont = SelectObject(hdc, hfont);
2588     GetTextFaceA(hdc, sizeof(buf), buf);
2589 todo_wine /* Wine uses Arial for all substitutions */
2590     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2591        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2592        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2593        "Got %s\n", buf);
2594     cs = GetTextCharset(hdc);
2595     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2596     DeleteObject(SelectObject(hdc, hfont));
2597
2598     memset(&lf, 0, sizeof(lf));
2599     lf.lfHeight = -13;
2600     lf.lfWeight = FW_REGULAR;
2601     strcpy(lf.lfFaceName, "Nonexistent font");
2602     hfont = CreateFontIndirectA(&lf);
2603     hfont = SelectObject(hdc, hfont);
2604     GetTextFaceA(hdc, sizeof(buf), buf);
2605     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2606        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2607     cs = GetTextCharset(hdc);
2608     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2609     DeleteObject(SelectObject(hdc, hfont));
2610
2611     memset(&lf, 0, sizeof(lf));
2612     lf.lfHeight = -13;
2613     lf.lfWeight = FW_DONTCARE;
2614     strcpy(lf.lfFaceName, "Times New Roman");
2615     hfont = CreateFontIndirectA(&lf);
2616     hfont = SelectObject(hdc, hfont);
2617     GetTextFaceA(hdc, sizeof(buf), buf);
2618     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2619     cs = GetTextCharset(hdc);
2620     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2621     DeleteObject(SelectObject(hdc, hfont));
2622
2623     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2624     {
2625         memset(&lf, 0, sizeof(lf));
2626         lf.lfHeight = -13;
2627         lf.lfWeight = FW_REGULAR;
2628         strcpy(lf.lfFaceName, font_subst[i].name);
2629         hfont = CreateFontIndirectA(&lf);
2630         hfont = SelectObject(hdc, hfont);
2631         cs = GetTextCharset(hdc);
2632         if (font_subst[i].charset == expected_cs)
2633         {
2634             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2635             GetTextFaceA(hdc, sizeof(buf), buf);
2636             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2637         }
2638         else
2639         {
2640             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2641             GetTextFaceA(hdc, sizeof(buf), buf);
2642             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2643                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2644         }
2645         DeleteObject(SelectObject(hdc, hfont));
2646
2647         memset(&lf, 0, sizeof(lf));
2648         lf.lfHeight = -13;
2649         lf.lfWeight = FW_DONTCARE;
2650         strcpy(lf.lfFaceName, font_subst[i].name);
2651         hfont = CreateFontIndirectA(&lf);
2652         hfont = SelectObject(hdc, hfont);
2653         GetTextFaceA(hdc, sizeof(buf), buf);
2654         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2655            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2656            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2657            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2658            "got %s for font %s\n", buf, font_subst[i].name);
2659         cs = GetTextCharset(hdc);
2660         ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2661         DeleteObject(SelectObject(hdc, hfont));
2662     }
2663
2664     ReleaseDC(0, hdc);
2665 }
2666
2667 static void test_GdiRealizationInfo(void)
2668 {
2669     HDC hdc;
2670     DWORD info[4];
2671     BOOL r;
2672     HFONT hfont, hfont_old;
2673     LOGFONTA lf;
2674
2675     if(!pGdiRealizationInfo)
2676     {
2677         win_skip("GdiRealizationInfo not available\n");
2678         return;
2679     }
2680
2681     hdc = GetDC(0);
2682
2683     memset(info, 0xcc, sizeof(info));
2684     r = pGdiRealizationInfo(hdc, info);
2685     ok(r != 0, "ret 0\n");
2686     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2687     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2688
2689     if (!is_truetype_font_installed("Arial"))
2690     {
2691         skip("skipping GdiRealizationInfo with truetype font\n");
2692         goto end;
2693     }
2694
2695     memset(&lf, 0, sizeof(lf));
2696     strcpy(lf.lfFaceName, "Arial");
2697     lf.lfHeight = 20;
2698     lf.lfWeight = FW_NORMAL;
2699     hfont = CreateFontIndirectA(&lf);
2700     hfont_old = SelectObject(hdc, hfont);
2701
2702     memset(info, 0xcc, sizeof(info));
2703     r = pGdiRealizationInfo(hdc, info);
2704     ok(r != 0, "ret 0\n");
2705     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2706     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2707
2708     DeleteObject(SelectObject(hdc, hfont_old));
2709
2710  end:
2711     ReleaseDC(0, hdc);
2712 }
2713
2714 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2715    the nul in the count of characters copied when the face name buffer is not
2716    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2717    always includes it.  */
2718 static void test_GetTextFace(void)
2719 {
2720     static const char faceA[] = "Tahoma";
2721     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2722     LOGFONTA fA = {0};
2723     LOGFONTW fW = {0};
2724     char bufA[LF_FACESIZE];
2725     WCHAR bufW[LF_FACESIZE];
2726     HFONT f, g;
2727     HDC dc;
2728     int n;
2729
2730     if(!is_font_installed("Tahoma"))
2731     {
2732         skip("Tahoma is not installed so skipping this test\n");
2733         return;
2734     }
2735
2736     /* 'A' case.  */
2737     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2738     f = CreateFontIndirectA(&fA);
2739     ok(f != NULL, "CreateFontIndirectA failed\n");
2740
2741     dc = GetDC(NULL);
2742     g = SelectObject(dc, f);
2743     n = GetTextFaceA(dc, sizeof bufA, bufA);
2744     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2745     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2746
2747     /* Play with the count arg.  */
2748     bufA[0] = 'x';
2749     n = GetTextFaceA(dc, 0, bufA);
2750     ok(n == 0, "GetTextFaceA returned %d\n", n);
2751     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2752
2753     bufA[0] = 'x';
2754     n = GetTextFaceA(dc, 1, bufA);
2755     ok(n == 0, "GetTextFaceA returned %d\n", n);
2756     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2757
2758     bufA[0] = 'x'; bufA[1] = 'y';
2759     n = GetTextFaceA(dc, 2, bufA);
2760     ok(n == 1, "GetTextFaceA returned %d\n", n);
2761     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2762
2763     n = GetTextFaceA(dc, 0, NULL);
2764     ok(n == sizeof faceA ||
2765        broken(n == 0), /* win98, winMe */
2766        "GetTextFaceA returned %d\n", n);
2767
2768     DeleteObject(SelectObject(dc, g));
2769     ReleaseDC(NULL, dc);
2770
2771     /* 'W' case.  */
2772     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2773     SetLastError(0xdeadbeef);
2774     f = CreateFontIndirectW(&fW);
2775     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2776     {
2777         win_skip("CreateFontIndirectW is not implemented\n");
2778         return;
2779     }
2780     ok(f != NULL, "CreateFontIndirectW failed\n");
2781
2782     dc = GetDC(NULL);
2783     g = SelectObject(dc, f);
2784     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2785     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2786     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2787
2788     /* Play with the count arg.  */
2789     bufW[0] = 'x';
2790     n = GetTextFaceW(dc, 0, bufW);
2791     ok(n == 0, "GetTextFaceW returned %d\n", n);
2792     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2793
2794     bufW[0] = 'x';
2795     n = GetTextFaceW(dc, 1, bufW);
2796     ok(n == 1, "GetTextFaceW returned %d\n", n);
2797     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2798
2799     bufW[0] = 'x'; bufW[1] = 'y';
2800     n = GetTextFaceW(dc, 2, bufW);
2801     ok(n == 2, "GetTextFaceW returned %d\n", n);
2802     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2803
2804     n = GetTextFaceW(dc, 0, NULL);
2805     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2806
2807     DeleteObject(SelectObject(dc, g));
2808     ReleaseDC(NULL, dc);
2809 }
2810
2811 static void test_orientation(void)
2812 {
2813     static const char test_str[11] = "Test String";
2814     HDC hdc;
2815     LOGFONTA lf;
2816     HFONT hfont, old_hfont;
2817     SIZE size;
2818
2819     if (!is_truetype_font_installed("Arial"))
2820     {
2821         skip("Arial is not installed\n");
2822         return;
2823     }
2824
2825     hdc = CreateCompatibleDC(0);
2826     memset(&lf, 0, sizeof(lf));
2827     lstrcpyA(lf.lfFaceName, "Arial");
2828     lf.lfHeight = 72;
2829     lf.lfOrientation = lf.lfEscapement = 900;
2830     hfont = create_font("orientation", &lf);
2831     old_hfont = SelectObject(hdc, hfont);
2832     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2833     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2834     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2835     SelectObject(hdc, old_hfont);
2836     DeleteObject(hfont);
2837     DeleteDC(hdc);
2838 }
2839
2840 static void test_GetGlyphOutline(void)
2841 {
2842     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2843     HDC hdc;
2844     GLYPHMETRICS gm;
2845     LOGFONTA lf;
2846     HFONT hfont, old_hfont;
2847     INT ret;
2848
2849     if (!is_truetype_font_installed("Tahoma"))
2850     {
2851         skip("Tahoma is not installed\n");
2852         return;
2853     }
2854
2855     hdc = CreateCompatibleDC(0);
2856     memset(&lf, 0, sizeof(lf));
2857     lf.lfHeight = 72;
2858     lstrcpyA(lf.lfFaceName, "Tahoma");
2859     SetLastError(0xdeadbeef);
2860     hfont = CreateFontIndirectA(&lf);
2861     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2862     old_hfont = SelectObject(hdc, hfont);
2863
2864     memset(&gm, 0, sizeof(gm));
2865     SetLastError(0xdeadbeef);
2866     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2867     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
2868
2869     memset(&gm, 0, sizeof(gm));
2870     SetLastError(0xdeadbeef);
2871     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2872     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
2873     ok(GetLastError() == 0xdeadbeef ||
2874        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
2875        "expected 0xdeadbeef, got %u\n", GetLastError());
2876
2877     memset(&gm, 0, sizeof(gm));
2878     SetLastError(0xdeadbeef);
2879     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2880     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2881         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
2882
2883     memset(&gm, 0, sizeof(gm));
2884     SetLastError(0xdeadbeef);
2885     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2886     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2887     {
2888        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
2889        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2890     }
2891
2892     /* test for needed buffer size request on space char */
2893     memset(&gm, 0, sizeof(gm));
2894     SetLastError(0xdeadbeef);
2895     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
2896     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2897         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
2898
2899     /* requesting buffer size for space char + error */
2900     memset(&gm, 0, sizeof(gm));
2901     SetLastError(0xdeadbeef);
2902     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
2903     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2904     {
2905        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
2906        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2907     }
2908
2909     SelectObject(hdc, old_hfont);
2910     DeleteObject(hfont);
2911     DeleteDC(hdc);
2912 }
2913
2914 /* bug #9995: there is a limit to the character width that can be specified */
2915 void test_GetTextMetrics2(  const char *fontname)
2916 {
2917     HFONT of, hf;
2918     HDC hdc;
2919     TEXTMETRICA tm;
2920     LOGFONTA lf;
2921     BOOL ret;
2922     int avecharw[3], maxcharw[3];
2923
2924     if (!is_truetype_font_installed( fontname)) {
2925         skip("%s is not installed\n", fontname);
2926         return;
2927     }
2928     hdc = CreateCompatibleDC(0);
2929     ok( hdc != NULL, "CreateCompatibleDC failed\n");
2930     /* select width = 0 */
2931     hf = CreateFontA( -11, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
2932             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
2933             DEFAULT_QUALITY, VARIABLE_PITCH,
2934             fontname);
2935     ok( hf != NULL, "CreateFontA failed\n");
2936     of = SelectObject( hdc, hf);
2937     ret = GetObjectA( hf, sizeof( lf), &lf);
2938     ret = GetTextMetricsA( hdc, &tm);
2939     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2940     avecharw[0] =tm.tmAveCharWidth;
2941     maxcharw[0] =tm.tmMaxCharWidth;
2942     SelectObject( hdc, of);
2943     DeleteObject( hf);
2944     /* select LARGE width = 1023 */
2945     hf = CreateFontA( -11, 1023, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
2946             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
2947             DEFAULT_QUALITY, VARIABLE_PITCH,
2948             fontname);
2949     ok( hf != NULL, "CreateFontA failed\n");
2950     of = SelectObject( hdc, hf);
2951     ret = GetObjectA( hf, sizeof( lf), &lf);
2952     ret = GetTextMetricsA( hdc, &tm);
2953     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2954     avecharw[1] =tm.tmAveCharWidth;
2955     maxcharw[1] =tm.tmMaxCharWidth;
2956     SelectObject( hdc, of);
2957     DeleteObject( hf);
2958     /* select TOOLARGE width = 1536 */
2959     hf = CreateFontA( -11, 1536, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
2960             DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES,
2961             DEFAULT_QUALITY, VARIABLE_PITCH,
2962             fontname);
2963     ok( hf != NULL, "CreateFontA failed\n");
2964     of = SelectObject( hdc, hf);
2965     ret = GetObjectA( hf, sizeof( lf), &lf);
2966     ret = GetTextMetricsA( hdc, &tm);
2967     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2968     avecharw[2] =tm.tmAveCharWidth;
2969     maxcharw[2] =tm.tmMaxCharWidth;
2970     SelectObject( hdc, of);
2971     DeleteObject( hf);
2972     /* tests */
2973     ok( avecharw[1] > 10 * avecharw[0], "Av. charwidth not large ( %d cmp.to %d)\n",
2974             avecharw[1], avecharw[0]);
2975     ok( maxcharw[1] > 10 * maxcharw[0], "Max charwidth not large ( %d cmp.to %d)\n",
2976             maxcharw[1], maxcharw[0]);
2977 todo_wine {
2978     ok( avecharw[2] ==  avecharw[0], "Unexpected Av. charwidth ( %d cmp.to %d)\n",
2979             avecharw[2], avecharw[0]);
2980     ok( maxcharw[2] ==  maxcharw[0], "Unexpected Max charwidth ( %d cmp.to %d)\n",
2981             maxcharw[2], maxcharw[0]);
2982 }
2983     /* clean up */
2984     DeleteDC(hdc);
2985 }
2986
2987 START_TEST(font)
2988 {
2989     init();
2990     test_logfont();
2991     test_bitmap_font();
2992     test_outline_font();
2993     test_bitmap_font_metrics();
2994     test_GdiGetCharDimensions();
2995     test_GetCharABCWidths();
2996     test_text_extents();
2997     test_GetGlyphIndices();
2998     test_GetKerningPairs();
2999     test_GetOutlineTextMetrics();
3000     test_SetTextJustification();
3001     test_font_charset();
3002     test_GetFontUnicodeRanges();
3003     test_nonexistent_font();
3004     test_orientation();
3005
3006     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
3007      * I'd like to avoid them in this test.
3008      */
3009     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
3010     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
3011     if (is_truetype_font_installed("Arial Black") &&
3012         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
3013     {
3014         test_EnumFontFamilies("", ANSI_CHARSET);
3015         test_EnumFontFamilies("", SYMBOL_CHARSET);
3016         test_EnumFontFamilies("", DEFAULT_CHARSET);
3017     }
3018     else
3019         skip("Arial Black or Symbol/Wingdings is not installed\n");
3020     test_GetTextMetrics();
3021     test_GdiRealizationInfo();
3022     test_GetTextFace();
3023     test_GetGlyphOutline();
3024     test_GetTextMetrics2( "Tahoma");
3025     test_GetTextMetrics2( "Arial");
3026 }