gdi32: Fix SetEnhMetaFileBits last error handling.
[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, "NULL family should enumerate RUSSIAN_CHARSET\n");
1789         }
1790
1791         efdw.total = 0;
1792         SetLastError(0xdeadbeef);
1793         ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
1794         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError());
1795         if(ret)
1796         {
1797             get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset);
1798             trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
1799                   ansi_charset, symbol_charset, russian_charset);
1800             ok(efdw.total > 0, "fonts enumerated: NULL\n");
1801             ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
1802             ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
1803             ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
1804         }
1805     }
1806
1807     efd.total = 0;
1808     SetLastError(0xdeadbeef);
1809     ret = EnumFontFamilies(hdc, font_name, arial_enum_proc, (LPARAM)&efd);
1810     ok(ret, "EnumFontFamilies error %u\n", GetLastError());
1811     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1812     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s\n",
1813           ansi_charset, symbol_charset, russian_charset,
1814           *font_name ? font_name : "<empty>");
1815     if (*font_name)
1816         ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1817     else
1818         ok(!efd.total, "no fonts should be enumerated for empty font_name\n");
1819     for (i = 0; i < efd.total; i++)
1820     {
1821 /* FIXME: remove completely once Wine is fixed */
1822 if (efd.lf[i].lfCharSet != font_charset)
1823 {
1824 todo_wine
1825     ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1826 }
1827 else
1828         ok(efd.lf[i].lfCharSet == font_charset, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1829         ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1830            font_name, efd.lf[i].lfFaceName);
1831     }
1832
1833     memset(&lf, 0, sizeof(lf));
1834     lf.lfCharSet = ANSI_CHARSET;
1835     lstrcpy(lf.lfFaceName, font_name);
1836     efd.total = 0;
1837     SetLastError(0xdeadbeef);
1838     ret = EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1839     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1840     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1841     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s ANSI_CHARSET\n",
1842           ansi_charset, symbol_charset, russian_charset,
1843           *font_name ? font_name : "<empty>");
1844     if (font_charset == SYMBOL_CHARSET)
1845     {
1846         if (*font_name)
1847             ok(efd.total == 0, "no fonts should be enumerated: %s ANSI_CHARSET\n", font_name);
1848         else
1849             ok(efd.total > 0, "no fonts enumerated: %s\n", font_name);
1850     }
1851     else
1852     {
1853         ok(efd.total > 0, "no fonts enumerated: %s ANSI_CHARSET\n", font_name);
1854         for (i = 0; i < efd.total; i++)
1855         {
1856             ok(efd.lf[i].lfCharSet == ANSI_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1857             if (*font_name)
1858                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1859                    font_name, efd.lf[i].lfFaceName);
1860         }
1861     }
1862
1863     /* DEFAULT_CHARSET should enumerate all available charsets */
1864     memset(&lf, 0, sizeof(lf));
1865     lf.lfCharSet = DEFAULT_CHARSET;
1866     lstrcpy(lf.lfFaceName, font_name);
1867     efd.total = 0;
1868     SetLastError(0xdeadbeef);
1869     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1870     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1871     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1872     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s DEFAULT_CHARSET\n",
1873           ansi_charset, symbol_charset, russian_charset,
1874           *font_name ? font_name : "<empty>");
1875     ok(efd.total > 0, "no fonts enumerated: %s DEFAULT_CHARSET\n", font_name);
1876     for (i = 0; i < efd.total; i++)
1877     {
1878         if (*font_name)
1879             ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1880                font_name, efd.lf[i].lfFaceName);
1881     }
1882     if (*font_name)
1883     {
1884         switch (font_charset)
1885         {
1886         case ANSI_CHARSET:
1887             ok(ansi_charset > 0,
1888                "ANSI_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1889             ok(!symbol_charset,
1890                "ANSI_CHARSET should NOT enumerate SYMBOL_CHARSET for %s\n", font_name);
1891             ok(russian_charset > 0,
1892                "ANSI_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1893             break;
1894         case SYMBOL_CHARSET:
1895             ok(!ansi_charset,
1896                "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", font_name);
1897             ok(symbol_charset,
1898                "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1899             ok(!russian_charset,
1900                "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", font_name);
1901             break;
1902         case DEFAULT_CHARSET:
1903             ok(ansi_charset > 0,
1904                "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", font_name);
1905             ok(symbol_charset > 0,
1906                "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", font_name);
1907             ok(russian_charset > 0,
1908                "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", font_name);
1909             break;
1910         }
1911     }
1912     else
1913     {
1914         ok(ansi_charset > 0,
1915            "DEFAULT_CHARSET should enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1916         ok(symbol_charset > 0,
1917            "DEFAULT_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1918         ok(russian_charset > 0,
1919            "DEFAULT_CHARSET should enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1920     }
1921
1922     memset(&lf, 0, sizeof(lf));
1923     lf.lfCharSet = SYMBOL_CHARSET;
1924     lstrcpy(lf.lfFaceName, font_name);
1925     efd.total = 0;
1926     SetLastError(0xdeadbeef);
1927     EnumFontFamiliesEx(hdc, &lf, arial_enum_proc, (LPARAM)&efd, 0);
1928     ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
1929     get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
1930     trace("enumerated ansi %d, symbol %d, russian %d fonts for %s SYMBOL_CHARSET\n",
1931           ansi_charset, symbol_charset, russian_charset,
1932           *font_name ? font_name : "<empty>");
1933     if (*font_name && font_charset == ANSI_CHARSET)
1934         ok(efd.total == 0, "no fonts should be enumerated: %s SYMBOL_CHARSET\n", font_name);
1935     else
1936     {
1937         ok(efd.total > 0, "no fonts enumerated: %s SYMBOL_CHARSET\n", font_name);
1938         for (i = 0; i < efd.total; i++)
1939         {
1940             ok(efd.lf[i].lfCharSet == SYMBOL_CHARSET, "%d: got charset %d\n", i, efd.lf[i].lfCharSet);
1941             if (*font_name)
1942                 ok(!lstrcmp(efd.lf[i].lfFaceName, font_name), "expected %s, got %s\n",
1943                    font_name, efd.lf[i].lfFaceName);
1944         }
1945
1946         ok(!ansi_charset,
1947            "SYMBOL_CHARSET should NOT enumerate ANSI_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1948         ok(symbol_charset > 0,
1949            "SYMBOL_CHARSET should enumerate SYMBOL_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1950         ok(!russian_charset,
1951            "SYMBOL_CHARSET should NOT enumerate RUSSIAN_CHARSET for %s\n", *font_name ? font_name : "<empty>");
1952     }
1953
1954     ReleaseDC(0, hdc);
1955 }
1956
1957 static void test_negative_width(HDC hdc, const LOGFONTA *lf)
1958 {
1959     HFONT hfont, hfont_prev;
1960     DWORD ret;
1961     GLYPHMETRICS gm1, gm2;
1962     LOGFONTA lf2 = *lf;
1963     WORD idx;
1964     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
1965
1966     if(!pGetGlyphIndicesA)
1967         return;
1968
1969     /* negative widths are handled just as positive ones */
1970     lf2.lfWidth = -lf->lfWidth;
1971
1972     SetLastError(0xdeadbeef);
1973     hfont = CreateFontIndirectA(lf);
1974     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
1975     check_font("original", lf, hfont);
1976
1977     hfont_prev = SelectObject(hdc, hfont);
1978
1979     ret = pGetGlyphIndicesA(hdc, "x", 1, &idx, GGI_MARK_NONEXISTING_GLYPHS);
1980     if (ret == GDI_ERROR || idx == 0xffff)
1981     {
1982         SelectObject(hdc, hfont_prev);
1983         DeleteObject(hfont);
1984         skip("Font %s doesn't contain 'x', skipping the test\n", lf->lfFaceName);
1985         return;
1986     }
1987
1988     /* filling with 0xaa causes false pass under WINEDEBUG=warn+heap */
1989     memset(&gm1, 0xab, sizeof(gm1));
1990     SetLastError(0xdeadbeef);
1991     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm1, 0, NULL, &mat);
1992     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
1993
1994     SelectObject(hdc, hfont_prev);
1995     DeleteObject(hfont);
1996
1997     SetLastError(0xdeadbeef);
1998     hfont = CreateFontIndirectA(&lf2);
1999     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2000     check_font("negative width", &lf2, hfont);
2001
2002     hfont_prev = SelectObject(hdc, hfont);
2003
2004     memset(&gm2, 0xbb, sizeof(gm2));
2005     SetLastError(0xdeadbeef);
2006     ret = GetGlyphOutlineA(hdc, 'x', GGO_METRICS, &gm2, 0, NULL, &mat);
2007     ok(ret != GDI_ERROR, "GetGlyphOutline error 0x%x\n", GetLastError());
2008
2009     SelectObject(hdc, hfont_prev);
2010     DeleteObject(hfont);
2011
2012     ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX &&
2013        gm1.gmBlackBoxY == gm2.gmBlackBoxY &&
2014        gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x &&
2015        gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y &&
2016        gm1.gmCellIncX == gm2.gmCellIncX &&
2017        gm1.gmCellIncY == gm2.gmCellIncY,
2018        "gm1=%d,%d,%d,%d,%d,%d gm2=%d,%d,%d,%d,%d,%d\n",
2019        gm1.gmBlackBoxX, gm1.gmBlackBoxY, gm1.gmptGlyphOrigin.x,
2020        gm1.gmptGlyphOrigin.y, gm1.gmCellIncX, gm1.gmCellIncY,
2021        gm2.gmBlackBoxX, gm2.gmBlackBoxY, gm2.gmptGlyphOrigin.x,
2022        gm2.gmptGlyphOrigin.y, gm2.gmCellIncX, gm2.gmCellIncY);
2023 }
2024
2025 /* PANOSE is 10 bytes in size, need to pack the structure properly */
2026 #include "pshpack2.h"
2027 typedef struct
2028 {
2029     USHORT version;
2030     SHORT xAvgCharWidth;
2031     USHORT usWeightClass;
2032     USHORT usWidthClass;
2033     SHORT fsType;
2034     SHORT ySubscriptXSize;
2035     SHORT ySubscriptYSize;
2036     SHORT ySubscriptXOffset;
2037     SHORT ySubscriptYOffset;
2038     SHORT ySuperscriptXSize;
2039     SHORT ySuperscriptYSize;
2040     SHORT ySuperscriptXOffset;
2041     SHORT ySuperscriptYOffset;
2042     SHORT yStrikeoutSize;
2043     SHORT yStrikeoutPosition;
2044     SHORT sFamilyClass;
2045     PANOSE panose;
2046     ULONG ulUnicodeRange1;
2047     ULONG ulUnicodeRange2;
2048     ULONG ulUnicodeRange3;
2049     ULONG ulUnicodeRange4;
2050     CHAR achVendID[4];
2051     USHORT fsSelection;
2052     USHORT usFirstCharIndex;
2053     USHORT usLastCharIndex;
2054     /* According to the Apple spec, original version didn't have the below fields,
2055      * version numbers were taked from the OpenType spec.
2056      */
2057     /* version 0 (TrueType 1.5) */
2058     USHORT sTypoAscender;
2059     USHORT sTypoDescender;
2060     USHORT sTypoLineGap;
2061     USHORT usWinAscent;
2062     USHORT usWinDescent;
2063     /* version 1 (TrueType 1.66) */
2064     ULONG ulCodePageRange1;
2065     ULONG ulCodePageRange2;
2066     /* version 2 (OpenType 1.2) */
2067     SHORT sxHeight;
2068     SHORT sCapHeight;
2069     USHORT usDefaultChar;
2070     USHORT usBreakChar;
2071     USHORT usMaxContext;
2072 } TT_OS2_V2;
2073 #include "poppack.h"
2074
2075 #ifdef WORDS_BIGENDIAN
2076 #define GET_BE_WORD(x) (x)
2077 #define GET_BE_DWORD(x) (x)
2078 #else
2079 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
2080 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
2081 #endif
2082
2083 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
2084                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
2085                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
2086 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
2087 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
2088
2089 typedef struct
2090 {
2091     USHORT version;
2092     USHORT num_tables;
2093 } cmap_header;
2094
2095 typedef struct
2096 {
2097     USHORT plat_id;
2098     USHORT enc_id;
2099     ULONG offset;
2100 } cmap_encoding_record;
2101
2102 typedef struct
2103 {
2104     USHORT format;
2105     USHORT length;
2106     USHORT language;
2107
2108     BYTE glyph_ids[256];
2109 } cmap_format_0;
2110
2111 typedef struct
2112 {
2113     USHORT format;
2114     USHORT length;
2115     USHORT language;
2116
2117     USHORT seg_countx2;
2118     USHORT search_range;
2119     USHORT entry_selector;
2120     USHORT range_shift;
2121
2122     USHORT end_count[1]; /* this is a variable-sized array of length seg_countx2 / 2 */
2123 /* Then follows:
2124     USHORT pad;
2125     USHORT start_count[seg_countx2 / 2];
2126     USHORT id_delta[seg_countx2 / 2];
2127     USHORT id_range_offset[seg_countx2 / 2];
2128     USHORT glyph_ids[];
2129 */
2130 } cmap_format_4;
2131
2132 typedef struct
2133 {
2134     USHORT end_count;
2135     USHORT start_count;
2136     USHORT id_delta;
2137     USHORT id_range_offset;
2138 } cmap_format_4_seg;
2139
2140 static void expect_ff(const TEXTMETRICA *tmA, const TT_OS2_V2 *os2, WORD family, const char *name)
2141 {
2142     ok((tmA->tmPitchAndFamily & 0xf0) == family, "%s: expected family %02x got %02x. panose %d-%d-%d-%d-...\n",
2143        name, family, tmA->tmPitchAndFamily, os2->panose.bFamilyType, os2->panose.bSerifStyle,
2144        os2->panose.bWeight, os2->panose.bProportion);
2145 }
2146
2147 static BOOL get_first_last_from_cmap0(void *ptr, DWORD *first, DWORD *last)
2148 {
2149     int i;
2150     cmap_format_0 *cmap = (cmap_format_0*)ptr;
2151
2152     *first = 256;
2153
2154     for(i = 0; i < 256; i++)
2155     {
2156         if(cmap->glyph_ids[i] == 0) continue;
2157         *last = i;
2158         if(*first == 256) *first = i;
2159     }
2160     if(*first == 256) return FALSE;
2161     return TRUE;
2162 }
2163
2164 static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg)
2165 {
2166     USHORT segs = GET_BE_WORD(cmap->seg_countx2) / 2;
2167     seg->end_count = GET_BE_WORD(cmap->end_count[seg_num]);
2168     seg->start_count = GET_BE_WORD(cmap->end_count[segs + 1 + seg_num]);
2169     seg->id_delta = GET_BE_WORD(cmap->end_count[2 * segs + 1 + seg_num]);
2170     seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]);
2171 }
2172
2173 static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last)
2174 {
2175     int i;
2176     cmap_format_4 *cmap = (cmap_format_4*)ptr;
2177     USHORT seg_count = GET_BE_WORD(cmap->seg_countx2) / 2;
2178     USHORT const *glyph_ids = cmap->end_count + 4 * seg_count + 1;
2179
2180     *first = 0x10000;
2181
2182     for(i = 0; i < seg_count; i++)
2183     {
2184         DWORD code, index;
2185         cmap_format_4_seg seg;
2186
2187         get_seg4(cmap, i, &seg);
2188         for(code = seg.start_count; code <= seg.end_count; code++)
2189         {
2190             if(seg.id_range_offset == 0)
2191                 index = (seg.id_delta + code) & 0xffff;
2192             else
2193             {
2194                 index = seg.id_range_offset / 2
2195                     + code - seg.start_count
2196                     + i - seg_count;
2197
2198                 index = GET_BE_WORD(glyph_ids[index]);
2199                 if(index) index += seg.id_delta;
2200             }
2201             if(*first == 0x10000)
2202                 *last = *first = code;
2203             else if(index)
2204                 *last = code;
2205         }
2206     }
2207
2208     if(*first == 0x10000) return FALSE;
2209     return TRUE;
2210 }
2211
2212 static void *get_cmap(cmap_header *header, USHORT plat_id, USHORT enc_id)
2213 {
2214     USHORT i;
2215     cmap_encoding_record *record = (cmap_encoding_record *)(header + 1);
2216
2217     for(i = 0; i < GET_BE_WORD(header->num_tables); i++)
2218     {
2219         if(GET_BE_WORD(record->plat_id) == plat_id && GET_BE_WORD(record->enc_id) == enc_id)
2220             return (BYTE *)header + GET_BE_DWORD(record->offset);
2221         record++;
2222     }
2223     return NULL;
2224 }
2225
2226 typedef enum
2227 {
2228     cmap_none,
2229     cmap_ms_unicode,
2230     cmap_ms_symbol
2231 } cmap_type;
2232
2233 static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_type *cmap_type)
2234 {
2235     LONG size, ret;
2236     cmap_header *header;
2237     void *cmap;
2238     BOOL r = FALSE;
2239     WORD format;
2240
2241     size = GetFontData(hdc, MS_CMAP_TAG, 0, NULL, 0);
2242     ok(size != GDI_ERROR, "no cmap table found\n");
2243     if(size == GDI_ERROR) return FALSE;
2244
2245     header = HeapAlloc(GetProcessHeap(), 0, size);
2246     ret = GetFontData(hdc, MS_CMAP_TAG, 0, header, size);
2247     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2248     ok(GET_BE_WORD(header->version) == 0, "got cmap version %d\n", GET_BE_WORD(header->version));
2249
2250     cmap = get_cmap(header, 3, 1);
2251     if(cmap)
2252         *cmap_type = cmap_ms_unicode;
2253     else
2254     {
2255         cmap = get_cmap(header, 3, 0);
2256         if(cmap) *cmap_type = cmap_ms_symbol;
2257     }
2258     if(!cmap)
2259     {
2260         *cmap_type = cmap_none;
2261         goto end;
2262     }
2263
2264     format = GET_BE_WORD(*(WORD *)cmap);
2265     switch(format)
2266     {
2267     case 0:
2268         r = get_first_last_from_cmap0(cmap, first, last);
2269         break;
2270     case 4:
2271         r = get_first_last_from_cmap4(cmap, first, last);
2272         break;
2273     default:
2274         trace("unhandled cmap format %d\n", format);
2275         break;
2276     }
2277
2278 end:
2279     HeapFree(GetProcessHeap(), 0, header);
2280     return r;
2281 }
2282
2283 static void test_text_metrics(const LOGFONTA *lf)
2284 {
2285     HDC hdc;
2286     HFONT hfont, hfont_old;
2287     TEXTMETRICA tmA;
2288     TT_OS2_V2 tt_os2;
2289     LONG size, ret;
2290     const char *font_name = lf->lfFaceName;
2291     DWORD cmap_first = 0, cmap_last = 0;
2292     cmap_type cmap_type;
2293
2294     hdc = GetDC(0);
2295
2296     SetLastError(0xdeadbeef);
2297     hfont = CreateFontIndirectA(lf);
2298     ok(hfont != 0, "CreateFontIndirect error %u\n", GetLastError());
2299
2300     hfont_old = SelectObject(hdc, hfont);
2301
2302     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
2303     if (size == GDI_ERROR)
2304     {
2305         trace("OS/2 chunk was not found\n");
2306         goto end_of_test;
2307     }
2308     if (size > sizeof(tt_os2))
2309     {
2310         trace("got too large OS/2 chunk of size %u\n", size);
2311         size = sizeof(tt_os2);
2312     }
2313
2314     memset(&tt_os2, 0, sizeof(tt_os2));
2315     ret = GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size);
2316     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
2317
2318     SetLastError(0xdeadbeef);
2319     ret = GetTextMetricsA(hdc, &tmA);
2320     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
2321
2322     if(!get_first_last_from_cmap(hdc, &cmap_first, &cmap_last, &cmap_type))
2323     {
2324         skip("Unable to retrieve first and last glyphs from cmap\n");
2325     }
2326     else
2327     {
2328         USHORT expect_first_A, expect_last_A, expect_break_A, expect_default_A;
2329         USHORT expect_first_W, expect_last_W, expect_break_W, expect_default_W;
2330         UINT os2_first_char, os2_last_char, default_char, break_char;
2331         USHORT version;
2332         TEXTMETRICW tmW;
2333
2334         version = GET_BE_WORD(tt_os2.version);
2335
2336         os2_first_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
2337         os2_last_char = GET_BE_WORD(tt_os2.usLastCharIndex);
2338         default_char = GET_BE_WORD(tt_os2.usDefaultChar);
2339         break_char = GET_BE_WORD(tt_os2.usBreakChar);
2340
2341         trace("font %s charset %u: %x-%x (%x-%x) default %x break %x OS/2 version %u vendor %4.4s\n",
2342               font_name, lf->lfCharSet, os2_first_char, os2_last_char, cmap_first, cmap_last,
2343               default_char, break_char, version, (LPCSTR)&tt_os2.achVendID);
2344
2345         if (cmap_type == cmap_ms_symbol || (cmap_first >= 0xf000 && cmap_first < 0xf100))
2346         {
2347             expect_first_W    = 0;
2348             switch(GetACP())
2349             {
2350             case 1257:  /* Baltic */
2351                 expect_last_W = 0xf8fd;
2352                 break;
2353             default:
2354                 expect_last_W = 0xf0ff;
2355             }
2356             expect_break_W    = 0x20;
2357             expect_default_W  = expect_break_W - 1;
2358             expect_first_A    = 0x1e;
2359             expect_last_A     = min(os2_last_char - os2_first_char + 0x20, 0xff);
2360         }
2361         else
2362         {
2363             expect_first_W    = cmap_first;
2364             expect_last_W     = min(cmap_last, os2_last_char);
2365             if(os2_first_char <= 1)
2366                 expect_break_W = os2_first_char + 2;
2367             else if(os2_first_char > 0xff)
2368                 expect_break_W = 0x20;
2369             else
2370                 expect_break_W = os2_first_char;
2371             expect_default_W  = expect_break_W - 1;
2372             expect_first_A    = expect_default_W - 1;
2373             expect_last_A     = min(expect_last_W, 0xff);
2374         }
2375         expect_break_A    = expect_break_W;
2376         expect_default_A  = expect_default_W;
2377
2378         /* Wine currently uses SYMBOL_CHARSET to identify whether the ANSI metrics need special handling */
2379         if(cmap_type != cmap_ms_symbol && tmA.tmCharSet == SYMBOL_CHARSET && expect_first_A != 0x1e)
2380             todo_wine ok(tmA.tmFirstChar == expect_first_A ||
2381                          tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2382                          "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2383         else
2384             ok(tmA.tmFirstChar == expect_first_A ||
2385                tmA.tmFirstChar == expect_first_A + 1 /* win9x */,
2386                "A: tmFirstChar for %s got %02x expected %02x\n", font_name, tmA.tmFirstChar, expect_first_A);
2387         ok(tmA.tmLastChar == expect_last_A ||
2388            tmA.tmLastChar == 0xff /* win9x */,
2389            "A: tmLastChar for %s got %02x expected %02x\n", font_name, tmA.tmLastChar, expect_last_A);
2390         ok(tmA.tmBreakChar == expect_break_A, "A: tmBreakChar for %s got %02x expected %02x\n",
2391            font_name, tmA.tmBreakChar, expect_break_A);
2392         ok(tmA.tmDefaultChar == expect_default_A, "A: tmDefaultChar for %s got %02x expected %02x\n",
2393            font_name, tmA.tmDefaultChar, expect_default_A);
2394
2395
2396         SetLastError(0xdeadbeef);
2397         ret = GetTextMetricsW(hdc, &tmW);
2398         ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2399            "GetTextMetricsW error %u\n", GetLastError());
2400         if (ret)
2401         {
2402             /* Wine uses the os2 first char */
2403             if(cmap_first != os2_first_char && cmap_type != cmap_ms_symbol)
2404                 todo_wine ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2405                              font_name, tmW.tmFirstChar, expect_first_W);
2406             else
2407                 ok(tmW.tmFirstChar == expect_first_W, "W: tmFirstChar for %s got %02x expected %02x\n",
2408                    font_name, tmW.tmFirstChar, expect_first_W);
2409
2410             /* Wine uses the os2 last char */
2411             if(expect_last_W != os2_last_char && cmap_type != cmap_ms_symbol)
2412                 todo_wine ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2413                              font_name, tmW.tmLastChar, expect_last_W);
2414             else
2415                 ok(tmW.tmLastChar == expect_last_W, "W: tmLastChar for %s got %02x expected %02x\n",
2416                    font_name, tmW.tmLastChar, expect_last_W);
2417             ok(tmW.tmBreakChar == expect_break_W, "W: tmBreakChar for %s got %02x expected %02x\n",
2418                font_name, tmW.tmBreakChar, expect_break_W);
2419             ok(tmW.tmDefaultChar == expect_default_W, "W: tmDefaultChar for %s got %02x expected %02x\n",
2420                font_name, tmW.tmDefaultChar, expect_default_W);
2421
2422             /* Test the aspect ratio while we have tmW */
2423             ret = GetDeviceCaps(hdc, LOGPIXELSX);
2424             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectX %u != %u\n",
2425                tmW.tmDigitizedAspectX, ret);
2426             ret = GetDeviceCaps(hdc, LOGPIXELSY);
2427             ok(tmW.tmDigitizedAspectX == ret, "W: tmDigitizedAspectY %u != %u\n",
2428                tmW.tmDigitizedAspectX, ret);
2429         }
2430     }
2431
2432     /* test FF_ values */
2433     switch(tt_os2.panose.bFamilyType)
2434     {
2435     case PAN_ANY:
2436     case PAN_NO_FIT:
2437     case PAN_FAMILY_TEXT_DISPLAY:
2438     case PAN_FAMILY_PICTORIAL:
2439     default:
2440         if((tmA.tmPitchAndFamily & 1) == 0 || /* fixed */
2441            tt_os2.panose.bProportion == PAN_PROP_MONOSPACED)
2442         {
2443             expect_ff(&tmA, &tt_os2, FF_MODERN, font_name);
2444             break;
2445         }
2446         switch(tt_os2.panose.bSerifStyle)
2447         {
2448         case PAN_ANY:
2449         case PAN_NO_FIT:
2450         default:
2451             expect_ff(&tmA, &tt_os2, FF_DONTCARE, font_name);
2452             break;
2453
2454         case PAN_SERIF_COVE:
2455         case PAN_SERIF_OBTUSE_COVE:
2456         case PAN_SERIF_SQUARE_COVE:
2457         case PAN_SERIF_OBTUSE_SQUARE_COVE:
2458         case PAN_SERIF_SQUARE:
2459         case PAN_SERIF_THIN:
2460         case PAN_SERIF_BONE:
2461         case PAN_SERIF_EXAGGERATED:
2462         case PAN_SERIF_TRIANGLE:
2463             expect_ff(&tmA, &tt_os2, FF_ROMAN, font_name);
2464             break;
2465
2466         case PAN_SERIF_NORMAL_SANS:
2467         case PAN_SERIF_OBTUSE_SANS:
2468         case PAN_SERIF_PERP_SANS:
2469         case PAN_SERIF_FLARED:
2470         case PAN_SERIF_ROUNDED:
2471             expect_ff(&tmA, &tt_os2, FF_SWISS, font_name);
2472             break;
2473         }
2474         break;
2475
2476     case PAN_FAMILY_SCRIPT:
2477         expect_ff(&tmA, &tt_os2, FF_SCRIPT, font_name);
2478         break;
2479
2480     case PAN_FAMILY_DECORATIVE:
2481         expect_ff(&tmA, &tt_os2, FF_DECORATIVE, font_name);
2482         break;
2483     }
2484
2485     test_negative_width(hdc, lf);
2486
2487 end_of_test:
2488     SelectObject(hdc, hfont_old);
2489     DeleteObject(hfont);
2490
2491     ReleaseDC(0, hdc);
2492 }
2493
2494 static INT CALLBACK enum_truetype_font_proc(const LOGFONT *lf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
2495 {
2496     INT *enumed = (INT *)lParam;
2497
2498     if (type == TRUETYPE_FONTTYPE)
2499     {
2500         (*enumed)++;
2501         test_text_metrics(lf);
2502     }
2503     return 1;
2504 }
2505
2506 static void test_GetTextMetrics(void)
2507 {
2508     LOGFONTA lf;
2509     HDC hdc;
2510     INT enumed;
2511
2512     /* Report only once */
2513     if(!pGetGlyphIndicesA)
2514         win_skip("GetGlyphIndicesA is unavailable, negative width will not be checked\n");
2515
2516     hdc = GetDC(0);
2517
2518     memset(&lf, 0, sizeof(lf));
2519     lf.lfCharSet = DEFAULT_CHARSET;
2520     enumed = 0;
2521     EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
2522     trace("Tested metrics of %d truetype fonts\n", enumed);
2523
2524     ReleaseDC(0, hdc);
2525 }
2526
2527 static void test_nonexistent_font(void)
2528 {
2529     static const struct
2530     {
2531         const char *name;
2532         int charset;
2533     } font_subst[] =
2534     {
2535         { "Times New Roman Baltic", 186 },
2536         { "Times New Roman CE", 238 },
2537         { "Times New Roman CYR", 204 },
2538         { "Times New Roman Greek", 161 },
2539         { "Times New Roman TUR", 162 }
2540     };
2541     LOGFONTA lf;
2542     HDC hdc;
2543     HFONT hfont;
2544     CHARSETINFO csi;
2545     INT cs, expected_cs, i;
2546     char buf[LF_FACESIZE];
2547
2548     if (!is_truetype_font_installed("Arial") ||
2549         !is_truetype_font_installed("Times New Roman"))
2550     {
2551         skip("Arial or Times New Roman not installed\n");
2552         return;
2553     }
2554
2555     expected_cs = GetACP();
2556     if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
2557     {
2558         skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
2559         return;
2560     }
2561     expected_cs = csi.ciCharset;
2562     trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
2563
2564     hdc = GetDC(0);
2565
2566     memset(&lf, 0, sizeof(lf));
2567     lf.lfHeight = 100;
2568     lf.lfWeight = FW_REGULAR;
2569     lf.lfCharSet = ANSI_CHARSET;
2570     lf.lfPitchAndFamily = FF_SWISS;
2571     strcpy(lf.lfFaceName, "Nonexistent font");
2572     hfont = CreateFontIndirectA(&lf);
2573     hfont = SelectObject(hdc, hfont);
2574     GetTextFaceA(hdc, sizeof(buf), buf);
2575     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
2576     cs = GetTextCharset(hdc);
2577     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2578     DeleteObject(SelectObject(hdc, hfont));
2579
2580     memset(&lf, 0, sizeof(lf));
2581     lf.lfHeight = -13;
2582     lf.lfWeight = FW_DONTCARE;
2583     strcpy(lf.lfFaceName, "Nonexistent font");
2584     hfont = CreateFontIndirectA(&lf);
2585     hfont = SelectObject(hdc, hfont);
2586     GetTextFaceA(hdc, sizeof(buf), buf);
2587 todo_wine /* Wine uses Arial for all substitutions */
2588     ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
2589        !lstrcmpiA(buf, "MS Serif") || /* Win9x */
2590        !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2591        "Got %s\n", buf);
2592     cs = GetTextCharset(hdc);
2593     ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
2594     DeleteObject(SelectObject(hdc, hfont));
2595
2596     memset(&lf, 0, sizeof(lf));
2597     lf.lfHeight = -13;
2598     lf.lfWeight = FW_REGULAR;
2599     strcpy(lf.lfFaceName, "Nonexistent font");
2600     hfont = CreateFontIndirectA(&lf);
2601     hfont = SelectObject(hdc, hfont);
2602     GetTextFaceA(hdc, sizeof(buf), buf);
2603     ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2604        !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf);
2605     cs = GetTextCharset(hdc);
2606     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2607     DeleteObject(SelectObject(hdc, hfont));
2608
2609     memset(&lf, 0, sizeof(lf));
2610     lf.lfHeight = -13;
2611     lf.lfWeight = FW_DONTCARE;
2612     strcpy(lf.lfFaceName, "Times New Roman");
2613     hfont = CreateFontIndirectA(&lf);
2614     hfont = SelectObject(hdc, hfont);
2615     GetTextFaceA(hdc, sizeof(buf), buf);
2616     ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
2617     cs = GetTextCharset(hdc);
2618     ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
2619     DeleteObject(SelectObject(hdc, hfont));
2620
2621     for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
2622     {
2623         memset(&lf, 0, sizeof(lf));
2624         lf.lfHeight = -13;
2625         lf.lfWeight = FW_REGULAR;
2626         strcpy(lf.lfFaceName, font_subst[i].name);
2627         hfont = CreateFontIndirectA(&lf);
2628         hfont = SelectObject(hdc, hfont);
2629         cs = GetTextCharset(hdc);
2630         if (font_subst[i].charset == expected_cs)
2631         {
2632             ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2633             GetTextFaceA(hdc, sizeof(buf), buf);
2634             ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf);
2635         }
2636         else
2637         {
2638             ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d for font %s\n", cs, font_subst[i].name);
2639             GetTextFaceA(hdc, sizeof(buf), buf);
2640             ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
2641                !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s for font %s\n", buf, font_subst[i].name);
2642         }
2643         DeleteObject(SelectObject(hdc, hfont));
2644
2645         memset(&lf, 0, sizeof(lf));
2646         lf.lfHeight = -13;
2647         lf.lfWeight = FW_DONTCARE;
2648         strcpy(lf.lfFaceName, font_subst[i].name);
2649         hfont = CreateFontIndirectA(&lf);
2650         hfont = SelectObject(hdc, hfont);
2651         GetTextFaceA(hdc, sizeof(buf), buf);
2652         ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
2653            !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
2654            !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
2655            !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
2656            "got %s for font %s\n", buf, font_subst[i].name);
2657         cs = GetTextCharset(hdc);
2658         ok(cs == expected_cs, "expected %d, got %d for font %s\n", expected_cs, cs, font_subst[i].name);
2659         DeleteObject(SelectObject(hdc, hfont));
2660     }
2661
2662     ReleaseDC(0, hdc);
2663 }
2664
2665 static void test_GdiRealizationInfo(void)
2666 {
2667     HDC hdc;
2668     DWORD info[4];
2669     BOOL r;
2670     HFONT hfont, hfont_old;
2671     LOGFONTA lf;
2672
2673     if(!pGdiRealizationInfo)
2674     {
2675         win_skip("GdiRealizationInfo not available\n");
2676         return;
2677     }
2678
2679     hdc = GetDC(0);
2680
2681     memset(info, 0xcc, sizeof(info));
2682     r = pGdiRealizationInfo(hdc, info);
2683     ok(r != 0, "ret 0\n");
2684     ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]);
2685     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2686
2687     if (!is_truetype_font_installed("Arial"))
2688     {
2689         skip("skipping GdiRealizationInfo with truetype font\n");
2690         goto end;
2691     }
2692
2693     memset(&lf, 0, sizeof(lf));
2694     strcpy(lf.lfFaceName, "Arial");
2695     lf.lfHeight = 20;
2696     lf.lfWeight = FW_NORMAL;
2697     hfont = CreateFontIndirectA(&lf);
2698     hfont_old = SelectObject(hdc, hfont);
2699
2700     memset(info, 0xcc, sizeof(info));
2701     r = pGdiRealizationInfo(hdc, info);
2702     ok(r != 0, "ret 0\n");
2703     ok((info[0] & 0xf) == 3, "info[0] = %x for arial\n", info[0]);
2704     ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n");
2705
2706     DeleteObject(SelectObject(hdc, hfont_old));
2707
2708  end:
2709     ReleaseDC(0, hdc);
2710 }
2711
2712 /* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
2713    the nul in the count of characters copied when the face name buffer is not
2714    NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
2715    always includes it.  */
2716 static void test_GetTextFace(void)
2717 {
2718     static const char faceA[] = "Tahoma";
2719     static const WCHAR faceW[] = {'T','a','h','o','m','a', 0};
2720     LOGFONTA fA = {0};
2721     LOGFONTW fW = {0};
2722     char bufA[LF_FACESIZE];
2723     WCHAR bufW[LF_FACESIZE];
2724     HFONT f, g;
2725     HDC dc;
2726     int n;
2727
2728     if(!is_font_installed("Tahoma"))
2729     {
2730         skip("Tahoma is not installed so skipping this test\n");
2731         return;
2732     }
2733
2734     /* 'A' case.  */
2735     memcpy(fA.lfFaceName, faceA, sizeof faceA);
2736     f = CreateFontIndirectA(&fA);
2737     ok(f != NULL, "CreateFontIndirectA failed\n");
2738
2739     dc = GetDC(NULL);
2740     g = SelectObject(dc, f);
2741     n = GetTextFaceA(dc, sizeof bufA, bufA);
2742     ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
2743     ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
2744
2745     /* Play with the count arg.  */
2746     bufA[0] = 'x';
2747     n = GetTextFaceA(dc, 0, bufA);
2748     ok(n == 0, "GetTextFaceA returned %d\n", n);
2749     ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2750
2751     bufA[0] = 'x';
2752     n = GetTextFaceA(dc, 1, bufA);
2753     ok(n == 0, "GetTextFaceA returned %d\n", n);
2754     ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
2755
2756     bufA[0] = 'x'; bufA[1] = 'y';
2757     n = GetTextFaceA(dc, 2, bufA);
2758     ok(n == 1, "GetTextFaceA returned %d\n", n);
2759     ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n");
2760
2761     n = GetTextFaceA(dc, 0, NULL);
2762     ok(n == sizeof faceA ||
2763        broken(n == 0), /* win98, winMe */
2764        "GetTextFaceA returned %d\n", n);
2765
2766     DeleteObject(SelectObject(dc, g));
2767     ReleaseDC(NULL, dc);
2768
2769     /* 'W' case.  */
2770     memcpy(fW.lfFaceName, faceW, sizeof faceW);
2771     SetLastError(0xdeadbeef);
2772     f = CreateFontIndirectW(&fW);
2773     if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2774     {
2775         win_skip("CreateFontIndirectW is not implemented\n");
2776         return;
2777     }
2778     ok(f != NULL, "CreateFontIndirectW failed\n");
2779
2780     dc = GetDC(NULL);
2781     g = SelectObject(dc, f);
2782     n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
2783     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2784     ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
2785
2786     /* Play with the count arg.  */
2787     bufW[0] = 'x';
2788     n = GetTextFaceW(dc, 0, bufW);
2789     ok(n == 0, "GetTextFaceW returned %d\n", n);
2790     ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2791
2792     bufW[0] = 'x';
2793     n = GetTextFaceW(dc, 1, bufW);
2794     ok(n == 1, "GetTextFaceW returned %d\n", n);
2795     ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
2796
2797     bufW[0] = 'x'; bufW[1] = 'y';
2798     n = GetTextFaceW(dc, 2, bufW);
2799     ok(n == 2, "GetTextFaceW returned %d\n", n);
2800     ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
2801
2802     n = GetTextFaceW(dc, 0, NULL);
2803     ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
2804
2805     DeleteObject(SelectObject(dc, g));
2806     ReleaseDC(NULL, dc);
2807 }
2808
2809 static void test_orientation(void)
2810 {
2811     static const char test_str[11] = "Test String";
2812     HDC hdc;
2813     LOGFONTA lf;
2814     HFONT hfont, old_hfont;
2815     SIZE size;
2816
2817     if (!is_truetype_font_installed("Arial"))
2818     {
2819         skip("Arial is not installed\n");
2820         return;
2821     }
2822
2823     hdc = CreateCompatibleDC(0);
2824     memset(&lf, 0, sizeof(lf));
2825     lstrcpyA(lf.lfFaceName, "Arial");
2826     lf.lfHeight = 72;
2827     lf.lfOrientation = lf.lfEscapement = 900;
2828     hfont = create_font("orientation", &lf);
2829     old_hfont = SelectObject(hdc, hfont);
2830     ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n");
2831     ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
2832     ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
2833     SelectObject(hdc, old_hfont);
2834     DeleteObject(hfont);
2835     DeleteDC(hdc);
2836 }
2837
2838 static void test_GetGlyphOutline(void)
2839 {
2840     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
2841     HDC hdc;
2842     GLYPHMETRICS gm;
2843     LOGFONTA lf;
2844     HFONT hfont, old_hfont;
2845     INT ret;
2846
2847     if (!is_truetype_font_installed("Tahoma"))
2848     {
2849         skip("Tahoma is not installed\n");
2850         return;
2851     }
2852
2853     hdc = CreateCompatibleDC(0);
2854     memset(&lf, 0, sizeof(lf));
2855     lf.lfHeight = 72;
2856     lstrcpyA(lf.lfFaceName, "Tahoma");
2857     SetLastError(0xdeadbeef);
2858     hfont = CreateFontIndirectA(&lf);
2859     ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
2860     old_hfont = SelectObject(hdc, hfont);
2861
2862     memset(&gm, 0, sizeof(gm));
2863     SetLastError(0xdeadbeef);
2864     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2865     ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
2866
2867     memset(&gm, 0, sizeof(gm));
2868     SetLastError(0xdeadbeef);
2869     ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2870     ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n");
2871     ok(GetLastError() == 0xdeadbeef ||
2872        GetLastError() == ERROR_INVALID_PARAMETER, /* win98, winMe */
2873        "expected 0xdeadbeef, got %u\n", GetLastError());
2874
2875     memset(&gm, 0, sizeof(gm));
2876     SetLastError(0xdeadbeef);
2877     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
2878     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2879         ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError());
2880
2881     memset(&gm, 0, sizeof(gm));
2882     SetLastError(0xdeadbeef);
2883     ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL);
2884     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2885     {
2886        ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n");
2887        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2888     }
2889
2890     /* test for needed buffer size request on space char */
2891     memset(&gm, 0, sizeof(gm));
2892     SetLastError(0xdeadbeef);
2893     ret = GetGlyphOutlineW(hdc, ' ', GGO_NATIVE, &gm, 0, NULL, &mat);
2894     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2895         ok(ret == 0, "GetGlyphOutlineW should return 0 buffer size for space char\n");
2896
2897     /* requesting buffer size for space char + error */
2898     memset(&gm, 0, sizeof(gm));
2899     SetLastError(0xdeadbeef);
2900     ret = GetGlyphOutlineW(0, ' ', GGO_NATIVE, &gm, 0, NULL, NULL);
2901     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
2902     {
2903        ok(ret == GDI_ERROR, "GetGlyphOutlineW should return GDI_ERROR\n");
2904        ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
2905     }
2906
2907     SelectObject(hdc, old_hfont);
2908     DeleteObject(hfont);
2909     DeleteDC(hdc);
2910 }
2911
2912 START_TEST(font)
2913 {
2914     init();
2915
2916     test_logfont();
2917     test_bitmap_font();
2918     test_outline_font();
2919     test_bitmap_font_metrics();
2920     test_GdiGetCharDimensions();
2921     test_GetCharABCWidths();
2922     test_text_extents();
2923     test_GetGlyphIndices();
2924     test_GetKerningPairs();
2925     test_GetOutlineTextMetrics();
2926     test_SetTextJustification();
2927     test_font_charset();
2928     test_GetFontUnicodeRanges();
2929     test_nonexistent_font();
2930     test_orientation();
2931
2932     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
2933      * I'd like to avoid them in this test.
2934      */
2935     test_EnumFontFamilies("Arial Black", ANSI_CHARSET);
2936     test_EnumFontFamilies("Symbol", SYMBOL_CHARSET);
2937     if (is_truetype_font_installed("Arial Black") &&
2938         (is_truetype_font_installed("Symbol") || is_truetype_font_installed("Wingdings")))
2939     {
2940         test_EnumFontFamilies("", ANSI_CHARSET);
2941         test_EnumFontFamilies("", SYMBOL_CHARSET);
2942         test_EnumFontFamilies("", DEFAULT_CHARSET);
2943     }
2944     else
2945         skip("Arial Black or Symbol/Wingdings is not installed\n");
2946     test_GetTextMetrics();
2947     test_GdiRealizationInfo();
2948     test_GetTextFace();
2949     test_GetGlyphOutline();
2950 }