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